core: convert PID 1 to libsystemd-bus

This patch converts PID 1 to libsystemd-bus and thus drops the
dependency on libdbus. The only remaining code using libdbus is a test
case that validates our bus marshalling against libdbus' marshalling,
and this dependency can be turned off.

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

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

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

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

As a side effect we will now generate PropertiesChanged messages which
carry property contents, rather than just invalidation information.
This commit is contained in:
Lennart Poettering 2013-11-19 21:12:59 +01:00
parent 3febea3a0b
commit 718db96199
106 changed files with 6593 additions and 9683 deletions

View File

@ -662,16 +662,19 @@ libsystemd_shared_la_SOURCES = \
src/shared/linux/fanotify.h \
src/shared/linux/seccomp.h \
src/shared/linux/seccomp-bpf.h \
src/shared/ioprio.h \
src/shared/missing.h \
src/shared/list.h \
src/shared/macro.h \
src/shared/def.h \
src/shared/sparse-endian.h \
src/shared/refcnt.h \
src/shared/udev-util.h \
src/shared/bus-errors.h \
src/shared/device-nodes.c \
src/shared/device-nodes.h \
src/shared/sparse-endian.h \
src/shared/util.c \
src/shared/util.h \
src/shared/udev-util.h \
src/shared/virt.c \
src/shared/virt.h \
src/shared/efivars.c \
@ -712,7 +715,6 @@ libsystemd_shared_la_SOURCES = \
src/shared/gunicode.h \
src/shared/pager.c \
src/shared/pager.h \
src/shared/ioprio.h \
src/shared/socket-util.c \
src/shared/socket-util.h \
src/shared/conf-files.c \
@ -748,7 +750,6 @@ libsystemd_shared_la_SOURCES = \
src/shared/acpi-fpdt.c \
src/shared/boot-timestamps.h \
src/shared/boot-timestamps.c \
src/shared/refcnt.h \
src/shared/mkdir.c \
src/shared/mkdir.h \
src/shared/smack-util.c \
@ -762,21 +763,6 @@ libsystemd_shared_la_SOURCES = \
src/shared/net-util.c \
src/shared/net-util.h
#-------------------------------------------------------------------------------
noinst_LTLIBRARIES += \
libsystemd-dbus.la
libsystemd_dbus_la_SOURCES = \
src/shared/dbus-common.c \
src/shared/dbus-common.h
libsystemd_dbus_la_CFLAGS = \
$(AM_CFLAGS) \
$(DBUS_CFLAGS)
libsystemd_dbus_la_LIBADD = \
$(DBUS_LIBS)
# ------------------------------------------------------------------------------
noinst_LTLIBRARIES += \
libsystemd-units.la
@ -792,8 +778,7 @@ libsystemd_units_la_SOURCES = \
src/shared/specifier.h
libsystemd_units_la_CFLAGS = \
$(AM_CFLAGS) \
$(DBUS_CFLAGS)
$(AM_CFLAGS)
# ------------------------------------------------------------------------------
noinst_LTLIBRARIES += \
@ -953,6 +938,8 @@ libsystemd_core_la_SOURCES = \
src/core/dbus-kill.h \
src/core/dbus-cgroup.c \
src/core/dbus-cgroup.h \
src/core/dbus-client-track.c \
src/core/dbus-client-track.h \
src/core/cgroup.c \
src/core/cgroup.h \
src/core/selinux-access.c \
@ -982,7 +969,6 @@ libsystemd_core_la_SOURCES = \
src/core/securebits.h \
src/core/initreq.h \
src/core/special.h \
src/core/bus-errors.h \
src/core/build.h \
src/core/sysfs-show.h \
src/core/switch-root.h \
@ -1010,7 +996,6 @@ nodist_libsystemd_core_la_SOURCES = \
libsystemd_core_la_CFLAGS = \
$(AM_CFLAGS) \
$(DBUS_CFLAGS) \
$(LIBWRAP_CFLAGS) \
$(PAM_CFLAGS) \
$(AUDIT_CFLAGS) \
@ -1021,13 +1006,13 @@ libsystemd_core_la_LIBADD = \
libsystemd-capability.la \
libsystemd-units.la \
libsystemd-label.la \
libsystemd-dbus.la \
libsystemd-audit.la \
libsystemd-id128-internal.la \
libsystemd-daemon-internal.la \
libudev-internal.la \
libsystemd-shared.la \
libsystemd-rtnl.la \
libsystemd-bus-internal.la \
$(LIBWRAP_LIBS) \
$(PAM_LIBS) \
$(AUDIT_LIBS) \
@ -1072,10 +1057,6 @@ src/core/syscall-to-name.h: src/core/syscall-list.txt Makefile
systemd_SOURCES = \
src/core/main.c
systemd_CFLAGS = \
$(AM_CFLAGS) \
$(DBUS_CFLAGS)
systemd_LDADD = \
libsystemd-core.la \
$(RT_LIBS)
@ -1166,10 +1147,6 @@ test_device_nodes_LDADD = \
test_engine_SOURCES = \
src/test/test-engine.c
test_engine_CFLAGS = \
$(AM_CFLAGS) \
$(DBUS_CFLAGS)
test_engine_LDADD = \
libsystemd-core.la \
$(RT_LIBS)
@ -1177,10 +1154,6 @@ test_engine_LDADD = \
test_job_type_SOURCES = \
src/test/test-job-type.c
test_job_type_CFLAGS = \
$(AM_CFLAGS) \
$(DBUS_CFLAGS)
test_job_type_LDADD = \
libsystemd-core.la \
$(RT_LIBS)
@ -1191,10 +1164,6 @@ test_ns_SOURCES = \
test_ns_LDADD = \
libsystemd-core.la
test_ns_CFLAGS = \
$(AM_CFLAGS) \
$(DBUS_CFLAGS)
test_loopback_SOURCES = \
src/test/test-loopback.c
@ -1221,10 +1190,6 @@ endif
test_unit_name_SOURCES = \
src/test/test-unit-name.c
test_unit_name_CFLAGS = \
$(AM_CFLAGS) \
$(DBUS_CFLAGS)
test_unit_name_LDADD = \
libsystemd-core.la \
$(RT_LIBS)
@ -1232,10 +1197,6 @@ test_unit_name_LDADD = \
test_unit_file_SOURCES = \
src/test/test-unit-file.c
test_unit_file_CFLAGS = \
$(AM_CFLAGS) \
$(DBUS_CFLAGS)
test_unit_file_LDADD = \
libsystemd-core.la \
$(RT_LIBS)
@ -1274,10 +1235,6 @@ test_tables_SOURCES = \
src/test/test-tables.c \
src/shared/test-tables.h
test_tables_CFLAGS = \
$(AM_CFLAGS) \
$(DBUS_CFLAGS)
test_tables_LDADD = \
libsystemd-logs.la \
libsystemd-journal-internal.la \
@ -1401,10 +1358,6 @@ test_strxcpyx_LDADD = \
test_install_SOURCES = \
src/test/test-install.c
test_install_CFLAGS = \
$(AM_CFLAGS) \
$(DBUS_CFLAGS)
test_install_LDADD = \
libsystemd-units.la \
libsystemd-label.la \
@ -1422,7 +1375,6 @@ test_sched_prio_SOURCES = \
test_sched_prio_CFLAGS = \
$(AM_CFLAGS) \
$(DBUS_CFLAGS) \
-D"STR(s)=\#s" -D"TEST_DIR=STR($(abs_top_srcdir)/test/)"
test_sched_prio_LDADD = \
@ -2800,9 +2752,6 @@ mtd_probe_SOURCES = \
src/udev/mtd_probe/mtd_probe.h \
src/udev/mtd_probe/probe_smartmedia.c
mtd_probe_CPPFLAGS = \
$(AM_CPPFLAGS)
dist_udevrules_DATA += \
rules/75-probe_mtd.rules
@ -3893,7 +3842,6 @@ systemd_logind_LDADD = \
libsystemd_logind_core_la_SOURCES = \
src/login/logind-core.c \
src/login/logind-dbus.c \
src/login/logind-device.c \
src/login/logind-device.h \
src/login/logind-button.c \
@ -3910,6 +3858,7 @@ libsystemd_logind_core_la_SOURCES = \
src/login/logind-user.h \
src/login/logind-inhibit.c \
src/login/logind-inhibit.h \
src/login/logind-dbus.c \
src/login/logind-session-dbus.c \
src/login/logind-seat-dbus.c \
src/login/logind-user-dbus.c \

47
TODO
View File

@ -43,6 +43,53 @@ CGroup Rework Completion:
Features:
* sd-event: allow multiple signal handlers per signal
* timer: expose accuracy as unit setting
* sd-event: do per-minute coalescing of timer events too
* when we detect low battery and no AC on boot, show pretty splash and refuse boot
* move libasyncns into systemd as libsystemd-asyncns
* calendarspec: support value ranges with ".." notation. Example: 2013-4..8-1
* pid1 porting:
- restore selinux access control on properties
* sd-bus: when triggering property change events, allow a NULL strv indicate that all properties listed as such are send out as changed
* sd-bus: enforce signatures on response messages
* sd-bus: make message handlers take an sd_bus_error and generate error replies automatically if they are set
* sd-bus: when replying to a bus message we should not need to specify the bus again
* sd-bus: see if we can drop more message validation on the sending side
* sd-bus: introduce sd_bus_creds object and attach it to messages as well as allow querying it for names
* sd-bus: support "const" properties as flag
* sd-bus: add api call to escape bus path components
* sd-event: when a handler returns an error, just turn off its event
source, but do not return anything up to the event loop
caller. Instead add parameter to sd_event_request_quit() to take
retval. This way errors rippling upwards are the option, not the
default
* sd-event: child pid handling: first invoke waitid(WNOHANG) and call event handler, only afterwards reap the process
* sd-event: native support for watchdog stuff
* machined, localed: when we try to kill an empty cgroup, generate an ESRCH call over the bus
* sd-bus: SD_BUS_COMMENT() macro for inclusion in vtables, syntax inspired by gdbus
* libsystemd-journal, libsystemd-login, libudev: add calls to easily attach these objects to sd-event event loops
* be more careful what we export on the bus as (usec_t) 0 and (usec_t) -1
* check :no-sender logic after PID 1 conversion

View File

@ -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,

View File

@ -49,8 +49,8 @@ struct Automount {
char *where;
int pipe_fd;
sd_event_source *pipe_event_source;
mode_t directory_mode;
Watch pipe_watch;
dev_t dev_id;
Set *tokens;

View File

@ -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"
#include "bus-util.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"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, automount_result, AutomountResult);
#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;
const char bus_automount_invalidating_properties[] =
"Result\0";
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
};

View File

@ -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[];

View File

@ -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 bus_cgroup_append_device_weights(DBusMessageIter *i, const char *property, void *data) {
DBusMessageIter sub, sub2;
CGroupContext *c = data;
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) {
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;
CGroupBlockIODeviceBandwidth *b;
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) {
assert(i);
assert(property);
CGroupContext *c = userdata;
CGroupBlockIODeviceBandwidth *b;
int r;
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;
CGroupDeviceAllow *a;
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) {
assert(i);
assert(property);
CGroupContext *c = userdata;
CGroupDeviceAllow *a;
int r;
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;
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;
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;
r = sd_bus_message_enter_container(message, 'a', "(ss)");
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, *rwm;
while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
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_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) {

View File

@ -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 sd_bus_vtable bus_cgroup_vtable[];
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);
int bus_cgroup_set_property(Unit *u, CGroupContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);

View File

@ -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;
}

View File

@ -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);

View File

@ -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
};

View File

@ -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[];

View File

@ -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);
if (fn[0] == '-') {
b = true;
fn++;
}
r = sd_bus_message_open_container(reply, 'a', "(sb)");
if (r < 0)
return r;
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;
STRV_FOREACH(j, c->environment_files) {
const char *fn = *j;
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 0;
return sd_bus_message_close_container(reply);
}
static int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
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);
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 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);
ExecContext *c = userdata;
assert(bus);
assert(reply);
assert(c);
if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
return -ENOMEM;
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;
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) {
assert(i);
assert(property);
ExecContext *c = userdata;
assert(bus);
assert(reply);
assert(c);
assert_se((r = rlimit_from_string(property)) >= 0);
if (c->rlimit[r])
u = (uint64_t) c->rlimit[r]->rlim_max;
else {
struct rlimit rl = {};
getrlimit(r, &rl);
u = (uint64_t) rl.rlim_max;
}
if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
return -ENOMEM;
return 0;
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);
}
int bus_execute_append_command(DBusMessageIter *i, const char *property, void *data) {
ExecCommand *c = data;
DBusMessageIter sub, sub2, sub3;
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
};
assert(i);
assert(property);
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) {
if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasbttttuii)", &sub))
return -ENOMEM;
ExecCommand *c = *(ExecCommand**) userdata;
int r;
assert(bus);
assert(reply);
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;
r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
if (r < 0)
return r;
STRV_FOREACH(l, c->argv)
if (!dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, l))
return -ENOMEM;
r = sd_bus_message_append(reply, "s", c->path);
if (r < 0)
return r;
pid = (uint32_t) c->exec_status.pid;
code = (int32_t) c->exec_status.code;
status = (int32_t) c->exec_status.status;
r = sd_bus_message_append_strv(reply, c->argv);
if (r < 0)
return r;
b = !!c->ignore;
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;
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_close_container(reply);
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_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;
}
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 },
{}
};

View File

@ -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);

View File

@ -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"
#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"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, job_type, JobType);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state, job_state, JobState);
#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"
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) {
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 int method_cancel(sd_bus *bus, sd_bus_message *message, void *userdata) {
Job *j = userdata;
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;
assert(connection);
assert(bus);
assert(message);
assert(m);
assert(j);
if (streq(dbus_message_get_path(message), "/org/freedesktop/systemd1/job")) {
/* Be nice to gdbus and return introspection data for our mid-level paths */
SELINUX_UNIT_ACCESS_CHECK(j->unit, bus, message, "stop");
job_finish_and_invalidate(j, JOB_CANCELED, true);
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);
return bus_job_message_dispatch(j, connection, message);
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 (n <= 0 && m <= 0)
return 0;
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 (one_destination)
return send_message(one_destination->bus, isempty(one_destination->name) ? NULL : one_destination->name, j);
/* Send to everybody */
SET_FOREACH(b, j->manager->private_buses, i) {
r = send_message(b, NULL, j);
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);
m = new_message(j);
if (!m)
return -ENOMEM;
if (!dbus_message_set_destination(m, cl->name))
return -ENOMEM;
if (!dbus_connection_send(cl->bus, m, NULL))
return -ENOMEM;
dbus_message_unref(m);
m = NULL;
}
}
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;
return -ENOMEM;
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;
r = sd_bus_message_new_signal(
bus,
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"JobNew",
&m);
if (r < 0)
return r;
} else {
/* Send a new signal */
r = sd_bus_message_append(m, "uos", j->id, p, j->unit->id);
if (r < 0)
return r;
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 m;
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;
return -ENOMEM;
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 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;
}
return;
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;
oom:
log_error("Failed to allocate job change signal.");
assert(bus);
assert(j);
p = job_dbus_path(j);
if (!p)
return -ENOMEM;
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;
}

View File

@ -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[];

View File

@ -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));

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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"
#include "bus-util.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"
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) {
#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;
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 BUS_DEFINE_PROPERTY_GET_ENUM(property_get_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, }
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) {

View File

@ -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[];

View File

@ -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"
#include "bus-util.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"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, path_result, PathResult);
#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"
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) {
#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;
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);
return sd_bus_message_append(reply, "s", trigger ? trigger->id : "");
}
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_path_append_path_result, path_result, PathResult);
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
};

View File

@ -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[];

View File

@ -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"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, scope_result, ScopeResult);
#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) },
{}
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
};
DBusHandlerResult bus_scope_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
Scope *s = SCOPE(u);
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");
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;
r = sd_bus_message_read(message, "t", &s->timeout_stop_usec);
if (r < 0)
return r;
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);
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;
}

View File

@ -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[];

View File

@ -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"
#include "bus-util.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"
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);
#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) },
{}
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;
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);
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;
if (!path_is_absolute(path)) {
dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
return -EINVAL;
}
r = bus_parse_strv_iter(&sub2, &argv);
r = sd_bus_message_read(message, "s", &path);
if (r < 0)
return r;
dbus_message_iter_next(&sub2);
if (!path_is_absolute(path))
return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) < 0)
return -EINVAL;
r = sd_bus_message_read_strv(message, &argv);
if (r < 0)
return r;
r = sd_bus_message_read(message, "b", &b);
if (r < 0)
return r;
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;
}

View File

@ -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[];

View File

@ -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) {

View File

@ -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[];

View File

@ -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"
int bus_snapshot_method_remove(sd_bus *bus, sd_bus_message *message, void *userdata) {
Snapshot *s = userdata;
#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"
assert(bus);
assert(message);
assert(s);
#define INTERFACES_LIST \
BUS_UNIT_INTERFACES_LIST \
"org.freedesktop.systemd1.Snapshot\0"
SELINUX_UNIT_ACCESS_CHECK(UNIT(s), bus, message, "stop");
const char bus_snapshot_interface[] = BUS_SNAPSHOT_INTERFACE;
snapshot_remove(s);
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;
if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Snapshot", "Remove")) {
SELINUX_UNIT_ACCESS_CHECK(u, c, message, "stop");
reply = dbus_message_new_method_return(message);
if (!reply)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
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
};

View File

@ -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);

View File

@ -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"
#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" \
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);
#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"
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 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) {

View File

@ -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[];

View File

@ -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"
#include "bus-util.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"
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) {
#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"
Swap *s = SWAP(userdata);
int p;
#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);
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;
p = -1;
if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &j))
return -ENOMEM;
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 BUS_DEFINE_PROPERTY_GET_ENUM(property_get_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, }
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) {

View File

@ -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[];

View File

@ -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
};

View File

@ -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[];

View File

@ -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"
#include "bus-util.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"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, timer_result, TimerResult);
#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"
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) {
#define INTERFACES_LIST \
BUS_UNIT_INTERFACES_LIST \
"org.freedesktop.systemd1.Timer\0"
Timer *t = userdata;
TimerValue *v;
int r;
const char bus_timer_interface[] = BUS_TIMER_INTERFACE;
assert(bus);
assert(reply);
assert(t);
const char bus_timer_invalidating_properties[] =
"TimersMonotonic\0"
"TimersRealtime\0"
"NextElapseUSecRealtime\0"
"NextElapseUSecMonotonic\0"
"Result\0";
r = sd_bus_message_open_container(reply, 'a', "(stt)");
if (r < 0)
return r;
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) {
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;
r = calendar_spec_to_string(v->calendar_spec, &buf);
if (r < 0)
return r;
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);
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) {
assert(i);
assert(property);
Unit *u = userdata, *trigger;
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
};

View File

@ -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[];

File diff suppressed because it is too large Load Diff

View File

@ -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_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);
int bus_unit_set_properties(Unit *u, DBusMessageIter *i, UnitSetPropertiesMode mode, bool commit, DBusError *error);
extern const DBusObjectPathVTable bus_unit_vtable;
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);

File diff suppressed because it is too large Load Diff

View File

@ -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[];

View File

@ -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;
goto fail;
}
if (udev_enumerate_scan_devices(e) < 0) {
r = -EIO;
r = udev_enumerate_add_match_tag(e, "systemd");
if (r < 0)
goto fail;
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,

View File

@ -50,7 +50,5 @@ struct Device {
extern const UnitVTable device_vtable;
void device_fd_event(Manager *m, int events);
const char* device_state_to_string(DeviceState i) _const_;
DeviceState device_state_from_string(const char *s) _pure_;

View File

@ -24,8 +24,8 @@
#include <sys/timerfd.h>
#include <sys/epoll.h>
#include "systemd/sd-id128.h"
#include "systemd/sd-messages.h"
#include "sd-id128.h"
#include "sd-messages.h"
#include "set.h"
#include "unit.h"
#include "macro.h"
@ -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;
static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *userdata) {
Job *j = userdata;
if (j->unit->job_timeout <= 0 ||
j->timer_watch.type == WATCH_JOB_TIMER)
assert(j);
assert(s == j->timer_event_source);
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);
return 0;
}
int job_start_timer(Job *j) {
int r;
if (j->unit->job_timeout <= 0 || j->timer_event_source)
return 0;
assert(j->timer_watch.type == WATCH_INVALID);
j->begin_usec = now(CLOCK_MONOTONIC);
if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
r = -errno;
goto fail;
}
timespec_store(&its.it_value, j->unit->job_timeout);
if (timerfd_settime(fd, 0, &its, NULL) < 0) {
r = -errno;
goto fail;
}
if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
r = -errno;
goto fail;
}
j->timer_watch.type = WATCH_JOB_TIMER;
j->timer_watch.fd = fd;
j->timer_watch.data.job = j;
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 0;
fail:
if (fd >= 0)
close_nointr_nofail(fd);
return r;
}
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
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;
}
} 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->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;
if (j->timer_watch.type != WATCH_JOB_TIMER)
assert(j);
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) {

View File

@ -27,7 +27,6 @@
typedef struct Job Job;
typedef struct JobDependency JobDependency;
typedef struct JobBusClient JobBusClient;
typedef enum JobType JobType;
typedef enum JobState JobState;
typedef enum JobMode JobMode;
@ -102,6 +101,7 @@ enum JobResult {
_JOB_RESULT_INVALID = -1
};
#include "sd-event.h"
#include "manager.h"
#include "unit.h"
#include "hashmap.h"
@ -120,13 +120,6 @@ struct JobDependency {
bool conflicts;
};
struct JobBusClient {
LIST_FIELDS(JobBusClient, client);
/* Note that this bus object is not ref counted here. */
DBusConnection *bus;
char name[0];
};
struct Job {
Manager *manager;
Unit *unit;
@ -147,10 +140,11 @@ struct Job {
JobType type;
JobState state;
Watch timer_watch;
sd_event_source *timer_event_source;
usec_t begin_usec;
/* There can be more than one client, because of job merging. */
LIST_HEAD(JobBusClient, bus_client_list);
Set *subscribed;
JobResult result;
@ -165,8 +159,6 @@ struct Job {
bool irreversible:1;
};
JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name);
Job* job_new(Unit *unit, JobType type);
Job* job_new_raw(Unit *unit);
void job_free(Job *job);
@ -210,7 +202,6 @@ void job_add_to_run_queue(Job *j);
void job_add_to_dbus_queue(Job *j);
int job_start_timer(Job *j);
void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w);
int job_run_and_invalidate(Job *j);
int job_finish_and_invalidate(Job *j, JobResult result, bool recursive);

View File

@ -210,7 +210,7 @@ Socket.Broadcast, config_parse_bool, 0,
Socket.PassCredentials, config_parse_bool, 0, offsetof(Socket, pass_cred)
Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec)
Socket.TCPCongestion, config_parse_string, 0, offsetof(Socket, tcp_congestion)
Socket.ReusePort, config_parse_bool, 0, offsetof(Socket, reuseport)
Socket.ReusePort, config_parse_bool, 0, offsetof(Socket, reuse_port)
Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg)
Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize)
Socket.Service, config_parse_socket_service, 0, 0

View File

@ -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;
}

View File

@ -19,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <dbus/dbus.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
@ -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) {

File diff suppressed because it is too large Load Diff

View File

@ -24,8 +24,9 @@
#include <stdbool.h>
#include <inttypes.h>
#include <stdio.h>
#include <dbus/dbus.h>
#include "sd-bus.h"
#include "sd-event.h"
#include "fdset.h"
#include "cgroup-util.h"
@ -33,8 +34,6 @@
#define MANAGER_MAX_NAMES 131072 /* 128K */
typedef struct Manager Manager;
typedef enum WatchType WatchType;
typedef struct Watch Watch;
typedef enum ManagerExitCode {
MANAGER_RUNNING,
@ -50,42 +49,11 @@ typedef enum ManagerExitCode {
_MANAGER_EXIT_CODE_INVALID = -1
} ManagerExitCode;
enum WatchType {
WATCH_INVALID,
WATCH_SIGNAL,
WATCH_NOTIFY,
WATCH_FD,
WATCH_UNIT_TIMER,
WATCH_JOB_TIMER,
WATCH_MOUNT,
WATCH_SWAP,
WATCH_UDEV,
WATCH_DBUS_WATCH,
WATCH_DBUS_TIMEOUT,
WATCH_TIME_CHANGE,
WATCH_JOBS_IN_PROGRESS,
WATCH_IDLE_PIPE,
};
struct Watch {
int fd;
WatchType type;
union {
struct Unit *unit;
struct Job *job;
DBusWatch *bus_watch;
DBusTimeout *bus_timeout;
} data;
bool fd_is_dupped:1;
bool socket_accept:1;
};
#include "unit.h"
#include "job.h"
#include "hashmap.h"
#include "list.h"
#include "set.h"
#include "dbus.h"
#include "path-lookup.h"
#include "execute.h"
#include "unit-name.h"
@ -125,17 +93,21 @@ struct Manager {
/* Units that should be realized */
LIST_HEAD(Unit, cgroup_queue);
sd_event *event;
Hashmap *watch_pids; /* pid => Unit object n:1 */
char *notify_socket;
int notify_fd;
sd_event_source *notify_event_source;
Watch notify_watch;
Watch signal_watch;
Watch time_change_watch;
Watch jobs_in_progress_watch;
Watch idle_pipe_watch;
int signal_fd;
sd_event_source *signal_event_source;
int epoll_fd;
int time_change_fd;
sd_event_source *time_change_event_source;
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);

View File

@ -59,6 +59,9 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
[MOUNT_FAILED] = UNIT_FAILED
};
static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static char* mount_test_option(const char *haystack, const char *needle) {
struct mntent me = { .mnt_opts = (char*) haystack };
@ -156,13 +159,32 @@ static void mount_init(Unit *u) {
* already trying to comply its last one. */
m->exec_context.same_pgrp = true;
m->timer_watch.type = WATCH_INVALID;
m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
UNIT(m)->ignore_on_isolate = true;
}
static int mount_arm_timer(Mount *m) {
int r;
assert(m);
if (m->timeout_usec <= 0) {
m->timer_event_source = sd_event_source_unref(m->timer_event_source);
return 0;
}
if (m->timer_event_source) {
r = sd_event_source_set_time(m->timer_event_source, now(CLOCK_MONOTONIC) + m->timeout_usec);
if (r < 0)
return r;
return sd_event_source_set_enabled(m->timer_event_source, SD_EVENT_ONESHOT);
}
return sd_event_add_monotonic(UNIT(m)->manager->event, now(CLOCK_MONOTONIC) + m->timeout_usec, 0, mount_dispatch_timer, m, &m->timer_event_source);
}
static void mount_unwatch_control_pid(Mount *m) {
assert(m);
@ -201,7 +223,7 @@ static void mount_done(Unit *u) {
mount_unwatch_control_pid(m);
unit_unwatch_timer(u, &m->timer_watch);
m->timer_event_source = sd_event_source_unref(m->timer_event_source);
}
_pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
@ -626,7 +648,7 @@ static void mount_set_state(Mount *m, MountState state) {
state != MOUNT_UNMOUNTING_SIGKILL &&
state != MOUNT_REMOUNTING_SIGTERM &&
state != MOUNT_REMOUNTING_SIGKILL) {
unit_unwatch_timer(UNIT(m), &m->timer_watch);
m->timer_event_source = sd_event_source_unref(m->timer_event_source);
mount_unwatch_control_pid(m);
m->control_command = NULL;
m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
@ -692,7 +714,7 @@ static int mount_coldplug(Unit *u) {
if (r < 0)
return r;
r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
r = mount_arm_timer(m);
if (r < 0)
return r;
}
@ -751,7 +773,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
unit_realize_cgroup(UNIT(m));
r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
r = mount_arm_timer(m);
if (r < 0)
goto fail;
@ -782,7 +804,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
return 0;
fail:
unit_unwatch_timer(UNIT(m), &m->timer_watch);
m->timer_event_source = sd_event_source_unref(m->timer_event_source);
return r;
}
@ -825,7 +847,7 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
goto fail;
if (r > 0) {
r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
r = mount_arm_timer(m);
if (r < 0)
goto fail;
@ -959,17 +981,11 @@ static void mount_enter_remounting(Mount *m) {
m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
if (m->from_fragment) {
char *buf = NULL;
const char *o;
if (m->parameters_fragment.options) {
if (!(buf = strappend("remount,", m->parameters_fragment.options))) {
r = -ENOMEM;
goto fail;
}
o = buf;
} else
if (m->parameters_fragment.options)
o = strappenda("remount,", m->parameters_fragment.options);
else
o = "remount";
r = exec_command_set(
@ -980,8 +996,6 @@ static void mount_enter_remounting(Mount *m) {
"-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
"-o", o,
NULL);
free(buf);
} else
r = -ENOENT;
@ -990,7 +1004,8 @@ static void mount_enter_remounting(Mount *m) {
mount_unwatch_control_pid(m);
if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
r = mount_spawn(m, m->control_command, &m->control_pid);
if (r < 0)
goto fail;
mount_set_state(m, MOUNT_REMOUNTING);
@ -1279,44 +1294,43 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
unit_add_to_dbus_queue(u);
}
static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
Mount *m = MOUNT(u);
static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
Mount *m = MOUNT(userdata);
assert(m);
assert(elapsed == 1);
assert(w == &m->timer_watch);
assert(m->timer_event_source == source);
switch (m->state) {
case MOUNT_MOUNTING:
case MOUNT_MOUNTING_DONE:
log_warning_unit(u->id,
"%s mounting timed out. Stopping.", u->id);
log_warning_unit(UNIT(m)->id,
"%s mounting timed out. Stopping.", UNIT(m)->id);
mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
break;
case MOUNT_REMOUNTING:
log_warning_unit(u->id,
"%s remounting timed out. Stopping.", u->id);
log_warning_unit(UNIT(m)->id,
"%s remounting timed out. Stopping.", UNIT(m)->id);
m->reload_result = MOUNT_FAILURE_TIMEOUT;
mount_enter_mounted(m, MOUNT_SUCCESS);
break;
case MOUNT_UNMOUNTING:
log_warning_unit(u->id,
"%s unmounting timed out. Stopping.", u->id);
log_warning_unit(UNIT(m)->id,
"%s unmounting timed out. Stopping.", UNIT(m)->id);
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
break;
case MOUNT_MOUNTING_SIGTERM:
if (m->kill_context.send_sigkill) {
log_warning_unit(u->id,
"%s mounting timed out. Killing.", u->id);
log_warning_unit(UNIT(m)->id,
"%s mounting timed out. Killing.", UNIT(m)->id);
mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
} else {
log_warning_unit(u->id,
log_warning_unit(UNIT(m)->id,
"%s mounting timed out. Skipping SIGKILL. Ignoring.",
u->id);
UNIT(m)->id);
if (m->from_proc_self_mountinfo)
mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@ -1327,13 +1341,13 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
case MOUNT_REMOUNTING_SIGTERM:
if (m->kill_context.send_sigkill) {
log_warning_unit(u->id,
"%s remounting timed out. Killing.", u->id);
log_warning_unit(UNIT(m)->id,
"%s remounting timed out. Killing.", UNIT(m)->id);
mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
} else {
log_warning_unit(u->id,
log_warning_unit(UNIT(m)->id,
"%s remounting timed out. Skipping SIGKILL. Ignoring.",
u->id);
UNIT(m)->id);
if (m->from_proc_self_mountinfo)
mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@ -1344,13 +1358,13 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
case MOUNT_UNMOUNTING_SIGTERM:
if (m->kill_context.send_sigkill) {
log_warning_unit(u->id,
"%s unmounting timed out. Killing.", u->id);
log_warning_unit(UNIT(m)->id,
"%s unmounting timed out. Killing.", UNIT(m)->id);
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
} else {
log_warning_unit(u->id,
log_warning_unit(UNIT(m)->id,
"%s unmounting timed out. Skipping SIGKILL. Ignoring.",
u->id);
UNIT(m)->id);
if (m->from_proc_self_mountinfo)
mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@ -1362,9 +1376,9 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
case MOUNT_MOUNTING_SIGKILL:
case MOUNT_REMOUNTING_SIGKILL:
case MOUNT_UNMOUNTING_SIGKILL:
log_warning_unit(u->id,
log_warning_unit(UNIT(m)->id,
"%s mount process still around after SIGKILL. Ignoring.",
u->id);
UNIT(m)->id);
if (m->from_proc_self_mountinfo)
mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@ -1375,6 +1389,8 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
default:
assert_not_reached("Timeout at wrong time.");
}
return 0;
}
static int mount_add_one(
@ -1582,6 +1598,8 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
static void mount_shutdown(Manager *m) {
assert(m);
m->mount_event_source = sd_event_source_unref(m->mount_event_source);
if (m->proc_self_mountinfo) {
fclose(m->proc_self_mountinfo);
m->proc_self_mountinfo = NULL;
@ -1593,20 +1611,13 @@ static int mount_enumerate(Manager *m) {
assert(m);
if (!m->proc_self_mountinfo) {
struct epoll_event ev = {
.events = EPOLLPRI,
.data.ptr = &m->mount_watch,
};
m->proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
if (!m->proc_self_mountinfo)
return -errno;
m->mount_watch.type = WATCH_MOUNT;
m->mount_watch.fd = fileno(m->proc_self_mountinfo);
if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->mount_watch.fd, &ev) < 0)
return -errno;
r = sd_event_add_io(m->event, fileno(m->proc_self_mountinfo), EPOLLPRI, mount_dispatch_io, m, &m->mount_event_source);
if (r < 0)
goto fail;
}
r = mount_load_proc_self_mountinfo(m, false);
@ -1620,12 +1631,13 @@ fail:
return r;
}
void mount_fd_event(Manager *m, int events) {
static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
Unit *u;
int r;
assert(m);
assert(events & EPOLLPRI);
assert(revents & EPOLLPRI);
/* The manager calls this for every fd event happening on the
* /proc/self/mountinfo file, which informs us about mounting
@ -1642,7 +1654,7 @@ void mount_fd_event(Manager *m, int events) {
mount->is_mounted = mount->just_mounted = mount->just_changed = false;
}
return;
return 0;
}
manager_dispatch_load_queue(m);
@ -1696,6 +1708,8 @@ void mount_fd_event(Manager *m, int events) {
/* Reset the flags for later calls */
mount->is_mounted = mount->just_mounted = mount->just_changed = false;
}
return 0;
}
static void mount_reset_failed(Unit *u) {
@ -1710,7 +1724,7 @@ static void mount_reset_failed(Unit *u) {
m->reload_result = MOUNT_SUCCESS;
}
static int mount_kill(Unit *u, KillWho who, int signo, DBusError *error) {
static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error);
}
@ -1753,15 +1767,15 @@ DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
const UnitVTable mount_vtable = {
.object_size = sizeof(Mount),
.exec_context_offset = offsetof(Mount, exec_context),
.cgroup_context_offset = offsetof(Mount, cgroup_context),
.kill_context_offset = offsetof(Mount, kill_context),
.sections =
"Unit\0"
"Mount\0"
"Install\0",
.private_section = "Mount",
.exec_context_offset = offsetof(Mount, exec_context),
.cgroup_context_offset = offsetof(Mount, cgroup_context),
.no_alias = true,
.no_instances = true,
@ -1789,13 +1803,12 @@ const UnitVTable mount_vtable = {
.check_gc = mount_check_gc,
.sigchld_event = mount_sigchld_event,
.timer_event = mount_timer_event,
.reset_failed = mount_reset_failed,
.bus_interface = "org.freedesktop.systemd1.Mount",
.bus_message_handler = bus_mount_message_handler,
.bus_invalidating_properties = bus_mount_invalidating_properties,
.bus_vtable = bus_mount_vtable,
.bus_changing_properties = bus_mount_changing_properties,
.bus_set_property = bus_mount_set_property,
.bus_commit_properties = bus_mount_commit_properties,

View File

@ -107,7 +107,7 @@ struct Mount {
MountExecCommand control_command_id;
pid_t control_pid;
Watch timer_watch;
sd_event_source *timer_event_source;
};
extern const UnitVTable mount_vtable;

View File

@ -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) {
void path_spec_unwatch(PathSpec *s) {
assert(s);
if (s->inotify_fd < 0)
return;
s->event_source = sd_event_source_unref(s->event_source);
unit_unwatch_fd(u, &s->watch);
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
};

View File

@ -46,9 +46,11 @@ typedef enum PathType {
} PathType;
typedef struct PathSpec {
Unit *unit;
char *path;
Watch watch;
sd_event_source *event_source;
LIST_FIELDS(struct PathSpec, spec);
@ -59,8 +61,8 @@ typedef struct PathSpec {
bool previous_exists;
} PathSpec;
int path_spec_watch(PathSpec *s, Unit *u);
void path_spec_unwatch(PathSpec *s, Unit *u);
int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler);
void path_spec_unwatch(PathSpec *s);
int path_spec_fd_event(PathSpec *s, uint32_t events);
void path_spec_done(PathSpec *s);

View File

@ -40,6 +40,8 @@ static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
[SCOPE_FAILED] = UNIT_FAILED
};
static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
static void scope_init(Unit *u) {
Scope *s = SCOPE(u);
@ -48,8 +50,6 @@ static void scope_init(Unit *u) {
s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
watch_init(&s->timer_watch);
cgroup_context_init(&s->cgroup_context);
kill_context_init(&s->kill_context);
@ -67,7 +67,28 @@ static void scope_done(Unit *u) {
set_free(s->pids);
s->pids = NULL;
unit_unwatch_timer(u, &s->timer_watch);
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
}
static int scope_arm_timer(Scope *s) {
int r;
assert(s);
if (s->timeout_stop_usec <= 0) {
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
return 0;
}
if (s->timer_event_source) {
r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec);
if (r < 0)
return r;
return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
}
return sd_event_add_monotonic(UNIT(s)->manager->event, now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0, scope_dispatch_timer, s, &s->timer_event_source);
}
static void scope_set_state(Scope *s, ScopeState state) {
@ -79,7 +100,7 @@ static void scope_set_state(Scope *s, ScopeState state) {
if (state != SCOPE_STOP_SIGTERM &&
state != SCOPE_STOP_SIGKILL)
unit_unwatch_timer(UNIT(s), &s->timer_watch);
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
if (state != old_state)
log_debug("%s changed %s -> %s",
@ -158,11 +179,9 @@ static int scope_coldplug(Unit *u) {
if (s->deserialized_state != s->state) {
if ((s->deserialized_state == SCOPE_STOP_SIGKILL || s->deserialized_state == SCOPE_STOP_SIGTERM)
&& s->timeout_stop_usec > 0) {
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch);
if (s->deserialized_state == SCOPE_STOP_SIGKILL || s->deserialized_state == SCOPE_STOP_SIGTERM) {
r = scope_arm_timer(s);
if (r < 0)
return r;
}
@ -214,11 +233,9 @@ static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
goto fail;
if (r > 0) {
if (s->timeout_stop_usec > 0) {
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch);
if (r < 0)
goto fail;
}
r = scope_arm_timer(s);
if (r < 0)
goto fail;
scope_set_state(s, state);
} else
@ -297,7 +314,7 @@ static void scope_reset_failed(Unit *u) {
s->result = SCOPE_SUCCESS;
}
static int scope_kill(Unit *u, KillWho who, int signo, DBusError *error) {
static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
return unit_kill_common(u, who, signo, -1, -1, error);
}
@ -353,34 +370,35 @@ static bool scope_check_gc(Unit *u) {
return false;
}
static void scope_timer_event(Unit *u, uint64_t elapsed, Watch*w) {
Scope *s = SCOPE(u);
static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
Scope *s = SCOPE(userdata);
assert(s);
assert(elapsed == 1);
assert(w == &s->timer_watch);
assert(s->timer_event_source == source);
switch (s->state) {
case SCOPE_STOP_SIGTERM:
if (s->kill_context.send_sigkill) {
log_warning_unit(u->id, "%s stopping timed out. Killing.", u->id);
log_warning_unit(UNIT(s)->id, "%s stopping timed out. Killing.", UNIT(s)->id);
scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
} else {
log_warning_unit(u->id, "%s stopping timed out. Skipping SIGKILL.", u->id);
log_warning_unit(UNIT(s)->id, "%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id);
scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
}
break;
case SCOPE_STOP_SIGKILL:
log_warning_unit(u->id, "%s still around after SIGKILL. Ignoring.", u->id);
log_warning_unit(UNIT(s)->id, "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
break;
default:
assert_not_reached("Timeout at wrong time.");
}
return 0;
}
static void scope_notify_cgroup_empty_event(Unit *u) {
@ -435,13 +453,14 @@ DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
const UnitVTable scope_vtable = {
.object_size = sizeof(Scope),
.cgroup_context_offset = offsetof(Scope, cgroup_context),
.kill_context_offset = offsetof(Scope, kill_context),
.sections =
"Unit\0"
"Scope\0"
"Install\0",
.private_section = "Scope",
.cgroup_context_offset = offsetof(Scope, cgroup_context),
.no_alias = true,
.no_instances = true,
@ -467,14 +486,13 @@ const UnitVTable scope_vtable = {
.check_gc = scope_check_gc,
.timer_event = scope_timer_event,
.reset_failed = scope_reset_failed,
.notify_cgroup_empty = scope_notify_cgroup_empty_event,
.bus_interface = "org.freedesktop.systemd1.Scope",
.bus_message_handler = bus_scope_message_handler,
.bus_vtable = bus_scope_vtable,
.bus_changing_properties = bus_scope_changing_properties,
.bus_set_property = bus_scope_set_property,
.bus_commit_properties = bus_scope_commit_properties,

View File

@ -57,7 +57,7 @@ struct Scope {
Set *pids;
Watch timer_watch;
sd_event_source *timer_event_source;
};
extern const UnitVTable scope_vtable;

View File

@ -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;
int r;
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;
}
assert(bus);
assert(name);
assert(ret);
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;
}
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;
reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error);
if (!reply)
return -EIO;
r = sd_bus_message_read_array(m, 'y', &p, &sz);
if (r < 0)
return r;
if (dbus_set_error_from_message(error, reply))
return -EIO;
if (!dbus_message_iter_init(reply, &iter))
return -EIO;
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
return -EIO;
dbus_message_iter_recurse(&iter, &sub);
dbus_message_iter_get_fixed_array(&sub, &bytes, &nbytes);
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) {
const char *sender;
int r, fd;
struct ucred ucred;
socklen_t len = sizeof(ucred);
const char *sender;
socklen_t len;
int r, fd;
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;
sender = sd_bus_message_get_sender(message);
if (sender)
return bus_get_selinux_security_context(bus, sender, error, ret);
log_error("bus_get_selinux_security_context failed: %m");
return r;
}
fd = sd_bus_get_fd(bus);
if (fd < 0)
return fd;
if (!dbus_connection_get_unix_fd(connection, &fd)) {
log_error("bus_connection_get_unix_fd failed %m");
return -EINVAL;
}
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;
}

View File

@ -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

View File

@ -36,7 +36,6 @@
#include "unit-printf.h"
#include "dbus-service.h"
#include "special.h"
#include "dbus-common.h"
#include "exit-status.h"
#include "def.h"
#include "path-util.h"
@ -44,6 +43,8 @@
#include "utf8.h"
#include "env-util.h"
#include "fileio.h"
#include "bus-error.h"
#include "bus-util.h"
#ifdef HAVE_SYSV_COMPAT
@ -118,6 +119,10 @@ static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] =
[SERVICE_AUTO_RESTART] = UNIT_ACTIVATING
};
static int service_dispatch_io(sd_event_source *source, int fd, uint32_t events, void *userdata);
static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata);
static void service_init(Unit *u) {
Service *s = SERVICE(u);
@ -129,9 +134,6 @@ static void service_init(Unit *u) {
s->restart_usec = u->manager->default_restart_usec;
s->type = _SERVICE_TYPE_INVALID;
watch_init(&s->watchdog_watch);
watch_init(&s->timer_watch);
#ifdef HAVE_SYSV_COMPAT
s->sysv_start_priority = -1;
s->sysv_start_priority_from_rcnd = -1;
@ -176,7 +178,7 @@ static void service_unwatch_pid_file(Service *s) {
log_debug_unit(UNIT(s)->id, "Stopping watch for %s's PID file %s",
UNIT(s)->id, s->pid_file_pathspec->path);
path_spec_unwatch(s->pid_file_pathspec, UNIT(s));
path_spec_unwatch(s->pid_file_pathspec);
path_spec_done(s->pid_file_pathspec);
free(s->pid_file_pathspec);
s->pid_file_pathspec = NULL;
@ -239,15 +241,14 @@ static void service_connection_unref(Service *s) {
static void service_stop_watchdog(Service *s) {
assert(s);
unit_unwatch_timer(UNIT(s), &s->watchdog_watch);
s->watchdog_timestamp.realtime = 0;
s->watchdog_timestamp.monotonic = 0;
s->watchdog_event_source = sd_event_source_unref(s->watchdog_event_source);
s->watchdog_timestamp = (struct dual_timestamp) { 0, 0 };
}
static void service_enter_signal(Service *s, ServiceState state, ServiceResult f);
static void service_handle_watchdog(Service *s) {
usec_t offset;
usec_t nw;
int r;
assert(s);
@ -255,14 +256,24 @@ static void service_handle_watchdog(Service *s) {
if (s->watchdog_usec == 0)
return;
offset = now(CLOCK_MONOTONIC) - s->watchdog_timestamp.monotonic;
if (offset >= s->watchdog_usec) {
nw = now(CLOCK_MONOTONIC);
if (nw >= s->watchdog_timestamp.monotonic + s->watchdog_usec) {
log_error_unit(UNIT(s)->id, "%s watchdog timeout!", UNIT(s)->id);
service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_WATCHDOG);
return;
}
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->watchdog_usec - offset, &s->watchdog_watch);
if (s->watchdog_event_source) {
r = sd_event_source_set_time(s->watchdog_event_source, s->watchdog_timestamp.monotonic + s->watchdog_usec);
if (r < 0) {
log_warning_unit(UNIT(s)->id, "%s failed to reset watchdog timer: %s", UNIT(s)->id, strerror(-r));
return;
}
r = sd_event_source_set_enabled(s->watchdog_event_source, SD_EVENT_ON);
} else
r = sd_event_add_monotonic(UNIT(s)->manager->event, s->watchdog_timestamp.monotonic + s->watchdog_usec, 0, service_dispatch_watchdog, s, &s->watchdog_event_source);
if (r < 0)
log_warning_unit(UNIT(s)->id,
"%s failed to install watchdog timer: %s",
@ -327,7 +338,28 @@ static void service_done(Unit *u) {
service_stop_watchdog(s);
unit_unwatch_timer(u, &s->timer_watch);
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
}
static int service_arm_timer(Service *s, usec_t usec) {
int r;
assert(s);
if (usec <= 0) {
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
return 0;
}
if (s->timer_event_source) {
r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + usec);
if (r < 0)
return r;
return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
}
return sd_event_add_monotonic(UNIT(s)->manager->event, now(CLOCK_MONOTONIC) + usec, 0, service_dispatch_timer, s, &s->timer_event_source);
}
#ifdef HAVE_SYSV_COMPAT
@ -1214,9 +1246,11 @@ static int service_load(Unit *u) {
return r;
#endif
if (s->bus_name)
if ((r = unit_watch_bus_name(u, s->bus_name)) < 0)
if (s->bus_name) {
r = unit_watch_bus_name(u, s->bus_name);
if (r < 0)
return r;
}
if (s->type == SERVICE_NOTIFY && s->notify_access == NOTIFY_NONE)
s->notify_access = NOTIFY_MAIN;
@ -1467,7 +1501,7 @@ static void service_set_state(Service *s, ServiceState state) {
state != SERVICE_FINAL_SIGTERM &&
state != SERVICE_FINAL_SIGKILL &&
state != SERVICE_AUTO_RESTART)
unit_unwatch_timer(UNIT(s), &s->timer_watch);
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
if (state != SERVICE_START &&
state != SERVICE_START_POST &&
@ -1567,11 +1601,12 @@ static int service_coldplug(Unit *u) {
s->deserialized_state == SERVICE_AUTO_RESTART) {
if (s->deserialized_state == SERVICE_AUTO_RESTART || s->timeout_start_usec > 0) {
usec_t k;
k = s->deserialized_state == SERVICE_AUTO_RESTART ? s->restart_usec : s->timeout_start_usec;
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, k, &s->timer_watch);
r = service_arm_timer(s,
s->deserialized_state == SERVICE_AUTO_RESTART ? s->restart_usec :
s->deserialized_state == SERVICE_START_PRE || s->deserialized_state == SERVICE_START ||
s->deserialized_state == SERVICE_START_POST || s->deserialized_state == SERVICE_RELOAD ? s->timeout_start_usec :
s->timeout_stop_usec);
if (r < 0)
return r;
}
@ -1728,13 +1763,9 @@ static int service_spawn(
}
}
if (timeout && s->timeout_start_usec) {
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true,
s->timeout_start_usec, &s->timer_watch);
if (r < 0)
goto fail;
} else
unit_unwatch_timer(UNIT(s), &s->timer_watch);
r = service_arm_timer(s, timeout ? s->timeout_start_usec : 0);
if (r < 0)
goto fail;
r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
if (r < 0)
@ -1810,7 +1841,7 @@ static int service_spawn(
fail:
if (timeout)
unit_unwatch_timer(UNIT(s), &s->timer_watch);
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
return r;
}
@ -1881,10 +1912,9 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
(s->result != SERVICE_FAILURE_EXIT_CODE ||
!set_contains(s->restart_ignore_status.code, INT_TO_PTR(s->main_exec_status.status))) &&
(s->result != SERVICE_FAILURE_SIGNAL ||
!set_contains(s->restart_ignore_status.signal, INT_TO_PTR(s->main_exec_status.status)))
) {
!set_contains(s->restart_ignore_status.signal, INT_TO_PTR(s->main_exec_status.status)))) {
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->restart_usec, &s->timer_watch);
r = service_arm_timer(s, s->restart_usec);
if (r < 0)
goto fail;
@ -1971,8 +2001,7 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
if (r > 0) {
if (s->timeout_stop_usec > 0) {
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true,
s->timeout_stop_usec, &s->timer_watch);
r = service_arm_timer(s, s->timeout_stop_usec);
if (r < 0)
goto fail;
}
@ -2225,18 +2254,17 @@ fail:
}
static void service_enter_restart(Service *s) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
DBusError error;
assert(s);
dbus_error_init(&error);
if (UNIT(s)->job && UNIT(s)->job->type == JOB_STOP) {
/* Don't restart things if we are going down anyway */
log_info_unit(UNIT(s)->id,
"Stop job pending for unit, delaying automatic restart.");
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->restart_usec, &s->timer_watch);
r = service_arm_timer(s, s->restart_usec);
if (r < 0)
goto fail;
@ -2262,10 +2290,8 @@ static void service_enter_restart(Service *s) {
fail:
log_warning_unit(UNIT(s)->id,
"%s failed to schedule restart job: %s",
UNIT(s)->id, bus_error(&error, -r));
UNIT(s)->id, bus_error_message(&error, -r));
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false);
dbus_error_free(&error);
}
static void service_enter_reload(Service *s) {
@ -2402,22 +2428,18 @@ static int service_start_limit_test(Service *s) {
break;
case SERVICE_START_LIMIT_REBOOT: {
DBusError error;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
dbus_error_init(&error);
log_warning_unit(UNIT(s)->id,
"%s start request repeated too quickly, rebooting.", UNIT(s)->id);
r = manager_add_job_by_name(UNIT(s)->manager, JOB_START,
SPECIAL_REBOOT_TARGET, JOB_REPLACE,
true, &error, NULL);
if (r < 0) {
if (r < 0)
log_error_unit(UNIT(s)->id,
"Failed to reboot: %s.", bus_error(&error, r));
dbus_error_free(&error);
}
"Failed to reboot: %s.", bus_error_message(&error, r));
break;
}
@ -2837,7 +2859,7 @@ static int service_watch_pid_file(Service *s) {
log_debug_unit(UNIT(s)->id,
"Setting watch for %s's PID file %s",
UNIT(s)->id, s->pid_file_pathspec->path);
r = path_spec_watch(s->pid_file_pathspec, UNIT(s));
r = path_spec_watch(s->pid_file_pathspec, service_dispatch_io);
if (r < 0)
goto fail;
@ -2866,6 +2888,7 @@ static int service_demand_pid_file(Service *s) {
if (!ps)
return -ENOMEM;
ps->unit = UNIT(s);
ps->path = strdup(s->pid_file);
if (!ps->path) {
free(ps);
@ -2884,8 +2907,8 @@ static int service_demand_pid_file(Service *s) {
return service_watch_pid_file(s);
}
static void service_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
Service *s = SERVICE(u);
static int service_dispatch_io(sd_event_source *source, int fd, uint32_t events, void *userdata) {
Service *s = SERVICE(userdata);
assert(s);
assert(fd >= 0);
@ -2893,21 +2916,23 @@ static void service_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
assert(s->pid_file_pathspec);
assert(path_spec_owns_inotify_fd(s->pid_file_pathspec, fd));
log_debug_unit(u->id, "inotify event for %s", u->id);
log_debug_unit(UNIT(s)->id, "inotify event for %s", UNIT(s)->id);
if (path_spec_fd_event(s->pid_file_pathspec, events) < 0)
goto fail;
if (service_retry_pid_file(s) == 0)
return;
return 0;
if (service_watch_pid_file(s) < 0)
goto fail;
return;
return 0;
fail:
service_unwatch_pid_file(s);
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
return 0;
}
static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
@ -3180,55 +3205,48 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
unit_add_to_dbus_queue(u);
}
static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) {
Service *s = SERVICE(u);
static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
Service *s = SERVICE(userdata);
assert(s);
assert(elapsed == 1);
if (w == &s->watchdog_watch) {
service_handle_watchdog(s);
return;
}
assert(w == &s->timer_watch);
assert(source == s->timer_event_source);
switch (s->state) {
case SERVICE_START_PRE:
case SERVICE_START:
log_warning_unit(u->id,
"%s operation timed out. Terminating.", u->id);
log_warning_unit(UNIT(s)->id,
"%s operation timed out. Terminating.", UNIT(s)->id);
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_START_POST:
log_warning_unit(u->id,
"%s operation timed out. Stopping.", u->id);
log_warning_unit(UNIT(s)->id,
"%s operation timed out. Stopping.", UNIT(s)->id);
service_enter_stop(s, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_RELOAD:
log_warning_unit(u->id,
"%s operation timed out. Stopping.", u->id);
log_warning_unit(UNIT(s)->id,
"%s operation timed out. Stopping.", UNIT(s)->id);
s->reload_result = SERVICE_FAILURE_TIMEOUT;
service_enter_running(s, SERVICE_SUCCESS);
break;
case SERVICE_STOP:
log_warning_unit(u->id,
"%s stopping timed out. Terminating.", u->id);
log_warning_unit(UNIT(s)->id,
"%s stopping timed out. Terminating.", UNIT(s)->id);
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_STOP_SIGTERM:
if (s->kill_context.send_sigkill) {
log_warning_unit(u->id,
"%s stopping timed out. Killing.", u->id);
log_warning_unit(UNIT(s)->id,
"%s stopping timed out. Killing.", UNIT(s)->id);
service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_TIMEOUT);
} else {
log_warning_unit(u->id,
"%s stopping timed out. Skipping SIGKILL.", u->id);
log_warning_unit(UNIT(s)->id,
"%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id);
service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT);
}
@ -3239,46 +3257,58 @@ static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) {
* Must be something we cannot kill, so let's just be
* weirded out and continue */
log_warning_unit(u->id,
"%s still around after SIGKILL. Ignoring.", u->id);
log_warning_unit(UNIT(s)->id,
"%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_STOP_POST:
log_warning_unit(u->id,
"%s stopping timed out (2). Terminating.", u->id);
log_warning_unit(UNIT(s)->id,
"%s stopping timed out (2). Terminating.", UNIT(s)->id);
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_FINAL_SIGTERM:
if (s->kill_context.send_sigkill) {
log_warning_unit(u->id,
"%s stopping timed out (2). Killing.", u->id);
log_warning_unit(UNIT(s)->id,
"%s stopping timed out (2). Killing.", UNIT(s)->id);
service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_FAILURE_TIMEOUT);
} else {
log_warning_unit(u->id,
log_warning_unit(UNIT(s)->id,
"%s stopping timed out (2). Skipping SIGKILL. Entering failed mode.",
u->id);
UNIT(s)->id);
service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, false);
}
break;
case SERVICE_FINAL_SIGKILL:
log_warning_unit(u->id,
"%s still around after SIGKILL (2). Entering failed mode.", u->id);
log_warning_unit(UNIT(s)->id,
"%s still around after SIGKILL (2). Entering failed mode.", UNIT(s)->id);
service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, true);
break;
case SERVICE_AUTO_RESTART:
log_info_unit(u->id,
"%s holdoff time over, scheduling restart.", u->id);
log_info_unit(UNIT(s)->id,
"%s holdoff time over, scheduling restart.", UNIT(s)->id);
service_enter_restart(s);
break;
default:
assert_not_reached("Timeout at wrong time.");
}
return 0;
}
static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata) {
Service *s = SERVICE(userdata);
assert(s);
assert(source == s->watchdog_event_source);
service_handle_watchdog(s);
return 0;
}
static void service_notify_cgroup_empty_event(Unit *u) {
@ -3606,6 +3636,7 @@ static void service_bus_name_owner_change(
const char *new_owner) {
Service *s = SERVICE(u);
int r;
assert(s);
assert(name);
@ -3644,35 +3675,17 @@ static void service_bus_name_owner_change(
s->state == SERVICE_RUNNING ||
s->state == SERVICE_RELOAD)) {
pid_t pid;
/* 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);
}
}
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);
static void service_bus_query_pid_done(
Unit *u,
const char *name,
pid_t pid) {
Service *s = SERVICE(u);
assert(s);
assert(name);
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...",

View File

@ -130,7 +130,7 @@ struct Service {
dual_timestamp watchdog_timestamp;
usec_t watchdog_usec;
Watch watchdog_watch;
sd_event_source *watchdog_event_source;
ExecCommand* exec_command[_SERVICE_EXEC_COMMAND_MAX];
@ -191,7 +191,7 @@ struct Service {
UnitRef accept_socket;
Watch timer_watch;
sd_event_source *timer_event_source;
PathSpec *pid_file_pathspec;
NotifyAccess notify_access;

View File

@ -216,7 +216,7 @@ static int slice_stop(Unit *u) {
return 0;
}
static int slice_kill(Unit *u, KillWho who, int signo, DBusError *error) {
static int slice_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
return unit_kill_common(u, who, signo, -1, -1, error);
}
@ -275,13 +275,13 @@ DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
const UnitVTable slice_vtable = {
.object_size = sizeof(Slice),
.cgroup_context_offset = offsetof(Slice, cgroup_context),
.sections =
"Unit\0"
"Slice\0"
"Install\0",
.private_section = "Slice",
.cgroup_context_offset = offsetof(Slice, cgroup_context),
.no_alias = true,
.no_instances = true,
@ -306,7 +306,7 @@ const UnitVTable slice_vtable = {
.sub_state_to_string = slice_sub_state_to_string,
.bus_interface = "org.freedesktop.systemd1.Slice",
.bus_message_handler = bus_slice_message_handler,
.bus_vtable = bus_slice_vtable,
.bus_set_property = bus_slice_set_property,
.bus_commit_properties = bus_slice_commit_properties,

View File

@ -189,7 +189,7 @@ _pure_ static const char *snapshot_sub_state_to_string(Unit *u) {
return snapshot_state_to_string(SNAPSHOT(u)->state);
}
int snapshot_create(Manager *m, const char *name, bool cleanup, DBusError *e, Snapshot **_s) {
int snapshot_create(Manager *m, const char *name, bool cleanup, sd_bus_error *e, Snapshot **_s) {
_cleanup_free_ char *n = NULL;
Unit *other, *u = NULL;
Iterator i;
@ -200,20 +200,14 @@ int snapshot_create(Manager *m, const char *name, bool cleanup, DBusError *e, Sn
assert(_s);
if (name) {
if (!unit_name_is_valid(name, false)) {
dbus_set_error(e, BUS_ERROR_INVALID_NAME, "Unit name %s is not valid.", name);
return -EINVAL;
}
if (!unit_name_is_valid(name, false))
return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name);
if (unit_name_to_type(name) != UNIT_SNAPSHOT) {
dbus_set_error(e, BUS_ERROR_UNIT_TYPE_MISMATCH, "Unit name %s lacks snapshot suffix.", name);
return -EINVAL;
}
if (unit_name_to_type(name) != UNIT_SNAPSHOT)
return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s lacks snapshot suffix.", name);
if (manager_get_unit(m, name)) {
dbus_set_error(e, BUS_ERROR_UNIT_EXISTS, "Snapshot %s exists already.", name);
return -EEXIST;
}
if (manager_get_unit(m, name))
sd_bus_error_setf(e, BUS_ERROR_UNIT_EXISTS, "Snapshot %s exists already.", name);
} else {
@ -293,8 +287,8 @@ const UnitVTable snapshot_vtable = {
.no_gc = true,
.init = snapshot_init,
.load = snapshot_load,
.coldplug = snapshot_coldplug,
.dump = snapshot_dump,
@ -309,5 +303,5 @@ const UnitVTable snapshot_vtable = {
.sub_state_to_string = snapshot_sub_state_to_string,
.bus_interface = "org.freedesktop.systemd1.Snapshot",
.bus_message_handler = bus_snapshot_message_handler
.bus_vtable = bus_snapshot_vtable
};

View File

@ -42,7 +42,7 @@ struct Snapshot {
extern const UnitVTable snapshot_vtable;
int snapshot_create(Manager *m, const char *name, bool cleanup, DBusError *e, Snapshot **s);
int snapshot_create(Manager *m, const char *name, bool cleanup, sd_bus_error *e, Snapshot **s);
void snapshot_remove(Snapshot *s);
const char* snapshot_state_to_string(SnapshotState i) _const_;

View File

@ -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,

View File

@ -77,12 +77,14 @@ typedef enum SocketResult {
} SocketResult;
typedef struct SocketPort {
Socket *socket;
SocketType type;
int fd;
SocketAddress address;
char *path;
Watch fd_watch;
sd_event_source *event_source;
LIST_FIELDS(struct SocketPort, port);
} SocketPort;
@ -111,7 +113,7 @@ struct Socket {
SocketState state, deserialized_state;
Watch timer_watch;
sd_event_source *timer_event_source;
ExecCommand* control_command;
SocketExecCommand control_command_id;
@ -144,7 +146,7 @@ struct Socket {
size_t pipe_size;
char *bind_to_device;
char *tcp_congestion;
bool reuseport;
bool reuse_port;
long mq_maxmsg;
long mq_msgsize;

View File

@ -53,6 +53,9 @@ static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
[SWAP_FAILED] = UNIT_FAILED
};
static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static void swap_unset_proc_swaps(Swap *s) {
Swap *first;
Hashmap *swaps;
@ -96,8 +99,6 @@ static void swap_init(Unit *u) {
s->parameters_proc_swaps.priority = s->parameters_fragment.priority = -1;
s->timer_watch.type = WATCH_INVALID;
s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
UNIT(s)->ignore_on_isolate = true;
@ -134,7 +135,28 @@ static void swap_done(Unit *u) {
swap_unwatch_control_pid(s);
unit_unwatch_timer(u, &s->timer_watch);
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
}
static int swap_arm_timer(Swap *s) {
int r;
assert(s);
if (s->timeout_usec <= 0) {
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
return 0;
}
if (s->timer_event_source) {
r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec);
if (r < 0)
return r;
return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
}
return sd_event_add_monotonic(UNIT(s)->manager->event, now(CLOCK_MONOTONIC) + s->timeout_usec, 0, swap_dispatch_timer, s, &s->timer_event_source);
}
static int swap_add_device_links(Swap *s) {
@ -465,7 +487,7 @@ static void swap_set_state(Swap *s, SwapState state) {
state != SWAP_DEACTIVATING &&
state != SWAP_DEACTIVATING_SIGTERM &&
state != SWAP_DEACTIVATING_SIGKILL) {
unit_unwatch_timer(UNIT(s), &s->timer_watch);
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
swap_unwatch_control_pid(s);
s->control_command = NULL;
s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
@ -511,7 +533,7 @@ static int swap_coldplug(Unit *u) {
if (r < 0)
return r;
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
r = swap_arm_timer(s);
if (r < 0)
return r;
}
@ -576,7 +598,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
unit_realize_cgroup(UNIT(s));
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
r = swap_arm_timer(s);
if (r < 0)
goto fail;
@ -607,7 +629,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
return 0;
fail:
unit_unwatch_timer(UNIT(s), &s->timer_watch);
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
return r;
}
@ -650,7 +672,7 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
goto fail;
if (r > 0) {
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
r = swap_arm_timer(s);
if (r < 0)
goto fail;
@ -977,54 +999,55 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
u->manager->request_reload = true;
}
static void swap_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
Swap *s = SWAP(u);
static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
Swap *s = SWAP(userdata);
assert(s);
assert(elapsed == 1);
assert(w == &s->timer_watch);
assert(s->timer_event_source == source);
switch (s->state) {
case SWAP_ACTIVATING:
log_warning_unit(u->id, "%s activation timed out. Stopping.", u->id);
log_warning_unit(UNIT(s)->id, "%s activation timed out. Stopping.", UNIT(s)->id);
swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
break;
case SWAP_DEACTIVATING:
log_warning_unit(u->id, "%s deactivation timed out. Stopping.", u->id);
log_warning_unit(UNIT(s)->id, "%s deactivation timed out. Stopping.", UNIT(s)->id);
swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
break;
case SWAP_ACTIVATING_SIGTERM:
if (s->kill_context.send_sigkill) {
log_warning_unit(u->id, "%s activation timed out. Killing.", u->id);
log_warning_unit(UNIT(s)->id, "%s activation timed out. Killing.", UNIT(s)->id);
swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
} else {
log_warning_unit(u->id, "%s activation timed out. Skipping SIGKILL. Ignoring.", u->id);
log_warning_unit(UNIT(s)->id, "%s activation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id);
swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
}
break;
case SWAP_DEACTIVATING_SIGTERM:
if (s->kill_context.send_sigkill) {
log_warning_unit(u->id, "%s deactivation timed out. Killing.", u->id);
log_warning_unit(UNIT(s)->id, "%s deactivation timed out. Killing.", UNIT(s)->id);
swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
} else {
log_warning_unit(u->id, "%s deactivation timed out. Skipping SIGKILL. Ignoring.", u->id);
log_warning_unit(UNIT(s)->id, "%s deactivation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id);
swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
}
break;
case SWAP_ACTIVATING_SIGKILL:
case SWAP_DEACTIVATING_SIGKILL:
log_warning_unit(u->id, "%s swap process still around after SIGKILL. Ignoring.", u->id);
log_warning_unit(UNIT(s)->id, "%s swap process still around after SIGKILL. Ignoring.", UNIT(s)->id);
swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
break;
default:
assert_not_reached("Timeout at wrong time.");
}
return 0;
}
static int swap_load_proc_swaps(Manager *m, bool set_flags) {
@ -1068,23 +1091,13 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) {
return r;
}
int swap_dispatch_reload(Manager *m) {
/* This function should go as soon as the kernel properly notifies us */
if (_likely_(!m->request_reload))
return 0;
m->request_reload = false;
return swap_fd_event(m, EPOLLPRI);
}
int swap_fd_event(Manager *m, int events) {
static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
Unit *u;
int r;
assert(m);
assert(events & EPOLLPRI);
assert(revents & EPOLLPRI);
r = swap_load_proc_swaps(m, true);
if (r < 0) {
@ -1212,6 +1225,8 @@ fail:
static void swap_shutdown(Manager *m) {
assert(m);
m->swap_event_source = sd_event_source_unref(m->swap_event_source);
if (m->proc_swaps) {
fclose(m->proc_swaps);
m->proc_swaps = NULL;
@ -1226,26 +1241,23 @@ static int swap_enumerate(Manager *m) {
assert(m);
if (!m->proc_swaps) {
struct epoll_event ev = {
.events = EPOLLPRI,
.data.ptr = &m->swap_watch,
};
m->proc_swaps = fopen("/proc/swaps", "re");
if (!m->proc_swaps)
return (errno == ENOENT) ? 0 : -errno;
return errno == ENOENT ? 0 : -errno;
m->swap_watch.type = WATCH_SWAP;
m->swap_watch.fd = fileno(m->proc_swaps);
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,

View File

@ -96,7 +96,7 @@ struct Swap {
SwapExecCommand control_command_id;
pid_t control_pid;
Watch timer_watch;
sd_event_source *timer_event_source;
/* In order to be able to distinguish dependencies on
different device nodes we might end up creating multiple
@ -107,9 +107,6 @@ struct Swap {
extern const UnitVTable swap_vtable;
int swap_dispatch_reload(Manager *m);
int swap_fd_event(Manager *m, int events);
const char* swap_state_to_string(SwapState i) _const_;
SwapState swap_state_from_string(const char *s) _pure_;

View File

@ -205,6 +205,7 @@ DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
const UnitVTable target_vtable = {
.object_size = sizeof(Target),
.sections =
"Unit\0"
"Target\0"
@ -225,7 +226,7 @@ const UnitVTable target_vtable = {
.sub_state_to_string = target_sub_state_to_string,
.bus_interface = "org.freedesktop.systemd1.Target",
.bus_message_handler = bus_target_message_handler,
.bus_vtable = bus_target_vtable,
.status_message_formats = {
.finished_start_job = {

View File

@ -26,7 +26,8 @@
#include "timer.h"
#include "dbus-timer.h"
#include "special.h"
#include "dbus-common.h"
#include "bus-util.h"
#include "bus-error.h"
static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
[TIMER_DEAD] = UNIT_INACTIVE,
@ -36,6 +37,8 @@ static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
[TIMER_FAILED] = UNIT_FAILED
};
static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata);
static void timer_init(Unit *u) {
Timer *t = TIMER(u);
@ -44,8 +47,6 @@ static void timer_init(Unit *u) {
t->next_elapse_monotonic = (usec_t) -1;
t->next_elapse_realtime = (usec_t) -1;
watch_init(&t->monotonic_watch);
watch_init(&t->realtime_watch);
}
void timer_free_values(Timer *t) {
@ -70,8 +71,8 @@ static void timer_done(Unit *u) {
timer_free_values(t);
unit_unwatch_timer(u, &t->monotonic_watch);
unit_unwatch_timer(u, &t->realtime_watch);
t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
}
static int timer_verify(Timer *t) {
@ -189,8 +190,8 @@ static void timer_set_state(Timer *t, TimerState state) {
t->state = state;
if (state != TIMER_WAITING) {
unit_unwatch_timer(UNIT(t), &t->monotonic_watch);
unit_unwatch_timer(UNIT(t), &t->realtime_watch);
t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
}
if (state != old_state)
@ -230,6 +231,7 @@ static void timer_enter_dead(Timer *t, TimerResult f) {
timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
}
static void timer_enter_waiting(Timer *t, bool initial) {
TimerValue *v;
usec_t base = 0;
@ -337,11 +339,24 @@ static void timer_enter_waiting(Timer *t, bool initial) {
UNIT(t)->id,
format_timespan(buf, sizeof(buf), t->next_elapse_monotonic > ts.monotonic ? t->next_elapse_monotonic - ts.monotonic : 0, 0));
r = unit_watch_timer(UNIT(t), CLOCK_MONOTONIC, false, t->next_elapse_monotonic, &t->monotonic_watch);
if (t->monotonic_event_source) {
r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic);
if (r < 0)
goto fail;
r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT);
} else
r = sd_event_add_monotonic(UNIT(t)->manager->event, t->next_elapse_monotonic, 0, timer_dispatch, t, &t->monotonic_event_source);
if (r < 0)
goto fail;
} else
unit_unwatch_timer(UNIT(t), &t->monotonic_watch);
} else if (t->monotonic_event_source) {
r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF);
if (r < 0)
goto fail;
}
if (found_realtime) {
char buf[FORMAT_TIMESTAMP_MAX];
@ -350,11 +365,24 @@ static void timer_enter_waiting(Timer *t, bool initial) {
UNIT(t)->id,
format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
r = unit_watch_timer(UNIT(t), CLOCK_REALTIME, false, t->next_elapse_realtime, &t->realtime_watch);
if (t->realtime_event_source) {
r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime);
if (r < 0)
goto fail;
r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT);
} else
r = sd_event_add_realtime(UNIT(t)->manager->event, t->next_elapse_realtime, 0, timer_dispatch, t, &t->realtime_event_source);
if (r < 0)
goto fail;
} else
unit_unwatch_timer(UNIT(t), &t->realtime_watch);
} else if (t->realtime_event_source) {
r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF);
if (r < 0)
goto fail;
}
timer_set_state(t, TIMER_WAITING);
return;
@ -367,11 +395,10 @@ fail:
}
static void timer_enter_running(Timer *t) {
DBusError error;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(t);
dbus_error_init(&error);
/* Don't start job if we are supposed to go down */
if (unit_stop_pending(UNIT(t)))
@ -390,10 +417,8 @@ static void timer_enter_running(Timer *t) {
fail:
log_warning_unit(UNIT(t)->id,
"%s failed to queue unit startup job: %s",
UNIT(t)->id, bus_error(&error, r));
UNIT(t)->id, bus_error_message(&error, r));
timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
dbus_error_free(&error);
}
static int timer_start(Unit *u) {
@ -476,17 +501,17 @@ _pure_ static const char *timer_sub_state_to_string(Unit *u) {
return timer_state_to_string(TIMER(u)->state);
}
static void timer_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
Timer *t = TIMER(u);
static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
Timer *t = TIMER(userdata);
assert(t);
assert(elapsed == 1);
if (t->state != TIMER_WAITING)
return;
return 0;
log_debug_unit(u->id, "Timer elapsed on %s", u->id);
log_debug_unit(UNIT(t)->id, "Timer elapsed on %s", UNIT(t)->id);
timer_enter_running(t);
return 0;
}
static void timer_trigger_notify(Unit *u, Unit *other) {
@ -587,6 +612,7 @@ DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
const UnitVTable timer_vtable = {
.object_size = sizeof(Timer),
.sections =
"Unit\0"
"Timer\0"
@ -609,14 +635,12 @@ const UnitVTable timer_vtable = {
.active_state = timer_active_state,
.sub_state_to_string = timer_sub_state_to_string,
.timer_event = timer_timer_event,
.trigger_notify = timer_trigger_notify,
.reset_failed = timer_reset_failed,
.time_change = timer_time_change,
.bus_interface = "org.freedesktop.systemd1.Timer",
.bus_message_handler = bus_timer_message_handler,
.bus_invalidating_properties = bus_timer_invalidating_properties
.bus_vtable = bus_timer_vtable,
.bus_changing_properties = bus_timer_changing_properties,
};

View File

@ -75,8 +75,8 @@ struct Timer {
TimerState state, deserialized_state;
Watch monotonic_watch;
Watch realtime_watch;
sd_event_source *monotonic_event_source;
sd_event_source *realtime_event_source;
TimerResult result;

View File

@ -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);
}
}
}

View File

@ -48,7 +48,7 @@ int transaction_add_job_and_dependencies(
bool conflicts,
bool ignore_requirements,
bool ignore_order,
DBusError *e);
int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e);
sd_bus_error *e);
int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error *e);
int transaction_add_isolate_jobs(Transaction *tr, Manager *m);
void transaction_abort(Transaction *tr);

View File

@ -29,8 +29,8 @@
#include <unistd.h>
#include <sys/stat.h>
#include "systemd/sd-id128.h"
#include "systemd/sd-messages.h"
#include "sd-id128.h"
#include "sd-messages.h"
#include "set.h"
#include "unit.h"
#include "macro.h"
@ -48,6 +48,7 @@
#include "label.h"
#include "fileio-label.h"
#include "bus-errors.h"
#include "dbus.h"
const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
[UNIT_SERVICE] = &service_vtable,
@ -326,7 +327,7 @@ void unit_add_to_dbus_queue(Unit *u) {
return;
/* Shortcut things if nobody cares */
if (!bus_has_subscriber(u->manager)) {
if (set_isempty(u->manager->subscribed)) {
u->sent_dbus_new_signal = true;
return;
}
@ -1658,46 +1659,6 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
unit_add_to_gc_queue(u);
}
int unit_watch_fd(Unit *u, int fd, uint32_t events, Watch *w) {
struct epoll_event ev = {
.data.ptr = w,
.events = events,
};
assert(u);
assert(fd >= 0);
assert(w);
assert(w->type == WATCH_INVALID || (w->type == WATCH_FD && w->fd == fd && w->data.unit == u));
if (epoll_ctl(u->manager->epoll_fd,
w->type == WATCH_INVALID ? EPOLL_CTL_ADD : EPOLL_CTL_MOD,
fd,
&ev) < 0)
return -errno;
w->fd = fd;
w->type = WATCH_FD;
w->data.unit = u;
return 0;
}
void unit_unwatch_fd(Unit *u, Watch *w) {
assert(u);
assert(w);
if (w->type == WATCH_INVALID)
return;
assert(w->type == WATCH_FD);
assert(w->data.unit == u);
assert_se(epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
w->fd = -1;
w->type = WATCH_INVALID;
w->data.unit = NULL;
}
int unit_watch_pid(Unit *u, pid_t pid) {
assert(u);
assert(pid >= 1);
@ -1715,90 +1676,6 @@ void unit_unwatch_pid(Unit *u, pid_t pid) {
hashmap_remove_value(u->manager->watch_pids, LONG_TO_PTR(pid), u);
}
int unit_watch_timer(Unit *u, clockid_t clock_id, bool relative, usec_t usec, Watch *w) {
struct itimerspec its = {};
int flags, fd;
bool ours;
assert(u);
assert(w);
assert(w->type == WATCH_INVALID || (w->type == WATCH_UNIT_TIMER && w->data.unit == u));
/* This will try to reuse the old timer if there is one */
if (w->type == WATCH_UNIT_TIMER) {
assert(w->data.unit == u);
assert(w->fd >= 0);
ours = false;
fd = w->fd;
} else if (w->type == WATCH_INVALID) {
ours = true;
fd = timerfd_create(clock_id, TFD_NONBLOCK|TFD_CLOEXEC);
if (fd < 0)
return -errno;
} else
assert_not_reached("Invalid watch type");
if (usec <= 0) {
/* Set absolute time in the past, but not 0, since we
* don't want to disarm the timer */
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 1;
flags = TFD_TIMER_ABSTIME;
} else {
timespec_store(&its.it_value, usec);
flags = relative ? 0 : TFD_TIMER_ABSTIME;
}
/* This will also flush the elapse counter */
if (timerfd_settime(fd, flags, &its, NULL) < 0)
goto fail;
if (w->type == WATCH_INVALID) {
struct epoll_event ev = {
.data.ptr = w,
.events = EPOLLIN,
};
if (epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
goto fail;
}
w->type = WATCH_UNIT_TIMER;
w->fd = fd;
w->data.unit = u;
return 0;
fail:
if (ours)
close_nointr_nofail(fd);
return -errno;
}
void unit_unwatch_timer(Unit *u, Watch *w) {
assert(u);
assert(w);
if (w->type == WATCH_INVALID)
return;
assert(w->type == WATCH_UNIT_TIMER);
assert(w->data.unit == u);
assert(w->fd >= 0);
assert_se(epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
close_nointr_nofail(w->fd);
w->fd = -1;
w->type = WATCH_INVALID;
w->data.unit = NULL;
}
bool unit_job_is_applicable(Unit *u, JobType j) {
assert(u);
assert(j >= 0 && j < _JOB_TYPE_MAX);
@ -2572,7 +2449,7 @@ bool unit_active_or_pending(Unit *u) {
return false;
}
int unit_kill(Unit *u, KillWho w, int signo, DBusError *error) {
int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error) {
assert(u);
assert(w >= 0 && w < _KILL_WHO_MAX);
assert(signo > 0);
@ -2618,23 +2495,23 @@ int unit_kill_common(
int signo,
pid_t main_pid,
pid_t control_pid,
DBusError *error) {
sd_bus_error *error) {
int r = 0;
if (who == KILL_MAIN && main_pid <= 0) {
if (main_pid < 0)
dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
else
dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
return -ESRCH;
}
if (who == KILL_CONTROL && control_pid <= 0) {
if (control_pid < 0)
dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type));
sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type));
else
dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
return -ESRCH;
}
@ -2746,6 +2623,17 @@ ExecContext *unit_get_exec_context(Unit *u) {
return (ExecContext*) ((uint8_t*) u + offset);
}
KillContext *unit_get_kill_context(Unit *u) {
size_t offset;
assert(u);
offset = UNIT_VTABLE(u)->kill_context_offset;
if (offset <= 0)
return NULL;
return (KillContext*) ((uint8_t*) u + offset);
}
CGroupContext *unit_get_cgroup_context(Unit *u) {
size_t offset;

View File

@ -32,6 +32,7 @@ typedef enum UnitDependency UnitDependency;
typedef struct UnitRef UnitRef;
typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
#include "sd-event.h"
#include "set.h"
#include "util.h"
#include "list.h"
@ -295,6 +296,10 @@ struct UnitVTable {
* CGroupContext is found, if the unit type has that */
size_t cgroup_context_offset;
/* If greater than 0, the offset into the object where
* KillContext is found, if the unit type has that */
size_t kill_context_offset;
/* The name of the configuration file section with the private settings of this unit*/
const char *private_section;
@ -327,7 +332,7 @@ struct UnitVTable {
int (*stop)(Unit *u);
int (*reload)(Unit *u);
int (*kill)(Unit *u, KillWho w, int signo, DBusError *error);
int (*kill)(Unit *u, KillWho w, int signo, sd_bus_error *error);
bool (*can_reload)(Unit *u);
@ -359,9 +364,8 @@ struct UnitVTable {
/* Return true when this unit is suitable for snapshotting */
bool (*check_snapshot)(Unit *u);
void (*fd_event)(Unit *u, int fd, uint32_t events, Watch *w);
/* Invoked on every child that died */
void (*sigchld_event)(Unit *u, pid_t pid, int code, int status);
void (*timer_event)(Unit *u, uint64_t n_elapsed, Watch *w);
/* Reset failed state if we are in failed state */
void (*reset_failed)(Unit *u);
@ -377,14 +381,8 @@ struct UnitVTable {
* goes away. */
void (*bus_name_owner_change)(Unit *u, const char *name, const char *old_owner, const char *new_owner);
/* Called whenever a bus PID lookup finishes */
void (*bus_query_pid_done)(Unit *u, const char *name, pid_t pid);
/* Called for each message received on the bus */
DBusHandlerResult (*bus_message_handler)(Unit *u, DBusConnection *c, DBusMessage *message);
/* Called for each property that is being set */
int (*bus_set_property)(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
/* Called after at least one property got changed to apply the necessary change */
int (*bus_commit_properties)(Unit *u);
@ -412,14 +410,16 @@ struct UnitVTable {
/* Type specific cleanups. */
void (*shutdown)(Manager *m);
/* When sending out PropertiesChanged signal, which properties
* shall be invalidated? This is a NUL separated list of
* strings, to minimize relocations a little. */
const char *bus_invalidating_properties;
/* The interface name */
const char *bus_interface;
/* The bus vtable */
const sd_bus_vtable *bus_vtable;
/* strv list of changing properties */
const char * const * const bus_changing_properties;
/* The strings to print in status messages */
UnitStatusMessageFormats status_message_formats;
/* Can units of this type have multiple names? */
@ -521,20 +521,14 @@ int unit_start(Unit *u);
int unit_stop(Unit *u);
int unit_reload(Unit *u);
int unit_kill(Unit *u, KillWho w, int signo, DBusError *error);
int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t control_pid, DBusError *error);
int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error);
int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t control_pid, sd_bus_error *error);
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success);
int unit_watch_fd(Unit *u, int fd, uint32_t events, Watch *w);
void unit_unwatch_fd(Unit *u, Watch *w);
int unit_watch_pid(Unit *u, pid_t pid);
void unit_unwatch_pid(Unit *u, pid_t pid);
int unit_watch_timer(Unit *u, clockid_t, bool relative, usec_t usec, Watch *w);
void unit_unwatch_timer(Unit *u, Watch *w);
int unit_watch_bus_name(Unit *u, const char *name);
void unit_unwatch_bus_name(Unit *u, const char *name);
@ -590,6 +584,7 @@ void unit_ref_unset(UnitRef *ref);
int unit_exec_context_defaults(Unit *u, ExecContext *c);
ExecContext *unit_get_exec_context(Unit *u) _pure_;
KillContext *unit_get_kill_context(Unit *u) _pure_;
CGroupContext *unit_get_cgroup_context(Unit *u) _pure_;
int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data);

View File

@ -21,6 +21,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdbool.h>
#include "sd-bus.h"
bool bus_error_is_dirty(sd_bus_error *e);

View File

@ -119,11 +119,12 @@ enum bus_state {
BUS_AUTHENTICATING,
BUS_HELLO,
BUS_RUNNING,
BUS_CLOSING,
BUS_CLOSED
};
static inline bool BUS_IS_OPEN(enum bus_state state) {
return state > BUS_UNSET && state < BUS_CLOSED;
return state > BUS_UNSET && state < BUS_CLOSING;
}
enum bus_auth {
@ -155,7 +156,6 @@ struct sd_bus {
bool anonymous_auth:1;
bool prefer_readv:1;
bool prefer_writev:1;
bool processing:1;
bool match_callbacks_modified:1;
bool filter_callbacks_modified:1;
bool nodes_modified:1;

View File

@ -111,13 +111,10 @@ static int introspect_write_arguments(struct introspect *i, const char *signatur
}
}
int introspect_write_interface(struct introspect *i, const char *interface, const sd_bus_vtable *v) {
int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) {
assert(i);
assert(interface);
assert(v);
fprintf(i->f, " <interface name=\"%s\">\n", interface);
for (; v->type != _SD_BUS_VTABLE_END; v++) {
switch (v->type) {
@ -155,7 +152,6 @@ int introspect_write_interface(struct introspect *i, const char *interface, cons
}
fputs(" </interface>\n", i->f);
return 0;
}

View File

@ -36,6 +36,6 @@ struct introspect {
int introspect_begin(struct introspect *i);
int introspect_write_default_interfaces(struct introspect *i, bool object_manager);
int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix);
int introspect_write_interface(struct introspect *i, const char *interface, const sd_bus_vtable *v);
int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v);
int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply);
void introspect_free(struct introspect *i);

View File

@ -3294,6 +3294,7 @@ _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
return !isempty(c->signature);
}
static int message_read_ap(
sd_bus_message *m,
const char *types,

View File

@ -728,6 +728,7 @@ static int process_introspect(
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
_cleanup_set_free_free_ Set *s = NULL;
const char *previous_interface = NULL;
struct introspect intro;
struct node_vtable *c;
bool empty;
@ -768,11 +769,24 @@ static int process_introspect(
empty = false;
r = introspect_write_interface(&intro, c->interface, c->vtable);
if (!streq_ptr(previous_interface, c->interface)) {
if (previous_interface)
fputs(" </interface>\n", intro.f);
fprintf(intro.f, " <interface name=\"%s\">\n", c->interface);
}
r = introspect_write_interface(&intro, c->vtable);
if (r < 0)
goto finish;
previous_interface = c->interface;
}
if (previous_interface)
fputs(" </interface>\n", intro.f);
if (empty) {
/* Nothing?, let's see if we exist at all, and if not
* refuse to do anything */
@ -806,51 +820,6 @@ finish:
return r;
}
static int object_manager_serialize_vtable(
sd_bus *bus,
sd_bus_message *reply,
const char *path,
struct node_vtable *c,
sd_bus_error *error,
void *userdata) {
int r;
assert(bus);
assert(reply);
assert(path);
assert(c);
assert(error);
r = sd_bus_message_open_container(reply, 'e', "sa{sv}");
if (r < 0)
return r;
r = sd_bus_message_append(reply, "s", c->interface);
if (r < 0)
return r;
r = sd_bus_message_open_container(reply, 'a', "{sv}");
if (r < 0)
return r;
r = vtable_append_all_properties(bus, reply, path, c, userdata, error);
if (r < 0)
return r;
if (bus->nodes_modified)
return 0;
r = sd_bus_message_close_container(reply);
if (r < 0)
return r;
r = sd_bus_message_close_container(reply);
if (r < 0)
return r;
return 0;
}
static int object_manager_serialize_path(
sd_bus *bus,
sd_bus_message *reply,
@ -859,9 +828,10 @@ static int object_manager_serialize_path(
bool require_fallback,
sd_bus_error *error) {
const char *previous_interface = NULL;
bool found_something = false;
struct node_vtable *i;
struct node *n;
bool found_something = false;
int r;
assert(bus);
@ -889,6 +859,9 @@ static int object_manager_serialize_path(
continue;
if (!found_something) {
/* Open the object part */
r = sd_bus_message_open_container(reply, 'e', "oa{sa{sv}}");
if (r < 0)
return r;
@ -904,13 +877,54 @@ static int object_manager_serialize_path(
found_something = true;
}
r = object_manager_serialize_vtable(bus, reply, path, i, error, u);
if (!streq_ptr(previous_interface, i->interface)) {
/* Maybe close the previous interface part */
if (previous_interface) {
r = sd_bus_message_close_container(reply);
if (r < 0)
return r;
r = sd_bus_message_close_container(reply);
if (r < 0)
return r;
}
/* Open the new interface part */
r = sd_bus_message_open_container(reply, 'e', "sa{sv}");
if (r < 0)
return r;
r = sd_bus_message_append(reply, "s", i->interface);
if (r < 0)
return r;
r = sd_bus_message_open_container(reply, 'a', "{sv}");
if (r < 0)
return r;
}
r = vtable_append_all_properties(bus, reply, path, i, u, error);
if (r < 0)
return r;
if (sd_bus_error_is_set(error))
return 0;
if (bus->nodes_modified)
return 0;
previous_interface = i->interface;
}
if (previous_interface) {
r = sd_bus_message_close_container(reply);
if (r < 0)
return r;
r = sd_bus_message_close_container(reply);
if (r < 0)
return r;
}
if (found_something) {
@ -1503,7 +1517,7 @@ static int add_object_vtable_internal(
sd_bus_object_find_t find,
void *userdata) {
struct node_vtable *c = NULL, *i;
struct node_vtable *c = NULL, *i, *existing = NULL;
const sd_bus_vtable *v;
struct node *n;
int r;
@ -1515,6 +1529,10 @@ static int add_object_vtable_internal(
assert_return(vtable[0].type == _SD_BUS_VTABLE_START, -EINVAL);
assert_return(vtable[0].x.start.element_size == sizeof(struct sd_bus_vtable), -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
assert_return(!streq(interface, "org.freedesktop.DBus.Properties") &&
!streq(interface, "org.freedesktop.DBus.Introspectable") &&
!streq(interface, "org.freedesktop.DBus.Peer") &&
!streq(interface, "org.freedesktop.DBus.ObjectManager"), -EINVAL);
r = hashmap_ensure_allocated(&bus->vtable_methods, vtable_member_hash_func, vtable_member_compare_func);
if (r < 0)
@ -1529,15 +1547,20 @@ static int add_object_vtable_internal(
return -ENOMEM;
LIST_FOREACH(vtables, i, n->vtables) {
if (streq(i->interface, interface)) {
r = -EEXIST;
goto fail;
}
if (i->is_fallback != fallback) {
r = -EPROTOTYPE;
goto fail;
}
if (streq(i->interface, interface)) {
if (i->vtable == vtable) {
r = -EEXIST;
goto fail;
}
existing = i;
}
}
c = new0(struct node_vtable, 1);
@ -1654,7 +1677,7 @@ static int add_object_vtable_internal(
}
}
LIST_PREPEND(vtables, n->vtables, c);
LIST_INSERT_AFTER(vtables, n->vtables, existing, c);
bus->nodes_modified = true;
return 0;
@ -1671,7 +1694,10 @@ static int remove_object_vtable_internal(
sd_bus *bus,
const char *path,
const char *interface,
bool fallback) {
const sd_bus_vtable *vtable,
bool fallback,
sd_bus_object_find_t find,
void *userdata) {
struct node_vtable *c;
struct node *n;
@ -1686,7 +1712,11 @@ static int remove_object_vtable_internal(
return 0;
LIST_FOREACH(vtables, c, n->vtables)
if (streq(c->interface, interface) && c->is_fallback == fallback)
if (streq(c->interface, interface) &&
c->is_fallback == fallback &&
c->vtable == vtable &&
c->find == find &&
c->userdata == userdata)
break;
if (!c)
@ -1715,9 +1745,11 @@ _public_ int sd_bus_add_object_vtable(
_public_ int sd_bus_remove_object_vtable(
sd_bus *bus,
const char *path,
const char *interface) {
const char *interface,
const sd_bus_vtable *vtable,
void *userdata) {
return remove_object_vtable_internal(bus, path, interface, false);
return remove_object_vtable_internal(bus, path, interface, vtable, false, NULL, userdata);
}
_public_ int sd_bus_add_fallback_vtable(
@ -1734,9 +1766,12 @@ _public_ int sd_bus_add_fallback_vtable(
_public_ int sd_bus_remove_fallback_vtable(
sd_bus *bus,
const char *path,
const char *interface) {
const char *interface,
const sd_bus_vtable *vtable,
sd_bus_object_find_t find,
void *userdata) {
return remove_object_vtable_internal(bus, path, interface, true);
return remove_object_vtable_internal(bus, path, interface, vtable, true, find, userdata);
}
_public_ int sd_bus_add_node_enumerator(
@ -1824,8 +1859,8 @@ static int emit_properties_changed_on_interface(
char **names) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
bool has_invalidating = false;
struct vtable_member key;
bool has_invalidating = false, has_changing = false;
struct vtable_member key = {};
struct node_vtable *c;
struct node *n;
char **property;
@ -1841,23 +1876,6 @@ static int emit_properties_changed_on_interface(
if (!n)
return 0;
LIST_FOREACH(vtables, c, n->vtables) {
if (require_fallback && !c->is_fallback)
continue;
if (streq(c->interface, interface))
break;
}
if (!c)
return 0;
r = node_vtable_get_userdata(bus, path, c, &u);
if (r <= 0)
return r;
if (bus->nodes_modified)
return 0;
r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus.Properties", "PropertiesChanged", &m);
if (r < 0)
return r;
@ -1873,52 +1891,78 @@ static int emit_properties_changed_on_interface(
key.path = prefix;
key.interface = interface;
STRV_FOREACH(property, names) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
struct vtable_member *v;
assert_return(member_name_is_valid(*property), -EINVAL);
key.member = *property;
v = hashmap_get(bus->vtable_properties, &key);
if (!v)
return -ENOENT;
assert(c == v->parent);
assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE, -EDOM);
if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY) {
has_invalidating = true;
LIST_FOREACH(vtables, c, n->vtables) {
if (require_fallback && !c->is_fallback)
continue;
}
r = sd_bus_message_open_container(m, 'e', "sv");
if (r < 0)
return r;
if (!streq(c->interface, interface))
continue;
r = sd_bus_message_append(m, "s", *property);
if (r < 0)
return r;
r = sd_bus_message_open_container(m, 'v', v->vtable->x.property.signature);
if (r < 0)
return r;
r = invoke_property_get(bus, v->vtable, m->path, interface, *property, m, &error, vtable_property_convert_userdata(v->vtable, u));
r = node_vtable_get_userdata(bus, path, c, &u);
if (r < 0)
return r;
if (bus->nodes_modified)
return 0;
if (r == 0)
continue;
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
STRV_FOREACH(property, names) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
struct vtable_member *v;
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
assert_return(member_name_is_valid(*property), -EINVAL);
key.member = *property;
v = hashmap_get(bus->vtable_properties, &key);
if (!v)
return -ENOENT;
/* If there are two vtables for the same
* interface, let's handle this property when
* we come to that vtable. */
if (c != v->parent)
continue;
assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE, -EDOM);
if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY) {
has_invalidating = true;
continue;
}
has_changing = true;
r = sd_bus_message_open_container(m, 'e', "sv");
if (r < 0)
return r;
r = sd_bus_message_append(m, "s", *property);
if (r < 0)
return r;
r = sd_bus_message_open_container(m, 'v', v->vtable->x.property.signature);
if (r < 0)
return r;
r = invoke_property_get(bus, v->vtable, m->path, interface, *property, m, &error, vtable_property_convert_userdata(v->vtable, u));
if (r < 0)
return r;
if (bus->nodes_modified)
return 0;
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
}
}
if (!has_invalidating && !has_changing)
return 0;
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
@ -1928,19 +1972,35 @@ static int emit_properties_changed_on_interface(
return r;
if (has_invalidating) {
STRV_FOREACH(property, names) {
struct vtable_member *v;
key.member = *property;
assert_se(v = hashmap_get(bus->vtable_properties, &key));
assert(c == v->parent);
if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY))
LIST_FOREACH(vtables, c, n->vtables) {
if (require_fallback && !c->is_fallback)
continue;
r = sd_bus_message_append(m, "s", *property);
if (!streq(c->interface, interface))
continue;
r = node_vtable_get_userdata(bus, path, c, &u);
if (r < 0)
return r;
if (bus->nodes_modified)
return 0;
if (r == 0)
continue;
STRV_FOREACH(property, names) {
struct vtable_member *v;
key.member = *property;
assert_se(v = hashmap_get(bus->vtable_properties, &key));
assert(c == v->parent);
if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY))
continue;
r = sd_bus_message_append(m, "s", *property);
if (r < 0)
return r;
}
}
}
@ -2028,6 +2088,7 @@ static int interfaces_added_append_one_prefix(
bool require_fallback) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
bool found_interface = false;
struct node_vtable *c;
struct node *n;
void *u = NULL;
@ -2047,38 +2108,43 @@ static int interfaces_added_append_one_prefix(
if (require_fallback && !c->is_fallback)
continue;
if (streq(c->interface, interface))
break;
if (!streq(c->interface, interface))
continue;
r = node_vtable_get_userdata(bus, path, c, &u);
if (r < 0)
return r;
if (bus->nodes_modified)
return 0;
if (r == 0)
continue;
if (!found_interface) {
r = sd_bus_message_append_basic(m, 's', interface);
if (r < 0)
return r;
r = sd_bus_message_open_container(m, 'a', "{sv}");
if (r < 0)
return r;
found_interface = true;
}
r = vtable_append_all_properties(bus, m, path, c, u, &error);
if (r < 0)
return r;
if (bus->nodes_modified)
return 0;
}
if (!c)
return 0;
if (found_interface) {
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
}
r = node_vtable_get_userdata(bus, path, c, &u);
if (r <= 0)
return r;
if (bus->nodes_modified)
return 0;
r = sd_bus_message_append_basic(m, 's', interface);
if (r < 0)
return r;
r = sd_bus_message_open_container(m, 'a', "{sv}");
if (r < 0)
return r;
r = vtable_append_all_properties(bus, m,path, c, u, &error);
if (r < 0)
return r;
if (bus->nodes_modified)
return 0;
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
return 1;
return found_interface;
}
static int interfaces_added_append_one(

View File

@ -33,7 +33,10 @@ static int signature_element_length_internal(
int r;
assert(s);
if (!s)
return -EINVAL;
assert(l);
if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
*l = 1;
@ -114,7 +117,8 @@ bool signature_is_single(const char *s, bool allow_dict_entry) {
int r;
size_t t;
assert(s);
if (!s)
return false;
r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
if (r < 0)
@ -124,7 +128,9 @@ bool signature_is_single(const char *s, bool allow_dict_entry) {
}
bool signature_is_pair(const char *s) {
assert(s);
if (!s)
return false;
if (!bus_type_is_basic(*s))
return false;
@ -136,7 +142,8 @@ bool signature_is_valid(const char *s, bool allow_dict_entry) {
const char *p;
int r;
assert(s);
if (!s)
return false;
p = s;
while (*p) {

View File

@ -383,7 +383,7 @@ void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
#endif
}
static int bus_check_peercred(sd_bus *c) {
int bus_check_peercred(sd_bus *c) {
struct ucred ucred;
socklen_t l;
int fd;
@ -1014,7 +1014,8 @@ int bus_property_get_bool(
return sd_bus_message_append_basic(reply, 'b', &b);
}
int bus_property_get_uid(
#if __SIZEOF_SIZE_T__ != 8
int bus_property_get_size(
sd_bus *bus,
const char *path,
const char *interface,
@ -1023,12 +1024,41 @@ int bus_property_get_uid(
sd_bus_error *error,
void *userdata) {
assert_cc(sizeof(uint32_t) == sizeof(uid_t));
assert_cc(sizeof(uint32_t) == sizeof(gid_t));
assert_cc(sizeof(uint32_t) == sizeof(pid_t));
uint64_t sz = *(size_t*) userdata;
return sd_bus_message_append_basic(reply, 'u', userdata);
return sd_bus_message_append_basic(reply, 't', &sz);
}
#endif
#if __SIZEOF_LONG__ != 8
int bus_property_get_long(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
sd_bus_error *error,
void *userdata) {
int64_t l = *(long*) userdata;
return sd_bus_message_append_basic(reply, 'x', &l);
}
int bus_property_get_ulong(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
sd_bus_error *error,
void *userdata) {
uint64_t ul = *(unsigned long*) userdata;
return sd_bus_message_append_basic(reply, 't', &ul);
}
#endif
int bus_log_parse_error(int r) {
log_error("Failed to parse message: %s", strerror(-r));

View File

@ -55,7 +55,8 @@ int bus_map_all_properties(sd_bus *bus,
int bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name);
int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout);
int bus_property_get_tristate(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
int bus_check_peercred(sd_bus *c);
int bus_verify_polkit(sd_bus *bus, sd_bus_message *m, const char *action, bool interactive, bool *_challenge, sd_bus_error *e);
@ -71,11 +72,48 @@ int bus_open_transport_systemd(BusTransport transport, const char *host, bool us
int bus_print_property(const char *name, sd_bus_message *property, bool all);
int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all);
int bus_property_get_tristate(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
int bus_property_get_uid(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
#define bus_property_get_gid bus_property_get_uid
#define bus_property_get_pid bus_property_get_uid
#define bus_property_get_usec ((sd_bus_property_get_t) NULL)
#define bus_property_set_usec ((sd_bus_property_set_t) NULL)
assert_cc(sizeof(int) == sizeof(int32_t));
#define bus_property_get_int ((sd_bus_property_get_t) NULL)
assert_cc(sizeof(unsigned) == sizeof(unsigned));
#define bus_property_get_unsigned ((sd_bus_property_get_t) NULL)
/* On 64bit machines we can use the default serializer for size_t and
* friends, otherwise we need to cast this manually */
#if __SIZEOF_SIZE_T__ == 8
#define bus_property_get_size ((sd_bus_property_get_t) NULL)
#else
int bus_property_get_size(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
#endif
#if __SIZEOF_LONG__ == 8
#define bus_property_get_long ((sd_bus_property_get_t) NULL)
#define bus_property_get_ulong ((sd_bus_property_get_t) NULL)
#else
int bus_property_get_long(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
int bus_property_get_ulong(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
#endif
/* uid_t and friends on Linux 32 bit. This means we can just use the
* default serializer for 32bit unsigned, for serializing it, and map
* it to NULL here */
assert_cc(sizeof(uid_t) == sizeof(uint32_t));
#define bus_property_get_uid ((sd_bus_property_get_t) NULL)
assert_cc(sizeof(gid_t) == sizeof(uint32_t));
#define bus_property_get_gid ((sd_bus_property_get_t) NULL)
assert_cc(sizeof(pid_t) == sizeof(uint32_t));
#define bus_property_get_pid ((sd_bus_property_get_t) NULL)
assert_cc(sizeof(mode_t) == sizeof(uint32_t));
#define bus_property_get_mode ((sd_bus_property_get_t) NULL)
int bus_log_parse_error(int r);
int bus_log_create_error(int r);
@ -129,22 +167,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, sd_bus_message_unref);
} \
struct __useless_struct_to_allow_trailing_semicolon__
#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"
#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
#define BUS_ERROR_NO_SUCH_USER "org.freedesktop.login1.NoSuchUser"
#define BUS_ERROR_NO_USER_FOR_PID "org.freedesktop.login1.NoUserForPID"
#define BUS_ERROR_NO_SUCH_SEAT "org.freedesktop.login1.NoSuchSeat"
#define BUS_ERROR_SESSION_NOT_ON_SEAT "org.freedesktop.login1.SessionNotOnSeat"
#define BUS_ERROR_NOT_IN_CONTROL "org.freedesktop.login1.NotInControl"
#define BUS_ERROR_DEVICE_IS_TAKEN "org.freedesktop.login1.DeviceIsTaken"
#define BUS_ERROR_DEVICE_NOT_TAKEN "org.freedesktop.login1.DeviceNotTaken"
#define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress"
#define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported"
#define BUS_PROPERTY_DUAL_TIMESTAMP(name, offset, flags) \
SD_BUS_PROPERTY(name, "t", bus_property_get_usec, offset + offsetof(struct dual_timestamp, realtime), flags), \
SD_BUS_PROPERTY(name "Monotonic", "t", bus_property_get_usec, offset + offsetof(struct dual_timestamp, monotonic), flags)

View File

@ -1204,6 +1204,18 @@ _public_ void sd_bus_close(sd_bus *bus) {
* freed. */
}
static void bus_enter_closing(sd_bus *bus) {
assert(bus);
if (bus->state != BUS_OPENING &&
bus->state != BUS_AUTHENTICATING &&
bus->state != BUS_HELLO &&
bus->state != BUS_RUNNING)
return;
bus->state = BUS_CLOSING;
}
_public_ sd_bus *sd_bus_ref(sd_bus *bus) {
assert_return(bus, NULL);
@ -1282,6 +1294,20 @@ static int bus_seal_message(sd_bus *b, sd_bus_message *m) {
return bus_message_seal(m, ++b->serial);
}
static int bus_write_message(sd_bus *bus, sd_bus_message *message, size_t *idx) {
int r;
assert(bus);
assert(message);
if (bus->is_kernel)
r = bus_kernel_write_message(bus, message);
else
r = bus_socket_write_message(bus, message, idx);
return r;
}
static int dispatch_wqueue(sd_bus *bus) {
int r, ret = 0;
@ -1290,15 +1316,10 @@ static int dispatch_wqueue(sd_bus *bus) {
while (bus->wqueue_size > 0) {
if (bus->is_kernel)
r = bus_kernel_write_message(bus, bus->wqueue[0]);
else
r = bus_socket_write_message(bus, bus->wqueue[0], &bus->windex);
if (r < 0) {
sd_bus_close(bus);
r = bus_write_message(bus, bus->wqueue[0], &bus->windex);
if (r < 0)
return r;
} else if (r == 0)
else if (r == 0)
/* Didn't do anything this time */
return ret;
else if (bus->is_kernel || bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) {
@ -1324,6 +1345,20 @@ static int dispatch_wqueue(sd_bus *bus) {
return ret;
}
static int bus_read_message(sd_bus *bus, sd_bus_message **m) {
int r;
assert(bus);
assert(m);
if (bus->is_kernel)
r = bus_kernel_read_message(bus, m);
else
r = bus_socket_read_message(bus, m);
return r;
}
static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
sd_bus_message *z = NULL;
int r, ret = 0;
@ -1343,15 +1378,9 @@ static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
/* Try to read a new message */
do {
if (bus->is_kernel)
r = bus_kernel_read_message(bus, &z);
else
r = bus_socket_read_message(bus, &z);
if (r < 0) {
sd_bus_close(bus);
r = bus_read_message(bus, &z);
if (r < 0)
return r;
}
if (r == 0)
return ret;
@ -1395,15 +1424,10 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) {
size_t idx = 0;
if (bus->is_kernel)
r = bus_kernel_write_message(bus, m);
else
r = bus_socket_write_message(bus, m, &idx);
if (r < 0) {
sd_bus_close(bus);
r = bus_write_message(bus, m, &idx);
if (r < 0)
return r;
} else if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m)) {
else if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m)) {
/* Wasn't fully written. So let's remember how
* much was written. Note that the first entry
* of the wqueue array is always allocated so
@ -1573,7 +1597,7 @@ int bus_ensure_running(sd_bus *bus) {
assert(bus);
if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED)
if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED || bus->state == BUS_CLOSING)
return -ENOTCONN;
if (bus->state == BUS_RUNNING)
return 1;
@ -1644,12 +1668,10 @@ _public_ int sd_bus_call(
room = true;
}
if (bus->is_kernel)
r = bus_kernel_read_message(bus, &incoming);
else
r = bus_socket_read_message(bus, &incoming);
r = bus_read_message(bus, &incoming);
if (r < 0)
return r;
if (incoming) {
if (incoming->reply_serial == serial) {
@ -1731,7 +1753,6 @@ _public_ int sd_bus_call(
_public_ int sd_bus_get_fd(sd_bus *bus) {
assert_return(bus, -EINVAL);
assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
assert_return(bus->input_fd == bus->output_fd, -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
@ -1742,7 +1763,7 @@ _public_ int sd_bus_get_events(sd_bus *bus) {
int flags = 0;
assert_return(bus, -EINVAL);
assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
assert_return(BUS_IS_OPEN(bus->state) || bus->state == BUS_CLOSING, -ENOTCONN);
assert_return(!bus_pid_changed(bus), -ECHILD);
if (bus->state == BUS_OPENING)
@ -1769,9 +1790,14 @@ _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
assert_return(bus, -EINVAL);
assert_return(timeout_usec, -EINVAL);
assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
assert_return(BUS_IS_OPEN(bus->state) || bus->state == BUS_CLOSING, -ENOTCONN);
assert_return(!bus_pid_changed(bus), -ECHILD);
if (bus->state == BUS_CLOSING) {
*timeout_usec = 0;
return 1;
}
if (bus->state == BUS_AUTHENTICATING) {
*timeout_usec = bus->auth_timeout;
return 1;
@ -1821,12 +1847,21 @@ static int process_timeout(sd_bus *bus) {
if (r < 0)
return r;
r = bus_seal_message(bus, m);
if (r < 0)
return r;
assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
hashmap_remove(bus->reply_callbacks, &c->serial);
bus->current = m;
bus->iteration_counter ++;
r = c->callback(bus, m, c->userdata);
free(c);
bus->current = NULL;
return r < 0 ? r : 1;
}
@ -1877,7 +1912,7 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
r = c->callback(bus, m, c->userdata);
free(c);
return r;
return r < 0 ? r : 1;
}
static int process_filter(sd_bus *bus, sd_bus_message *m) {
@ -2078,6 +2113,85 @@ null_message:
return r;
}
static int process_closing(sd_bus *bus, sd_bus_message **ret) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
struct reply_callback *c;
int r;
assert(bus);
assert(bus->state == BUS_CLOSING);
c = hashmap_first(bus->reply_callbacks);
if (c) {
/* First, fail all outstanding method calls */
r = bus_message_new_synthetic_error(
bus,
c->serial,
&SD_BUS_ERROR_MAKE(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
&m);
if (r < 0)
return r;
r = bus_seal_message(bus, m);
if (r < 0)
return r;
if (c->timeout != 0)
prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
hashmap_remove(bus->reply_callbacks, &c->serial);
bus->current = m;
bus->iteration_counter++;
r = c->callback(bus, m, c->userdata);
free(c);
if (r >= 0)
r = 1;
goto finish;
}
/* Then, synthesize a Disconnected message */
r = sd_bus_message_new_signal(
bus,
"/org/freedesktop/DBus/Local",
"org.freedesktop.DBus.Local",
"Disconnected",
&m);
if (r < 0)
return r;
r = bus_seal_message(bus, m);
if (r < 0)
return r;
sd_bus_close(bus);
bus->current = m;
bus->iteration_counter++;
r = process_filter(bus, m);
if (r != 0)
goto finish;
r = process_match(bus, m);
if (r != 0)
goto finish;
if (ret) {
*ret = m;
m = NULL;
}
r = 1;
finish:
bus->current = NULL;
return r;
}
_public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
BUS_DONT_DESTROY(bus);
int r;
@ -2091,7 +2205,7 @@ _public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
assert_return(!bus_pid_changed(bus), -ECHILD);
/* We don't allow recursively invoking sd_bus_process(). */
assert_return(!bus->processing, -EBUSY);
assert_return(!bus->current, -EBUSY);
switch (bus->state) {
@ -2101,29 +2215,43 @@ _public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
case BUS_OPENING:
r = bus_socket_process_opening(bus);
if (r < 0)
if (r == -ECONNRESET || r == -EPIPE) {
bus_enter_closing(bus);
r = 1;
} else if (r < 0)
return r;
if (ret)
*ret = NULL;
return r;
case BUS_AUTHENTICATING:
r = bus_socket_process_authenticating(bus);
if (r < 0)
if (r == -ECONNRESET || r == -EPIPE) {
bus_enter_closing(bus);
r = 1;
} else if (r < 0)
return r;
if (ret)
*ret = NULL;
return r;
case BUS_RUNNING:
case BUS_HELLO:
bus->processing = true;
r = process_running(bus, ret);
bus->processing = false;
if (r == -ECONNRESET || r == -EPIPE) {
bus_enter_closing(bus);
r = 1;
if (ret)
*ret = NULL;
}
return r;
case BUS_CLOSING:
return process_closing(bus, ret);
}
assert_not_reached("Unknown state");
@ -2136,6 +2264,10 @@ static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
usec_t m = (usec_t) -1;
assert(bus);
if (bus->state == BUS_CLOSING)
return 1;
assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
e = sd_bus_get_events(bus);
@ -2186,9 +2318,13 @@ static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
_public_ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
assert_return(bus, -EINVAL);
assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
assert_return(!bus_pid_changed(bus), -ECHILD);
if (bus->state == BUS_CLOSING)
return 0;
assert_return(BUS_IS_OPEN(bus->state) , -ENOTCONN);
if (bus->rqueue_size > 0)
return 0;
@ -2199,9 +2335,13 @@ _public_ int sd_bus_flush(sd_bus *bus) {
int r;
assert_return(bus, -EINVAL);
assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
assert_return(!bus_pid_changed(bus), -ECHILD);
if (bus->state == BUS_CLOSING)
return 0;
assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
r = bus_ensure_running(bus);
if (r < 0)
return r;

View File

@ -51,7 +51,7 @@ struct sd_event_source {
sd_event *event;
void *userdata;
sd_prepare_handler_t prepare;
sd_event_handler_t prepare;
EventSourceType type:4;
int enabled:3;
@ -65,34 +65,34 @@ struct sd_event_source {
union {
struct {
sd_io_handler_t callback;
sd_event_io_handler_t callback;
int fd;
uint32_t events;
uint32_t revents;
bool registered:1;
} io;
struct {
sd_time_handler_t callback;
sd_event_time_handler_t callback;
usec_t next, accuracy;
unsigned earliest_index;
unsigned latest_index;
} time;
struct {
sd_signal_handler_t callback;
sd_event_signal_handler_t callback;
struct signalfd_siginfo siginfo;
int sig;
} signal;
struct {
sd_child_handler_t callback;
sd_event_child_handler_t callback;
siginfo_t siginfo;
pid_t pid;
int options;
} child;
struct {
sd_defer_handler_t callback;
sd_event_handler_t callback;
} defer;
struct {
sd_quit_handler_t callback;
sd_event_handler_t callback;
unsigned prioq_index;
} quit;
};
@ -567,7 +567,7 @@ _public_ int sd_event_add_io(
sd_event *e,
int fd,
uint32_t events,
sd_io_handler_t callback,
sd_event_io_handler_t callback,
void *userdata,
sd_event_source **ret) {
@ -655,7 +655,7 @@ static int event_add_time_internal(
Prioq **latest,
uint64_t usec,
uint64_t accuracy,
sd_time_handler_t callback,
sd_event_time_handler_t callback,
void *userdata,
sd_event_source **ret) {
@ -722,7 +722,7 @@ fail:
_public_ int sd_event_add_monotonic(sd_event *e,
uint64_t usec,
uint64_t accuracy,
sd_time_handler_t callback,
sd_event_time_handler_t callback,
void *userdata,
sd_event_source **ret) {
@ -732,7 +732,7 @@ _public_ int sd_event_add_monotonic(sd_event *e,
_public_ int sd_event_add_realtime(sd_event *e,
uint64_t usec,
uint64_t accuracy,
sd_time_handler_t callback,
sd_event_time_handler_t callback,
void *userdata,
sd_event_source **ret) {
@ -774,7 +774,7 @@ static int event_update_signal_fd(sd_event *e) {
_public_ int sd_event_add_signal(
sd_event *e,
int sig,
sd_signal_handler_t callback,
sd_event_signal_handler_t callback,
void *userdata,
sd_event_source **ret) {
@ -824,7 +824,7 @@ _public_ int sd_event_add_child(
sd_event *e,
pid_t pid,
int options,
sd_child_handler_t callback,
sd_event_child_handler_t callback,
void *userdata,
sd_event_source **ret) {
@ -883,7 +883,7 @@ _public_ int sd_event_add_child(
_public_ int sd_event_add_defer(
sd_event *e,
sd_defer_handler_t callback,
sd_event_handler_t callback,
void *userdata,
sd_event_source **ret) {
@ -916,7 +916,7 @@ _public_ int sd_event_add_defer(
_public_ int sd_event_add_quit(
sd_event *e,
sd_quit_handler_t callback,
sd_event_handler_t callback,
void *userdata,
sd_event_source **ret) {
@ -1297,7 +1297,7 @@ _public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
return 0;
}
_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_prepare_handler_t callback) {
_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) {
int r;
assert_return(s, -EINVAL);

View File

@ -52,7 +52,9 @@ int main(int argc, char *argv[]) {
assert_se(introspect_begin(&intro) >= 0);
assert_se(introspect_write_interface(&intro, "org.foo", vtable) >= 0);
fprintf(intro.f, " <interface name=\"org.foo\">\n");
assert_se(introspect_write_interface(&intro, vtable) >= 0);
fputs(" </interface>\n", intro.f);
fflush(intro.f);
fputs(intro.introspection, stdout);

View File

@ -28,7 +28,7 @@
#endif
#ifdef HAVE_DBUS
#include <dbus.h>
#include <dbus/dbus.h>
#endif
#include "log.h"

View File

@ -40,6 +40,7 @@
#include "bus-util.h"
#include "bus-error.h"
#include "logind.h"
#include "bus-errors.h"
static int property_get_idle_hint(
sd_bus *bus,
@ -184,7 +185,7 @@ static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void
p = session_bus_path(session);
if (!p)
return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
return sd_bus_reply_method_return(bus, message, "o", p);
}

View File

@ -304,7 +304,7 @@ int inhibitor_create_fifo(Inhibitor *i) {
if (r < 0)
return r;
r = sd_event_source_set_priority(i->event_source, SD_PRIORITY_IDLE);
r = sd_event_source_set_priority(i->event_source, SD_EVENT_PRIORITY_IDLE);
if (r < 0)
return r;
}

View File

@ -25,6 +25,7 @@
#include "util.h"
#include "bus-util.h"
#include "strv.h"
#include "bus-errors.h"
#include "logind.h"
#include "logind-seat.h"

View File

@ -25,6 +25,7 @@
#include "util.h"
#include "strv.h"
#include "bus-util.h"
#include "bus-errors.h"
#include "logind.h"
#include "logind-session.h"

View File

@ -864,7 +864,7 @@ int session_create_fifo(Session *s) {
if (r < 0)
return r;
r = sd_event_source_set_priority(s->fifo_event_source, SD_PRIORITY_IDLE);
r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
if (r < 0)
return r;
}

View File

@ -958,7 +958,7 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us
return r;
}
r = sd_event_source_set_priority(m->idle_action_event_source, SD_PRIORITY_IDLE+10);
r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
if (r < 0) {
log_error("Failed to set idle event source priority: %s", strerror(-r));
return r;

View File

@ -36,6 +36,7 @@
#include "utf8.h"
#include "unit-name.h"
#include "bus-util.h"
#include "bus-errors.h"
#include "time-util.h"
#include "cgroup-util.h"
#include "machined.h"

57
src/shared/bus-errors.h Normal file
View File

@ -0,0 +1,57 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#pragma once
/***
This file is part of systemd.
Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
#define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID"
#define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists"
#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
#define BUS_ERROR_NO_SUCH_JOB "org.freedesktop.systemd1.NoSuchJob"
#define BUS_ERROR_NOT_SUBSCRIBED "org.freedesktop.systemd1.NotSubscribed"
#define BUS_ERROR_ALREADY_SUBSCRIBED "org.freedesktop.systemd1.AlreadySubscribed"
#define BUS_ERROR_ONLY_BY_DEPENDENCY "org.freedesktop.systemd1.OnlyByDependency"
#define BUS_ERROR_TRANSACTION_JOBS_CONFLICTING "org.freedesktop.systemd1.TransactionJobsConflicting"
#define BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC "org.freedesktop.systemd1.TransactionOrderIsCyclic"
#define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive"
#define BUS_ERROR_UNIT_MASKED "org.freedesktop.systemd1.UnitMasked"
#define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable"
#define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation"
#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"
#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
#define BUS_ERROR_NO_SUCH_USER "org.freedesktop.login1.NoSuchUser"
#define BUS_ERROR_NO_USER_FOR_PID "org.freedesktop.login1.NoUserForPID"
#define BUS_ERROR_NO_SUCH_SEAT "org.freedesktop.login1.NoSuchSeat"
#define BUS_ERROR_SESSION_NOT_ON_SEAT "org.freedesktop.login1.SessionNotOnSeat"
#define BUS_ERROR_NOT_IN_CONTROL "org.freedesktop.login1.NotInControl"
#define BUS_ERROR_DEVICE_IS_TAKEN "org.freedesktop.login1.DeviceIsTaken"
#define BUS_ERROR_DEVICE_NOT_TAKEN "org.freedesktop.login1.DeviceNotTaken"
#define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress"
#define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported"
#define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess"

File diff suppressed because it is too large Load Diff

View File

@ -1,246 +0,0 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#pragma once
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <dbus/dbus.h>
#include <inttypes.h>
#include <sys/types.h>
#include "macro.h"
#ifndef DBUS_ERROR_UNKNOWN_OBJECT
#define DBUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject"
#endif
#ifndef DBUS_ERROR_UNKNOWN_INTERFACE
#define DBUS_ERROR_UNKNOWN_INTERFACE "org.freedesktop.DBus.Error.UnknownInterface"
#endif
#ifndef DBUS_ERROR_UNKNOWN_PROPERTY
#define DBUS_ERROR_UNKNOWN_PROPERTY "org.freedesktop.DBus.Error.UnknownProperty"
#endif
#ifndef DBUS_ERROR_PROPERTY_READ_ONLY
#define DBUS_ERROR_PROPERTY_READ_ONLY "org.freedesktop.DBus.Error.PropertyReadOnly"
#endif
#define BUS_PROPERTIES_INTERFACE \
" <interface name=\"org.freedesktop.DBus.Properties\">\n" \
" <method name=\"Get\">\n" \
" <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
" <arg name=\"property\" direction=\"in\" type=\"s\"/>\n" \
" <arg name=\"value\" direction=\"out\" type=\"v\"/>\n" \
" </method>\n" \
" <method name=\"GetAll\">\n" \
" <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
" <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n" \
" </method>\n" \
" <method name=\"Set\">\n" \
" <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
" <arg name=\"property\" direction=\"in\" type=\"s\"/>\n" \
" <arg name=\"value\" direction=\"in\" type=\"v\"/>\n" \
" </method>\n" \
" <signal name=\"PropertiesChanged\">\n" \
" <arg type=\"s\" name=\"interface\"/>\n" \
" <arg type=\"a{sv}\" name=\"changed_properties\"/>\n" \
" <arg type=\"as\" name=\"invalidated_properties\"/>\n" \
" </signal>\n" \
" </interface>\n"
#define BUS_INTROSPECTABLE_INTERFACE \
" <interface name=\"org.freedesktop.DBus.Introspectable\">\n" \
" <method name=\"Introspect\">\n" \
" <arg name=\"data\" type=\"s\" direction=\"out\"/>\n" \
" </method>\n" \
" </interface>\n"
#define BUS_PEER_INTERFACE \
"<interface name=\"org.freedesktop.DBus.Peer\">\n" \
" <method name=\"Ping\"/>\n" \
" <method name=\"GetMachineId\">\n" \
" <arg type=\"s\" name=\"machine_uuid\" direction=\"out\"/>\n" \
" </method>\n" \
"</interface>\n"
#define BUS_GENERIC_INTERFACES_LIST \
"org.freedesktop.DBus.Properties\0" \
"org.freedesktop.DBus.Introspectable\0" \
"org.freedesktop.DBus.Peer\0"
int bus_check_peercred(DBusConnection *c);
int bus_connect(DBusBusType t, DBusConnection **_bus, bool *private_bus, DBusError *error);
int bus_connect_system_ssh(const char *user, const char *host, DBusConnection **_bus, DBusError *error);
int bus_connect_system_polkit(DBusConnection **_bus, DBusError *error);
const char *bus_error_message(const DBusError *error);
const char *bus_error(const DBusError *e, int r);
typedef int (*BusPropertyCallback)(DBusMessageIter *iter, const char *property, void *data);
typedef int (*BusPropertySetCallback)(DBusMessageIter *iter, const char *property, void *data);
typedef struct BusProperty {
const char *property; /* name of the property */
BusPropertyCallback append; /* Function that is called to serialize this property */
const char *signature;
const uint16_t offset; /* Offset from BusBoundProperties::base address to the property data.
* uint16_t is sufficient, because we have no structs too big.
* -Werror=overflow will catch it if this does not hold. */
bool indirect; /* data is indirect, ie. not base+offset, but *(base+offset) */
BusPropertySetCallback set; /* Optional: Function that is called to set this property */
} BusProperty;
typedef struct BusBoundProperties {
const char *interface; /* interface of the properties */
const BusProperty *properties; /* array of properties, ended by a NULL-filled element */
const void *const base; /* base pointer to which the offset must be added to reach data */
} BusBoundProperties;
dbus_bool_t bus_maybe_send_reply (DBusConnection *c,
DBusMessage *message,
DBusMessage *reply);
DBusHandlerResult bus_send_error_reply(
DBusConnection *c,
DBusMessage *message,
DBusError *bus_error,
int error);
DBusHandlerResult bus_default_message_handler(
DBusConnection *c,
DBusMessage *message,
const char *introspection,
const char *interfaces,
const BusBoundProperties *bound_properties);
int bus_property_append_string(DBusMessageIter *i, const char *property, void *data);
int bus_property_append_strv(DBusMessageIter *i, const char *property, void *data);
int bus_property_append_bool(DBusMessageIter *i, const char *property, void *data);
int bus_property_append_tristate_false(DBusMessageIter *i, const char *property, void *data);
int bus_property_append_int32(DBusMessageIter *i, const char *property, void *data);
int bus_property_append_uint32(DBusMessageIter *i, const char *property, void *data);
int bus_property_append_uint64(DBusMessageIter *i, const char *property, void *data);
int bus_property_append_size(DBusMessageIter *i, const char *property, void *data);
int bus_property_append_ul(DBusMessageIter *i, const char *property, void *data);
int bus_property_append_long(DBusMessageIter *i, const char *property, void *data);
#define bus_property_append_int bus_property_append_int32
#define bus_property_append_pid bus_property_append_uint32
#define bus_property_append_uid bus_property_append_uint32
#define bus_property_append_gid bus_property_append_uint32
#define bus_property_append_mode bus_property_append_uint32
#define bus_property_append_unsigned bus_property_append_uint32
#define bus_property_append_usec bus_property_append_uint64
int bus_property_set_uint64(DBusMessageIter *i, const char *property, void *data);
#define bus_property_set_usec bus_property_set_uint64
#define DEFINE_BUS_PROPERTY_APPEND_ENUM(function,name,type) \
int function(DBusMessageIter *i, const char *property, void *data) { \
const char *value; \
type *field = data; \
\
assert(i); \
assert(property); \
\
value = strempty(name##_to_string(*field)); \
\
if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &value)) \
return -ENOMEM; \
\
return 0; \
}
#define DEFINE_BUS_PROPERTY_SET_ENUM(function,name,type) \
int function(DBusMessageIter *i, const char *property, void *data) { \
const char *value; \
type f, *field = data; \
\
assert(i); \
assert(property); \
\
dbus_message_iter_get_basic(i, &value); \
\
f = name##_from_string(value); \
if (f < 0) \
return f; \
\
*field = f; \
return 0; \
}
const char *bus_errno_to_dbus(int error) _const_;
DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties);
DBusMessage* bus_properties_changed_one_new(const char *path, const char *interface, const char *property);
uint32_t bus_flags_to_events(DBusWatch *bus_watch) _pure_;
unsigned bus_events_to_flags(uint32_t events) _const_;
int bus_parse_strv(DBusMessage *m, char ***_l);
int bus_parse_strv_iter(DBusMessageIter *iter, char ***_l);
int bus_parse_strv_pairs_iter(DBusMessageIter *iter, char ***_l);
struct unit_info {
const char *id;
const char *description;
const char *load_state;
const char *active_state;
const char *sub_state;
const char *following;
const char *unit_path;
uint32_t job_id;
const char *job_type;
const char *job_path;
};
int bus_parse_unit_info(DBusMessageIter *iter, struct unit_info *u);
int bus_append_strv_iter(DBusMessageIter *iter, char **l);
int bus_iter_get_basic_and_next(DBusMessageIter *iter, int type, void *data, bool next);
int generic_print_property(const char *name, DBusMessageIter *iter, bool all);
void bus_async_unregister_and_exit(DBusConnection *bus, const char *name);
DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata);
pid_t bus_get_unix_process_id(DBusConnection *connection, const char *name, DBusError *error);
bool bus_error_is_no_service(const DBusError *error);
int bus_method_call_with_reply(DBusConnection *bus,
const char *destination,
const char *path,
const char *interface,
const char *method,
DBusMessage **return_reply,
DBusError *return_error,
int first_arg_type, ...);
const char *bus_message_get_sender_with_fallback(DBusMessage *m);
void bus_message_unrefp(DBusMessage **reply);
#define _cleanup_dbus_message_unref_ __attribute__((cleanup(bus_message_unrefp)))
#define _cleanup_dbus_error_free_ __attribute__((cleanup(dbus_error_free)))

Some files were not shown because too many files have changed in this diff Show More