mirror of
https://github.com/systemd/systemd
synced 2024-10-07 08:40:44 +00:00
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:
parent
3febea3a0b
commit
718db96199
71
Makefile.am
71
Makefile.am
|
@ -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
47
TODO
|
@ -43,6 +43,53 @@ CGroup Rework Completion:
|
|||
|
||||
Features:
|
||||
|
||||
* sd-event: allow multiple signal handlers per signal
|
||||
|
||||
* timer: expose accuracy as unit setting
|
||||
|
||||
* sd-event: do per-minute coalescing of timer events too
|
||||
|
||||
* when we detect low battery and no AC on boot, show pretty splash and refuse boot
|
||||
|
||||
* move libasyncns into systemd as libsystemd-asyncns
|
||||
|
||||
* calendarspec: support value ranges with ".." notation. Example: 2013-4..8-1
|
||||
|
||||
* pid1 porting:
|
||||
- restore selinux access control on properties
|
||||
|
||||
* sd-bus: when triggering property change events, allow a NULL strv indicate that all properties listed as such are send out as changed
|
||||
|
||||
* sd-bus: enforce signatures on response messages
|
||||
|
||||
* sd-bus: make message handlers take an sd_bus_error and generate error replies automatically if they are set
|
||||
|
||||
* sd-bus: when replying to a bus message we should not need to specify the bus again
|
||||
|
||||
* sd-bus: see if we can drop more message validation on the sending side
|
||||
|
||||
* sd-bus: introduce sd_bus_creds object and attach it to messages as well as allow querying it for names
|
||||
|
||||
* sd-bus: support "const" properties as flag
|
||||
|
||||
* sd-bus: add api call to escape bus path components
|
||||
|
||||
* sd-event: when a handler returns an error, just turn off its event
|
||||
source, but do not return anything up to the event loop
|
||||
caller. Instead add parameter to sd_event_request_quit() to take
|
||||
retval. This way errors rippling upwards are the option, not the
|
||||
default
|
||||
|
||||
* sd-event: child pid handling: first invoke waitid(WNOHANG) and call event handler, only afterwards reap the process
|
||||
|
||||
* sd-event: native support for watchdog stuff
|
||||
|
||||
* machined, localed: when we try to kill an empty cgroup, generate an ESRCH call over the bus
|
||||
|
||||
* sd-bus: SD_BUS_COMMENT() macro for inclusion in vtables, syntax inspired by gdbus
|
||||
|
||||
* libsystemd-journal, libsystemd-login, libudev: add calls to easily attach these objects to sd-event event loops
|
||||
|
||||
* be more careful what we export on the bus as (usec_t) 0 and (usec_t) -1
|
||||
|
||||
* check :no-sender logic after PID 1 conversion
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
a->bandwidth = u64;
|
||||
|
||||
if (!exist)
|
||||
LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
|
||||
}
|
||||
|
||||
n++;
|
||||
dbus_message_iter_next(&sub);
|
||||
a->bandwidth = u64;
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
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;
|
||||
unsigned n = 0;
|
||||
|
||||
if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
|
||||
dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT)
|
||||
return -EINVAL;
|
||||
|
||||
dbus_message_iter_recurse(i, &sub);
|
||||
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
|
||||
DBusMessageIter sub2;
|
||||
const char *path;
|
||||
uint64_t u64;
|
||||
unsigned n = 0;
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'a', "(st)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
a->weight = ul;
|
||||
|
||||
if (!exist)
|
||||
LIST_PREPEND(device_weights,c->blockio_device_weights, a);
|
||||
}
|
||||
|
||||
a->weight = ul;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
250
src/core/dbus-client-track.c
Normal file
250
src/core/dbus-client-track.c
Normal 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;
|
||||
}
|
42
src/core/dbus-client-track.h
Normal file
42
src/core/dbus-client-track.h
Normal 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);
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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;
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
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 },
|
||||
{}
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
assert(bus);
|
||||
assert(message);
|
||||
assert(j);
|
||||
|
||||
if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Job", "Cancel")) {
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "stop");
|
||||
SELINUX_UNIT_ACCESS_CHECK(j->unit, bus, 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;
|
||||
return sd_bus_reply_method_return(bus, message, NULL);
|
||||
}
|
||||
|
||||
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(message);
|
||||
assert(m);
|
||||
|
||||
if (streq(dbus_message_get_path(message), "/org/freedesktop/systemd1/job")) {
|
||||
/* Be nice to gdbus and return introspection data for our mid-level paths */
|
||||
|
||||
if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
|
||||
_cleanup_free_ char *introspection = NULL;
|
||||
FILE *f;
|
||||
Iterator i;
|
||||
size_t size;
|
||||
|
||||
SELINUX_ACCESS_CHECK(connection, message, "status");
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
/* We roll our own introspection code here, instead of
|
||||
* relying on bus_default_message_handler() because we
|
||||
* need to generate our introspection string
|
||||
* dynamically. */
|
||||
|
||||
f = open_memstream(&introspection, &size);
|
||||
if (!f)
|
||||
goto oom;
|
||||
|
||||
fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
|
||||
"<node>\n", f);
|
||||
|
||||
fputs(BUS_INTROSPECTABLE_INTERFACE, f);
|
||||
fputs(BUS_PEER_INTERFACE, f);
|
||||
|
||||
HASHMAP_FOREACH(j, m->jobs, i)
|
||||
fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
|
||||
|
||||
fputs("</node>\n", f);
|
||||
|
||||
if (ferror(f)) {
|
||||
fclose(f);
|
||||
goto oom;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (!introspection)
|
||||
goto oom;
|
||||
|
||||
if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
|
||||
goto oom;
|
||||
}
|
||||
|
||||
if (!bus_maybe_send_reply(connection, message, reply))
|
||||
goto oom;
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
r = manager_get_job_from_dbus_path(m, dbus_message_get_path(message), &j);
|
||||
if (r == -ENOMEM)
|
||||
goto oom;
|
||||
if (r == -ENOENT) {
|
||||
DBusError e;
|
||||
|
||||
dbus_error_init(&e);
|
||||
dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown job");
|
||||
return bus_send_error_reply(connection, message, &e, r);
|
||||
}
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, NULL, r);
|
||||
|
||||
return bus_job_message_dispatch(j, connection, message);
|
||||
|
||||
oom:
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
oom:
|
||||
log_error("Failed to allocate job remove signal.");
|
||||
}
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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;
|
||||
|
||||
dbus_message_iter_recurse(i, &sub);
|
||||
while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
|
||||
_cleanup_strv_free_ char **argv = NULL;
|
||||
DBusMessageIter sub2;
|
||||
dbus_bool_t ignore;
|
||||
const char *path;
|
||||
|
||||
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_enter_container(message, 'a', "(sasb)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
dbus_message_iter_next(&sub2);
|
||||
while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
|
||||
_cleanup_strv_free_ char **argv = NULL;
|
||||
const char *path;
|
||||
int b;
|
||||
|
||||
if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) < 0)
|
||||
return -EINVAL;
|
||||
r = sd_bus_message_read(message, "s", &path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!path_is_absolute(path))
|
||||
return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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[];
|
||||
|
|
1370
src/core/dbus-unit.c
1370
src/core/dbus-unit.c
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
|
|
2240
src/core/dbus.c
2240
src/core/dbus.c
File diff suppressed because it is too large
Load diff
|
@ -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[];
|
||||
|
|
|
@ -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;
|
||||
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 (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 = udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd");
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = udev_monitor_enable_receiving(m->udev_monitor);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
e = udev_enumerate_new(m->udev);
|
||||
if (!e) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (udev_monitor_enable_receiving(m->udev_monitor) < 0) {
|
||||
r = -EIO;
|
||||
r = udev_enumerate_add_match_tag(e, "systemd");
|
||||
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;
|
||||
}
|
||||
|
||||
if (!(e = udev_enumerate_new(m->udev))) {
|
||||
r = -ENOMEM;
|
||||
r = udev_enumerate_scan_devices(e);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
if (udev_enumerate_add_match_tag(e, "systemd") < 0) {
|
||||
r = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (udev_enumerate_scan_devices(e) < 0) {
|
||||
r = -EIO;
|
||||
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
|
||||
* libudev might filter-out devices which pass the bloom
|
||||
* filter, so getting NULL here is not necessarily an error.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
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,
|
||||
|
|
|
@ -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_;
|
||||
|
|
199
src/core/job.c
199
src/core/job.c
|
@ -24,8 +24,8 @@
|
|||
#include <sys/timerfd.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#include "systemd/sd-id128.h"
|
||||
#include "systemd/sd-messages.h"
|
||||
#include "sd-id128.h"
|
||||
#include "sd-messages.h"
|
||||
#include "set.h"
|
||||
#include "unit.h"
|
||||
#include "macro.h"
|
||||
|
@ -37,20 +37,7 @@
|
|||
#include "special.h"
|
||||
#include "async.h"
|
||||
#include "virt.h"
|
||||
|
||||
JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) {
|
||||
JobBusClient *cl;
|
||||
size_t name_len;
|
||||
|
||||
name_len = strlen(name);
|
||||
cl = malloc0(sizeof(JobBusClient) + name_len + 1);
|
||||
if (!cl)
|
||||
return NULL;
|
||||
|
||||
cl->bus = connection;
|
||||
memcpy(cl->name, name, name_len + 1);
|
||||
return cl;
|
||||
}
|
||||
#include "dbus-client-track.h"
|
||||
|
||||
Job* job_new_raw(Unit *unit) {
|
||||
Job *j;
|
||||
|
@ -66,7 +53,6 @@ Job* job_new_raw(Unit *unit) {
|
|||
j->manager = unit->manager;
|
||||
j->unit = unit;
|
||||
j->type = _JOB_TYPE_INVALID;
|
||||
j->timer_watch.type = WATCH_INVALID;
|
||||
|
||||
return j;
|
||||
}
|
||||
|
@ -89,8 +75,6 @@ Job* job_new(Unit *unit, JobType type) {
|
|||
}
|
||||
|
||||
void job_free(Job *j) {
|
||||
JobBusClient *cl;
|
||||
|
||||
assert(j);
|
||||
assert(!j->installed);
|
||||
assert(!j->transaction_prev);
|
||||
|
@ -104,19 +88,10 @@ void job_free(Job *j) {
|
|||
if (j->in_dbus_queue)
|
||||
LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
|
||||
|
||||
if (j->timer_watch.type != WATCH_INVALID) {
|
||||
assert(j->timer_watch.type == WATCH_JOB_TIMER);
|
||||
assert(j->timer_watch.data.job == j);
|
||||
assert(j->timer_watch.fd >= 0);
|
||||
sd_event_source_unref(j->timer_event_source);
|
||||
|
||||
assert_se(epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_DEL, j->timer_watch.fd, NULL) >= 0);
|
||||
close_nointr_nofail(j->timer_watch.fd);
|
||||
}
|
||||
bus_client_track_free(j->subscribed);
|
||||
|
||||
while ((cl = j->bus_client_list)) {
|
||||
LIST_REMOVE(client, j->bus_client_list, cl);
|
||||
free(cl);
|
||||
}
|
||||
free(j);
|
||||
}
|
||||
|
||||
|
@ -859,48 +834,32 @@ finish:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *userdata) {
|
||||
Job *j = userdata;
|
||||
|
||||
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) {
|
||||
struct itimerspec its = {};
|
||||
struct epoll_event ev = {
|
||||
.data.ptr = &j->timer_watch,
|
||||
.events = EPOLLIN,
|
||||
};
|
||||
int fd, r;
|
||||
int r;
|
||||
|
||||
if (j->unit->job_timeout <= 0 ||
|
||||
j->timer_watch.type == WATCH_JOB_TIMER)
|
||||
if (j->unit->job_timeout <= 0 || j->timer_event_source)
|
||||
return 0;
|
||||
|
||||
assert(j->timer_watch.type == WATCH_INVALID);
|
||||
|
||||
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;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (fd >= 0)
|
||||
close_nointr_nofail(fd);
|
||||
j->begin_usec = now(CLOCK_MONOTONIC);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
141
src/core/mount.c
141
src/core/mount.c
|
@ -59,6 +59,9 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
|
|||
[MOUNT_FAILED] = UNIT_FAILED
|
||||
};
|
||||
|
||||
static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
|
||||
static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
|
||||
|
||||
static char* mount_test_option(const char *haystack, const char *needle) {
|
||||
struct mntent me = { .mnt_opts = (char*) haystack };
|
||||
|
||||
|
@ -156,13 +159,32 @@ static void mount_init(Unit *u) {
|
|||
* already trying to comply its last one. */
|
||||
m->exec_context.same_pgrp = true;
|
||||
|
||||
m->timer_watch.type = WATCH_INVALID;
|
||||
|
||||
m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
|
||||
|
||||
UNIT(m)->ignore_on_isolate = true;
|
||||
}
|
||||
|
||||
static int mount_arm_timer(Mount *m) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (m->timeout_usec <= 0) {
|
||||
m->timer_event_source = sd_event_source_unref(m->timer_event_source);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (m->timer_event_source) {
|
||||
r = sd_event_source_set_time(m->timer_event_source, now(CLOCK_MONOTONIC) + m->timeout_usec);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_event_source_set_enabled(m->timer_event_source, SD_EVENT_ONESHOT);
|
||||
}
|
||||
|
||||
return sd_event_add_monotonic(UNIT(m)->manager->event, now(CLOCK_MONOTONIC) + m->timeout_usec, 0, mount_dispatch_timer, m, &m->timer_event_source);
|
||||
}
|
||||
|
||||
static void mount_unwatch_control_pid(Mount *m) {
|
||||
assert(m);
|
||||
|
||||
|
@ -201,7 +223,7 @@ static void mount_done(Unit *u) {
|
|||
|
||||
mount_unwatch_control_pid(m);
|
||||
|
||||
unit_unwatch_timer(u, &m->timer_watch);
|
||||
m->timer_event_source = sd_event_source_unref(m->timer_event_source);
|
||||
}
|
||||
|
||||
_pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
|
||||
|
@ -626,7 +648,7 @@ static void mount_set_state(Mount *m, MountState state) {
|
|||
state != MOUNT_UNMOUNTING_SIGKILL &&
|
||||
state != MOUNT_REMOUNTING_SIGTERM &&
|
||||
state != MOUNT_REMOUNTING_SIGKILL) {
|
||||
unit_unwatch_timer(UNIT(m), &m->timer_watch);
|
||||
m->timer_event_source = sd_event_source_unref(m->timer_event_source);
|
||||
mount_unwatch_control_pid(m);
|
||||
m->control_command = NULL;
|
||||
m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
|
||||
|
@ -692,7 +714,7 @@ static int mount_coldplug(Unit *u) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
|
||||
r = mount_arm_timer(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
@ -751,7 +773,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
|
|||
|
||||
unit_realize_cgroup(UNIT(m));
|
||||
|
||||
r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
|
||||
r = mount_arm_timer(m);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -782,7 +804,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
unit_unwatch_timer(UNIT(m), &m->timer_watch);
|
||||
m->timer_event_source = sd_event_source_unref(m->timer_event_source);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -825,7 +847,7 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
|
|||
goto fail;
|
||||
|
||||
if (r > 0) {
|
||||
r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
|
||||
r = mount_arm_timer(m);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -959,17 +981,11 @@ static void mount_enter_remounting(Mount *m) {
|
|||
m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
|
||||
|
||||
if (m->from_fragment) {
|
||||
char *buf = NULL;
|
||||
const char *o;
|
||||
|
||||
if (m->parameters_fragment.options) {
|
||||
if (!(buf = strappend("remount,", m->parameters_fragment.options))) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
o = buf;
|
||||
} else
|
||||
if (m->parameters_fragment.options)
|
||||
o = strappenda("remount,", m->parameters_fragment.options);
|
||||
else
|
||||
o = "remount";
|
||||
|
||||
r = exec_command_set(
|
||||
|
@ -980,8 +996,6 @@ static void mount_enter_remounting(Mount *m) {
|
|||
"-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
|
||||
"-o", o,
|
||||
NULL);
|
||||
|
||||
free(buf);
|
||||
} else
|
||||
r = -ENOENT;
|
||||
|
||||
|
@ -990,7 +1004,8 @@ static void mount_enter_remounting(Mount *m) {
|
|||
|
||||
mount_unwatch_control_pid(m);
|
||||
|
||||
if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
|
||||
r = mount_spawn(m, m->control_command, &m->control_pid);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
mount_set_state(m, MOUNT_REMOUNTING);
|
||||
|
@ -1279,44 +1294,43 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
|||
unit_add_to_dbus_queue(u);
|
||||
}
|
||||
|
||||
static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
|
||||
Mount *m = MOUNT(u);
|
||||
static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
|
||||
Mount *m = MOUNT(userdata);
|
||||
|
||||
assert(m);
|
||||
assert(elapsed == 1);
|
||||
assert(w == &m->timer_watch);
|
||||
assert(m->timer_event_source == source);
|
||||
|
||||
switch (m->state) {
|
||||
|
||||
case MOUNT_MOUNTING:
|
||||
case MOUNT_MOUNTING_DONE:
|
||||
log_warning_unit(u->id,
|
||||
"%s mounting timed out. Stopping.", u->id);
|
||||
log_warning_unit(UNIT(m)->id,
|
||||
"%s mounting timed out. Stopping.", UNIT(m)->id);
|
||||
mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case MOUNT_REMOUNTING:
|
||||
log_warning_unit(u->id,
|
||||
"%s remounting timed out. Stopping.", u->id);
|
||||
log_warning_unit(UNIT(m)->id,
|
||||
"%s remounting timed out. Stopping.", UNIT(m)->id);
|
||||
m->reload_result = MOUNT_FAILURE_TIMEOUT;
|
||||
mount_enter_mounted(m, MOUNT_SUCCESS);
|
||||
break;
|
||||
|
||||
case MOUNT_UNMOUNTING:
|
||||
log_warning_unit(u->id,
|
||||
"%s unmounting timed out. Stopping.", u->id);
|
||||
log_warning_unit(UNIT(m)->id,
|
||||
"%s unmounting timed out. Stopping.", UNIT(m)->id);
|
||||
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case MOUNT_MOUNTING_SIGTERM:
|
||||
if (m->kill_context.send_sigkill) {
|
||||
log_warning_unit(u->id,
|
||||
"%s mounting timed out. Killing.", u->id);
|
||||
log_warning_unit(UNIT(m)->id,
|
||||
"%s mounting timed out. Killing.", UNIT(m)->id);
|
||||
mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_warning_unit(u->id,
|
||||
log_warning_unit(UNIT(m)->id,
|
||||
"%s mounting timed out. Skipping SIGKILL. Ignoring.",
|
||||
u->id);
|
||||
UNIT(m)->id);
|
||||
|
||||
if (m->from_proc_self_mountinfo)
|
||||
mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
|
||||
|
@ -1327,13 +1341,13 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
|
|||
|
||||
case MOUNT_REMOUNTING_SIGTERM:
|
||||
if (m->kill_context.send_sigkill) {
|
||||
log_warning_unit(u->id,
|
||||
"%s remounting timed out. Killing.", u->id);
|
||||
log_warning_unit(UNIT(m)->id,
|
||||
"%s remounting timed out. Killing.", UNIT(m)->id);
|
||||
mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_warning_unit(u->id,
|
||||
log_warning_unit(UNIT(m)->id,
|
||||
"%s remounting timed out. Skipping SIGKILL. Ignoring.",
|
||||
u->id);
|
||||
UNIT(m)->id);
|
||||
|
||||
if (m->from_proc_self_mountinfo)
|
||||
mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
|
||||
|
@ -1344,13 +1358,13 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
|
|||
|
||||
case MOUNT_UNMOUNTING_SIGTERM:
|
||||
if (m->kill_context.send_sigkill) {
|
||||
log_warning_unit(u->id,
|
||||
"%s unmounting timed out. Killing.", u->id);
|
||||
log_warning_unit(UNIT(m)->id,
|
||||
"%s unmounting timed out. Killing.", UNIT(m)->id);
|
||||
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_warning_unit(u->id,
|
||||
log_warning_unit(UNIT(m)->id,
|
||||
"%s unmounting timed out. Skipping SIGKILL. Ignoring.",
|
||||
u->id);
|
||||
UNIT(m)->id);
|
||||
|
||||
if (m->from_proc_self_mountinfo)
|
||||
mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
|
||||
|
@ -1362,9 +1376,9 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
|
|||
case MOUNT_MOUNTING_SIGKILL:
|
||||
case MOUNT_REMOUNTING_SIGKILL:
|
||||
case MOUNT_UNMOUNTING_SIGKILL:
|
||||
log_warning_unit(u->id,
|
||||
log_warning_unit(UNIT(m)->id,
|
||||
"%s mount process still around after SIGKILL. Ignoring.",
|
||||
u->id);
|
||||
UNIT(m)->id);
|
||||
|
||||
if (m->from_proc_self_mountinfo)
|
||||
mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
|
||||
|
@ -1375,6 +1389,8 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
|
|||
default:
|
||||
assert_not_reached("Timeout at wrong time.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mount_add_one(
|
||||
|
@ -1582,6 +1598,8 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
|
|||
static void mount_shutdown(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
m->mount_event_source = sd_event_source_unref(m->mount_event_source);
|
||||
|
||||
if (m->proc_self_mountinfo) {
|
||||
fclose(m->proc_self_mountinfo);
|
||||
m->proc_self_mountinfo = NULL;
|
||||
|
@ -1593,20 +1611,13 @@ static int mount_enumerate(Manager *m) {
|
|||
assert(m);
|
||||
|
||||
if (!m->proc_self_mountinfo) {
|
||||
struct epoll_event ev = {
|
||||
.events = EPOLLPRI,
|
||||
.data.ptr = &m->mount_watch,
|
||||
};
|
||||
|
||||
m->proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
|
||||
if (!m->proc_self_mountinfo)
|
||||
return -errno;
|
||||
|
||||
m->mount_watch.type = WATCH_MOUNT;
|
||||
m->mount_watch.fd = fileno(m->proc_self_mountinfo);
|
||||
|
||||
if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->mount_watch.fd, &ev) < 0)
|
||||
return -errno;
|
||||
r = sd_event_add_io(m->event, fileno(m->proc_self_mountinfo), EPOLLPRI, mount_dispatch_io, m, &m->mount_event_source);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = mount_load_proc_self_mountinfo(m, false);
|
||||
|
@ -1620,12 +1631,13 @@ fail:
|
|||
return r;
|
||||
}
|
||||
|
||||
void mount_fd_event(Manager *m, int events) {
|
||||
static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
|
||||
Manager *m = userdata;
|
||||
Unit *u;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(events & EPOLLPRI);
|
||||
assert(revents & EPOLLPRI);
|
||||
|
||||
/* The manager calls this for every fd event happening on the
|
||||
* /proc/self/mountinfo file, which informs us about mounting
|
||||
|
@ -1642,7 +1654,7 @@ void mount_fd_event(Manager *m, int events) {
|
|||
mount->is_mounted = mount->just_mounted = mount->just_changed = false;
|
||||
}
|
||||
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
manager_dispatch_load_queue(m);
|
||||
|
@ -1696,6 +1708,8 @@ void mount_fd_event(Manager *m, int events) {
|
|||
/* Reset the flags for later calls */
|
||||
mount->is_mounted = mount->just_mounted = mount->just_changed = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mount_reset_failed(Unit *u) {
|
||||
|
@ -1710,7 +1724,7 @@ static void mount_reset_failed(Unit *u) {
|
|||
m->reload_result = MOUNT_SUCCESS;
|
||||
}
|
||||
|
||||
static int mount_kill(Unit *u, KillWho who, int signo, DBusError *error) {
|
||||
static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
|
||||
return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error);
|
||||
}
|
||||
|
||||
|
@ -1753,15 +1767,15 @@ DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
|
|||
|
||||
const UnitVTable mount_vtable = {
|
||||
.object_size = sizeof(Mount),
|
||||
.exec_context_offset = offsetof(Mount, exec_context),
|
||||
.cgroup_context_offset = offsetof(Mount, cgroup_context),
|
||||
.kill_context_offset = offsetof(Mount, kill_context),
|
||||
|
||||
.sections =
|
||||
"Unit\0"
|
||||
"Mount\0"
|
||||
"Install\0",
|
||||
|
||||
.private_section = "Mount",
|
||||
.exec_context_offset = offsetof(Mount, exec_context),
|
||||
.cgroup_context_offset = offsetof(Mount, cgroup_context),
|
||||
|
||||
.no_alias = true,
|
||||
.no_instances = true,
|
||||
|
@ -1789,13 +1803,12 @@ const UnitVTable mount_vtable = {
|
|||
.check_gc = mount_check_gc,
|
||||
|
||||
.sigchld_event = mount_sigchld_event,
|
||||
.timer_event = mount_timer_event,
|
||||
|
||||
.reset_failed = mount_reset_failed,
|
||||
|
||||
.bus_interface = "org.freedesktop.systemd1.Mount",
|
||||
.bus_message_handler = bus_mount_message_handler,
|
||||
.bus_invalidating_properties = bus_mount_invalidating_properties,
|
||||
.bus_vtable = bus_mount_vtable,
|
||||
.bus_changing_properties = bus_mount_changing_properties,
|
||||
.bus_set_property = bus_mount_set_property,
|
||||
.bus_commit_properties = bus_mount_commit_properties,
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
unit_unwatch_fd(u, &s->watch);
|
||||
s->event_source = sd_event_source_unref(s->event_source);
|
||||
|
||||
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
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
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,
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ struct Scope {
|
|||
|
||||
Set *pids;
|
||||
|
||||
Watch timer_watch;
|
||||
sd_event_source *timer_event_source;
|
||||
};
|
||||
|
||||
extern const UnitVTable scope_vtable;
|
||||
|
|
|
@ -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;
|
||||
|
||||
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()) {
|
||||
if (!use_selinux())
|
||||
return 0;
|
||||
|
||||
r = access_init();
|
||||
if (r < 0) {
|
||||
dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to initialize SELinux.");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
r = service_arm_timer(s, timeout ? s->timeout_start_usec : 0);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
} else
|
||||
unit_unwatch_timer(UNIT(s), &s->timer_watch);
|
||||
|
||||
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,36 +3675,18 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int service_set_socket_fd(Service *s, int fd, Socket *sock) {
|
||||
|
@ -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...",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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,14 +1108,16 @@ 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_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";
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
case SOCKET_SPECIAL: return "Special";
|
||||
case SOCKET_MQUEUE: return "MessageQueue";
|
||||
case SOCKET_FIFO: return "FIFO";
|
||||
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,
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
113
src/core/swap.c
113
src/core/swap.c
|
@ -53,6 +53,9 @@ static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
|
|||
[SWAP_FAILED] = UNIT_FAILED
|
||||
};
|
||||
|
||||
static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
|
||||
static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
|
||||
|
||||
static void swap_unset_proc_swaps(Swap *s) {
|
||||
Swap *first;
|
||||
Hashmap *swaps;
|
||||
|
@ -96,8 +99,6 @@ static void swap_init(Unit *u) {
|
|||
|
||||
s->parameters_proc_swaps.priority = s->parameters_fragment.priority = -1;
|
||||
|
||||
s->timer_watch.type = WATCH_INVALID;
|
||||
|
||||
s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
|
||||
|
||||
UNIT(s)->ignore_on_isolate = true;
|
||||
|
@ -134,7 +135,28 @@ static void swap_done(Unit *u) {
|
|||
|
||||
swap_unwatch_control_pid(s);
|
||||
|
||||
unit_unwatch_timer(u, &s->timer_watch);
|
||||
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
|
||||
}
|
||||
|
||||
static int swap_arm_timer(Swap *s) {
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (s->timeout_usec <= 0) {
|
||||
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->timer_event_source) {
|
||||
r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
|
||||
}
|
||||
|
||||
return sd_event_add_monotonic(UNIT(s)->manager->event, now(CLOCK_MONOTONIC) + s->timeout_usec, 0, swap_dispatch_timer, s, &s->timer_event_source);
|
||||
}
|
||||
|
||||
static int swap_add_device_links(Swap *s) {
|
||||
|
@ -465,7 +487,7 @@ static void swap_set_state(Swap *s, SwapState state) {
|
|||
state != SWAP_DEACTIVATING &&
|
||||
state != SWAP_DEACTIVATING_SIGTERM &&
|
||||
state != SWAP_DEACTIVATING_SIGKILL) {
|
||||
unit_unwatch_timer(UNIT(s), &s->timer_watch);
|
||||
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
|
||||
swap_unwatch_control_pid(s);
|
||||
s->control_command = NULL;
|
||||
s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
|
||||
|
@ -511,7 +533,7 @@ static int swap_coldplug(Unit *u) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
|
||||
r = swap_arm_timer(s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
@ -576,7 +598,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
|
|||
|
||||
unit_realize_cgroup(UNIT(s));
|
||||
|
||||
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
|
||||
r = swap_arm_timer(s);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -607,7 +629,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
unit_unwatch_timer(UNIT(s), &s->timer_watch);
|
||||
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -650,7 +672,7 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
|
|||
goto fail;
|
||||
|
||||
if (r > 0) {
|
||||
r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
|
||||
r = swap_arm_timer(s);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -977,54 +999,55 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
|||
u->manager->request_reload = true;
|
||||
}
|
||||
|
||||
static void swap_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
|
||||
Swap *s = SWAP(u);
|
||||
static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
|
||||
Swap *s = SWAP(userdata);
|
||||
|
||||
assert(s);
|
||||
assert(elapsed == 1);
|
||||
assert(w == &s->timer_watch);
|
||||
assert(s->timer_event_source == source);
|
||||
|
||||
switch (s->state) {
|
||||
|
||||
case SWAP_ACTIVATING:
|
||||
log_warning_unit(u->id, "%s activation timed out. Stopping.", u->id);
|
||||
log_warning_unit(UNIT(s)->id, "%s activation timed out. Stopping.", UNIT(s)->id);
|
||||
swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case SWAP_DEACTIVATING:
|
||||
log_warning_unit(u->id, "%s deactivation timed out. Stopping.", u->id);
|
||||
log_warning_unit(UNIT(s)->id, "%s deactivation timed out. Stopping.", UNIT(s)->id);
|
||||
swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case SWAP_ACTIVATING_SIGTERM:
|
||||
if (s->kill_context.send_sigkill) {
|
||||
log_warning_unit(u->id, "%s activation timed out. Killing.", u->id);
|
||||
log_warning_unit(UNIT(s)->id, "%s activation timed out. Killing.", UNIT(s)->id);
|
||||
swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_warning_unit(u->id, "%s activation timed out. Skipping SIGKILL. Ignoring.", u->id);
|
||||
log_warning_unit(UNIT(s)->id, "%s activation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id);
|
||||
swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
|
||||
case SWAP_DEACTIVATING_SIGTERM:
|
||||
if (s->kill_context.send_sigkill) {
|
||||
log_warning_unit(u->id, "%s deactivation timed out. Killing.", u->id);
|
||||
log_warning_unit(UNIT(s)->id, "%s deactivation timed out. Killing.", UNIT(s)->id);
|
||||
swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_warning_unit(u->id, "%s deactivation timed out. Skipping SIGKILL. Ignoring.", u->id);
|
||||
log_warning_unit(UNIT(s)->id, "%s deactivation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id);
|
||||
swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
|
||||
case SWAP_ACTIVATING_SIGKILL:
|
||||
case SWAP_DEACTIVATING_SIGKILL:
|
||||
log_warning_unit(u->id, "%s swap process still around after SIGKILL. Ignoring.", u->id);
|
||||
log_warning_unit(UNIT(s)->id, "%s swap process still around after SIGKILL. Ignoring.", UNIT(s)->id);
|
||||
swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("Timeout at wrong time.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int swap_load_proc_swaps(Manager *m, bool set_flags) {
|
||||
|
@ -1068,23 +1091,13 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) {
|
|||
return r;
|
||||
}
|
||||
|
||||
int swap_dispatch_reload(Manager *m) {
|
||||
/* This function should go as soon as the kernel properly notifies us */
|
||||
|
||||
if (_likely_(!m->request_reload))
|
||||
return 0;
|
||||
|
||||
m->request_reload = false;
|
||||
|
||||
return swap_fd_event(m, EPOLLPRI);
|
||||
}
|
||||
|
||||
int swap_fd_event(Manager *m, int events) {
|
||||
static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
|
||||
Manager *m = userdata;
|
||||
Unit *u;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(events & EPOLLPRI);
|
||||
assert(revents & EPOLLPRI);
|
||||
|
||||
r = swap_load_proc_swaps(m, true);
|
||||
if (r < 0) {
|
||||
|
@ -1212,6 +1225,8 @@ fail:
|
|||
static void swap_shutdown(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
m->swap_event_source = sd_event_source_unref(m->swap_event_source);
|
||||
|
||||
if (m->proc_swaps) {
|
||||
fclose(m->proc_swaps);
|
||||
m->proc_swaps = NULL;
|
||||
|
@ -1226,26 +1241,23 @@ static int swap_enumerate(Manager *m) {
|
|||
assert(m);
|
||||
|
||||
if (!m->proc_swaps) {
|
||||
struct epoll_event ev = {
|
||||
.events = EPOLLPRI,
|
||||
.data.ptr = &m->swap_watch,
|
||||
};
|
||||
|
||||
m->proc_swaps = fopen("/proc/swaps", "re");
|
||||
if (!m->proc_swaps)
|
||||
return (errno == ENOENT) ? 0 : -errno;
|
||||
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,
|
||||
|
||||
|
|
|
@ -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_;
|
||||
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
unit_unwatch_timer(UNIT(t), &t->monotonic_watch);
|
||||
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 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
|
||||
unit_unwatch_timer(UNIT(t), &t->realtime_watch);
|
||||
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 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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,7 +262,8 @@ 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.",
|
||||
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,7 +407,7 @@ 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,
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
154
src/core/unit.c
154
src/core/unit.c
|
@ -29,8 +29,8 @@
|
|||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "systemd/sd-id128.h"
|
||||
#include "systemd/sd-messages.h"
|
||||
#include "sd-id128.h"
|
||||
#include "sd-messages.h"
|
||||
#include "set.h"
|
||||
#include "unit.h"
|
||||
#include "macro.h"
|
||||
|
@ -48,6 +48,7 @@
|
|||
#include "label.h"
|
||||
#include "fileio-label.h"
|
||||
#include "bus-errors.h"
|
||||
#include "dbus.h"
|
||||
|
||||
const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
|
||||
[UNIT_SERVICE] = &service_vtable,
|
||||
|
@ -326,7 +327,7 @@ void unit_add_to_dbus_queue(Unit *u) {
|
|||
return;
|
||||
|
||||
/* Shortcut things if nobody cares */
|
||||
if (!bus_has_subscriber(u->manager)) {
|
||||
if (set_isempty(u->manager->subscribed)) {
|
||||
u->sent_dbus_new_signal = true;
|
||||
return;
|
||||
}
|
||||
|
@ -1658,46 +1659,6 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
|
|||
unit_add_to_gc_queue(u);
|
||||
}
|
||||
|
||||
int unit_watch_fd(Unit *u, int fd, uint32_t events, Watch *w) {
|
||||
struct epoll_event ev = {
|
||||
.data.ptr = w,
|
||||
.events = events,
|
||||
};
|
||||
|
||||
assert(u);
|
||||
assert(fd >= 0);
|
||||
assert(w);
|
||||
assert(w->type == WATCH_INVALID || (w->type == WATCH_FD && w->fd == fd && w->data.unit == u));
|
||||
|
||||
if (epoll_ctl(u->manager->epoll_fd,
|
||||
w->type == WATCH_INVALID ? EPOLL_CTL_ADD : EPOLL_CTL_MOD,
|
||||
fd,
|
||||
&ev) < 0)
|
||||
return -errno;
|
||||
|
||||
w->fd = fd;
|
||||
w->type = WATCH_FD;
|
||||
w->data.unit = u;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void unit_unwatch_fd(Unit *u, Watch *w) {
|
||||
assert(u);
|
||||
assert(w);
|
||||
|
||||
if (w->type == WATCH_INVALID)
|
||||
return;
|
||||
|
||||
assert(w->type == WATCH_FD);
|
||||
assert(w->data.unit == u);
|
||||
assert_se(epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
|
||||
|
||||
w->fd = -1;
|
||||
w->type = WATCH_INVALID;
|
||||
w->data.unit = NULL;
|
||||
}
|
||||
|
||||
int unit_watch_pid(Unit *u, pid_t pid) {
|
||||
assert(u);
|
||||
assert(pid >= 1);
|
||||
|
@ -1715,90 +1676,6 @@ void unit_unwatch_pid(Unit *u, pid_t pid) {
|
|||
hashmap_remove_value(u->manager->watch_pids, LONG_TO_PTR(pid), u);
|
||||
}
|
||||
|
||||
int unit_watch_timer(Unit *u, clockid_t clock_id, bool relative, usec_t usec, Watch *w) {
|
||||
struct itimerspec its = {};
|
||||
int flags, fd;
|
||||
bool ours;
|
||||
|
||||
assert(u);
|
||||
assert(w);
|
||||
assert(w->type == WATCH_INVALID || (w->type == WATCH_UNIT_TIMER && w->data.unit == u));
|
||||
|
||||
/* This will try to reuse the old timer if there is one */
|
||||
|
||||
if (w->type == WATCH_UNIT_TIMER) {
|
||||
assert(w->data.unit == u);
|
||||
assert(w->fd >= 0);
|
||||
|
||||
ours = false;
|
||||
fd = w->fd;
|
||||
} else if (w->type == WATCH_INVALID) {
|
||||
|
||||
ours = true;
|
||||
fd = timerfd_create(clock_id, TFD_NONBLOCK|TFD_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
} else
|
||||
assert_not_reached("Invalid watch type");
|
||||
|
||||
if (usec <= 0) {
|
||||
/* Set absolute time in the past, but not 0, since we
|
||||
* don't want to disarm the timer */
|
||||
its.it_value.tv_sec = 0;
|
||||
its.it_value.tv_nsec = 1;
|
||||
|
||||
flags = TFD_TIMER_ABSTIME;
|
||||
} else {
|
||||
timespec_store(&its.it_value, usec);
|
||||
flags = relative ? 0 : TFD_TIMER_ABSTIME;
|
||||
}
|
||||
|
||||
/* This will also flush the elapse counter */
|
||||
if (timerfd_settime(fd, flags, &its, NULL) < 0)
|
||||
goto fail;
|
||||
|
||||
if (w->type == WATCH_INVALID) {
|
||||
struct epoll_event ev = {
|
||||
.data.ptr = w,
|
||||
.events = EPOLLIN,
|
||||
};
|
||||
|
||||
if (epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
w->type = WATCH_UNIT_TIMER;
|
||||
w->fd = fd;
|
||||
w->data.unit = u;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (ours)
|
||||
close_nointr_nofail(fd);
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
void unit_unwatch_timer(Unit *u, Watch *w) {
|
||||
assert(u);
|
||||
assert(w);
|
||||
|
||||
if (w->type == WATCH_INVALID)
|
||||
return;
|
||||
|
||||
assert(w->type == WATCH_UNIT_TIMER);
|
||||
assert(w->data.unit == u);
|
||||
assert(w->fd >= 0);
|
||||
|
||||
assert_se(epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
|
||||
close_nointr_nofail(w->fd);
|
||||
|
||||
w->fd = -1;
|
||||
w->type = WATCH_INVALID;
|
||||
w->data.unit = NULL;
|
||||
}
|
||||
|
||||
bool unit_job_is_applicable(Unit *u, JobType j) {
|
||||
assert(u);
|
||||
assert(j >= 0 && j < _JOB_TYPE_MAX);
|
||||
|
@ -2572,7 +2449,7 @@ bool unit_active_or_pending(Unit *u) {
|
|||
return false;
|
||||
}
|
||||
|
||||
int unit_kill(Unit *u, KillWho w, int signo, DBusError *error) {
|
||||
int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error) {
|
||||
assert(u);
|
||||
assert(w >= 0 && w < _KILL_WHO_MAX);
|
||||
assert(signo > 0);
|
||||
|
@ -2618,23 +2495,23 @@ int unit_kill_common(
|
|||
int signo,
|
||||
pid_t main_pid,
|
||||
pid_t control_pid,
|
||||
DBusError *error) {
|
||||
sd_bus_error *error) {
|
||||
|
||||
int r = 0;
|
||||
|
||||
if (who == KILL_MAIN && main_pid <= 0) {
|
||||
if (main_pid < 0)
|
||||
dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
|
||||
sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
|
||||
else
|
||||
dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
|
||||
sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
if (who == KILL_CONTROL && control_pid <= 0) {
|
||||
if (control_pid < 0)
|
||||
dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type));
|
||||
sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type));
|
||||
else
|
||||
dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
|
||||
sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
|
@ -2746,6 +2623,17 @@ ExecContext *unit_get_exec_context(Unit *u) {
|
|||
return (ExecContext*) ((uint8_t*) u + offset);
|
||||
}
|
||||
|
||||
KillContext *unit_get_kill_context(Unit *u) {
|
||||
size_t offset;
|
||||
assert(u);
|
||||
|
||||
offset = UNIT_VTABLE(u)->kill_context_offset;
|
||||
if (offset <= 0)
|
||||
return NULL;
|
||||
|
||||
return (KillContext*) ((uint8_t*) u + offset);
|
||||
}
|
||||
|
||||
CGroupContext *unit_get_cgroup_context(Unit *u) {
|
||||
size_t offset;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,14 +1547,19 @@ static int add_object_vtable_internal(
|
|||
return -ENOMEM;
|
||||
|
||||
LIST_FOREACH(vtables, i, n->vtables) {
|
||||
if (i->is_fallback != fallback) {
|
||||
r = -EPROTOTYPE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (streq(i->interface, interface)) {
|
||||
|
||||
if (i->vtable == vtable) {
|
||||
r = -EEXIST;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (i->is_fallback != fallback) {
|
||||
r = -EPROTOTYPE;
|
||||
goto fail;
|
||||
existing = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,6 +1891,21 @@ static int emit_properties_changed_on_interface(
|
|||
key.path = prefix;
|
||||
key.interface = interface;
|
||||
|
||||
LIST_FOREACH(vtables, c, n->vtables) {
|
||||
if (require_fallback && !c->is_fallback)
|
||||
continue;
|
||||
|
||||
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) {
|
||||
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
struct vtable_member *v;
|
||||
|
@ -1884,7 +1917,12 @@ static int emit_properties_changed_on_interface(
|
|||
if (!v)
|
||||
return -ENOENT;
|
||||
|
||||
assert(c == v->parent);
|
||||
/* 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) {
|
||||
|
@ -1892,6 +1930,8 @@ static int emit_properties_changed_on_interface(
|
|||
continue;
|
||||
}
|
||||
|
||||
has_changing = true;
|
||||
|
||||
r = sd_bus_message_open_container(m, 'e', "sv");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1918,6 +1958,10 @@ static int emit_properties_changed_on_interface(
|
|||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_invalidating && !has_changing)
|
||||
return 0;
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
|
@ -1928,6 +1972,21 @@ static int emit_properties_changed_on_interface(
|
|||
return r;
|
||||
|
||||
if (has_invalidating) {
|
||||
LIST_FOREACH(vtables, c, n->vtables) {
|
||||
if (require_fallback && !c->is_fallback)
|
||||
continue;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -1943,6 +2002,7 @@ static int emit_properties_changed_on_interface(
|
|||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
|
@ -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,19 +2108,18 @@ static int interfaces_added_append_one_prefix(
|
|||
if (require_fallback && !c->is_fallback)
|
||||
continue;
|
||||
|
||||
if (streq(c->interface, interface))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!c)
|
||||
return 0;
|
||||
if (!streq(c->interface, interface))
|
||||
continue;
|
||||
|
||||
r = node_vtable_get_userdata(bus, path, c, &u);
|
||||
if (r <= 0)
|
||||
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;
|
||||
|
@ -2068,17 +2128,23 @@ static int interfaces_added_append_one_prefix(
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = vtable_append_all_properties(bus, m,path, c, u, &error);
|
||||
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 (found_interface) {
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return found_interface;
|
||||
}
|
||||
|
||||
static int interfaces_added_append_one(
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#endif
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
#include <dbus.h>
|
||||
#include <dbus/dbus.h>
|
||||
#endif
|
||||
|
||||
#include "log.h"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
57
src/shared/bus-errors.h
Normal 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
|
@ -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
Loading…
Reference in a new issue