X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fdbus-timer.c;h=43e785246cd9c053fd50f2cadc7c76273429eb73;hb=c529695e7a30b300fdaa61ace4a8a4ed0e94ad1c;hp=c6f1dd9b7f72bd804cd84c87d844cca174ff62f1;hpb=ca2871d9b027018c108e0cf7bbc4e5a919e300c3;p=elogind.git
diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c
index c6f1dd9b7..43e785246 100644
--- a/src/core/dbus-timer.c
+++ b/src/core/dbus-timer.c
@@ -19,173 +19,310 @@
along with systemd; If not, see .
***/
-#include
-
+#include "unit.h"
+#include "timer.h"
#include "dbus-unit.h"
#include "dbus-timer.h"
-#include "dbus-execute.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_TIMER_INTERFACE \
- " \n" \
- " \n" \
- " \n" \
- " \n" \
- " \n" \
- " \n" \
- " \n" \
- " \n"
-
-#define INTROSPECTION \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "\n" \
- BUS_UNIT_INTERFACE \
- BUS_TIMER_INTERFACE \
- BUS_PROPERTIES_INTERFACE \
- BUS_PEER_INTERFACE \
- BUS_INTROSPECTABLE_INTERFACE \
- "\n"
-
-#define INTERFACES_LIST \
- BUS_UNIT_INTERFACES_LIST \
- "org.freedesktop.systemd1.Timer\0"
-
-const char bus_timer_interface[] = BUS_TIMER_INTERFACE;
-
-const char bus_timer_invalidating_properties[] =
- "TimersMonotonic\0"
- "TimersRealtime\0"
- "NextElapseUSecRealtime\0"
- "NextElapseUSecMonotonic\0"
- "Result\0";
-
-static int bus_timer_append_monotonic_timers(DBusMessageIter *i, const char *property, void *data) {
- Timer *p = data;
- DBusMessageIter sub, sub2;
- TimerValue *k;
-
- assert(i);
- assert(property);
- assert(p);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(stt)", &sub))
- return -ENOMEM;
-
- LIST_FOREACH(value, k, p->values) {
+#include "bus-util.h"
+#include "errno-list.h"
+#include "strv.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, timer_result, TimerResult);
+
+static int property_get_monotonic_timers(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Timer *t = userdata;
+ TimerValue *v;
+ int r;
+
+ assert(bus);
+ assert(reply);
+ assert(t);
+
+ r = sd_bus_message_open_container(reply, 'a', "(stt)");
+ if (r < 0)
+ return r;
+
+ LIST_FOREACH(value, v, t->values) {
_cleanup_free_ char *buf = NULL;
- const char *t;
+ const char *s;
size_t l;
- bool b;
- if (k->base == TIMER_CALENDAR)
+ if (v->base == TIMER_CALENDAR)
continue;
- t = timer_base_to_string(k->base);
- assert(endswith(t, "Sec"));
+ s = timer_base_to_string(v->base);
+ assert(endswith(s, "Sec"));
/* s/Sec/USec/ */
- l = strlen(t);
+ l = strlen(s);
buf = new(char, l+2);
if (!buf)
return -ENOMEM;
- memcpy(buf, t, l-3);
+ memcpy(buf, s, l-3);
memcpy(buf+l-3, "USec", 5);
- b = dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &buf) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->value) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->next_elapse) &&
- dbus_message_iter_close_container(&sub, &sub2);
-
- if (!b)
- return -ENOMEM;
+ r = sd_bus_message_append(reply, "(stt)", buf, v->value, v->next_elapse);
+ if (r < 0)
+ return r;
}
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
+ return sd_bus_message_close_container(reply);
}
-static int bus_timer_append_calendar_timers(DBusMessageIter *i, const char *property, void *data) {
- Timer *p = data;
- DBusMessageIter sub, sub2;
- TimerValue *k;
+static int property_get_calendar_timers(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Timer *t = userdata;
+ TimerValue *v;
+ int r;
- assert(i);
- assert(property);
- assert(p);
+ assert(bus);
+ assert(reply);
+ assert(t);
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sst)", &sub))
- return -ENOMEM;
+ r = sd_bus_message_open_container(reply, 'a', "(sst)");
+ if (r < 0)
+ return r;
- LIST_FOREACH(value, k, p->values) {
+ LIST_FOREACH(value, v, t->values) {
_cleanup_free_ char *buf = NULL;
- const char *t;
- bool b;
- int j;
- if (k->base != TIMER_CALENDAR)
+ if (v->base != TIMER_CALENDAR)
continue;
- t = timer_base_to_string(k->base);
- j = calendar_spec_to_string(k->calendar_spec, &buf);
- if (j < 0)
- return j;
-
- b = dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &t) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &buf) &&
- dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->next_elapse) &&
- dbus_message_iter_close_container(&sub, &sub2);
+ r = calendar_spec_to_string(v->calendar_spec, &buf);
+ if (r < 0)
+ return r;
- if (!b)
- return -ENOMEM;
+ r = sd_bus_message_append(reply, "(sst)", timer_base_to_string(v->base), buf, v->next_elapse);
+ if (r < 0)
+ return r;
}
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
+ return sd_bus_message_close_container(reply);
}
-static int bus_timer_append_unit(DBusMessageIter *i, const char *property, void *data) {
- Unit *u = data, *trigger;
- const char *t;
+static int property_get_unit(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Unit *u = userdata, *trigger;
- assert(i);
- assert(property);
+ assert(bus);
+ assert(reply);
assert(u);
trigger = UNIT_TRIGGER(u);
- t = trigger ? trigger->id : "";
- return dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t) ? 0 : -ENOMEM;
+ return sd_bus_message_append(reply, "s", trigger ? trigger->id : "");
}
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_timer_append_timer_result, timer_result, TimerResult);
+static int property_get_next_elapse_monotonic(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Timer *t = userdata;
+ usec_t x;
+
+ assert(bus);
+ assert(reply);
+ assert(t);
+
+ if (t->next_elapse_monotonic_or_boottime <= 0)
+ x = 0;
+ else if (t->wake_system) {
+ usec_t a, b;
+
+ a = now(CLOCK_MONOTONIC);
+ b = now(CLOCK_BOOTTIME);
+
+ if (t->next_elapse_monotonic_or_boottime + a > b)
+ x = t->next_elapse_monotonic_or_boottime + a - b;
+ else
+ x = 0;
+ } else
+ x = t->next_elapse_monotonic_or_boottime;
+
+ return sd_bus_message_append(reply, "t", x);
+}
-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, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("TimersMonotonic", "a(stt)", property_get_monotonic_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
+ SD_BUS_PROPERTY("TimersCalendar", "a(sst)", property_get_calendar_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
+ SD_BUS_PROPERTY("NextElapseUSecRealtime", "t", bus_property_get_usec, offsetof(Timer, next_elapse_realtime), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("NextElapseUSecMonotonic", "t", property_get_next_elapse_monotonic, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), 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_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_VTABLE_END
};
-DBusHandlerResult bus_timer_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
+static int bus_timer_set_transient_property(
+ Timer *t,
+ const char *name,
+ sd_bus_message *message,
+ UnitSetPropertiesMode mode,
+ sd_bus_error *error) {
+
+ int r;
+
+ assert(t);
+ assert(name);
+ assert(message);
+
+ if (STR_IN_SET(name,
+ "OnActiveSec",
+ "OnBootSec",
+ "OnStartupSec",
+ "OnUnitActiveSec",
+ "OnUnitInactiveSec")) {
+
+ TimerValue *v;
+ TimerBase b = _TIMER_BASE_INVALID;
+ usec_t u = 0;
+
+ b = timer_base_from_string(name);
+ if (b < 0)
+ return -EINVAL;
+
+ r = sd_bus_message_read(message, "t", &u);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ char time[FORMAT_TIMESPAN_MAX];
+
+ unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
+
+ v = new0(TimerValue, 1);
+ if (!v)
+ return -ENOMEM;
+
+ v->base = b;
+ v->value = u;
+
+ LIST_PREPEND(value, t->values, v);
+ }
+
+ return 1;
+
+ } else if (streq(name, "OnCalendar")) {
+
+ TimerValue *v;
+ CalendarSpec *c = NULL;
+ const char *str;
+
+ r = sd_bus_message_read(message, "s", &str);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ r = calendar_spec_from_string(str, &c);
+ if (r < 0)
+ return r;
+
+ unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, str);
+
+ v = new0(TimerValue, 1);
+ if (!v) {
+ if (c)
+ calendar_spec_free(c);
+ return -ENOMEM;
+ }
+
+ v->base = TIMER_CALENDAR;
+ v->calendar_spec = c;
+
+ LIST_PREPEND(value, t->values, v);
+ }
+
+ return 1;
+
+ } else if (streq(name, "AccuracySec")) {
+
+ usec_t u = 0;
+
+ r = sd_bus_message_read(message, "t", &u);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ char time[FORMAT_TIMESPAN_MAX];
+
+ t->accuracy_usec = u;
+ unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
+ }
+
+ return 1;
+
+ } else if (streq(name, "WakeSystem")) {
+
+ int b;
+
+ r = sd_bus_message_read(message, "b", &b);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ t->wake_system = b;
+ unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, yes_no(t->wake_system));
+ }
+
+ return 1;
+
+ }
+
+ return 0;
+}
+
+int bus_timer_set_property(
+ Unit *u,
+ const char *name,
+ sd_bus_message *message,
+ UnitSetPropertiesMode mode,
+ sd_bus_error *error) {
+
Timer *t = TIMER(u);
- const BusBoundProperties bps[] = {
- { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
- { "org.freedesktop.systemd1.Timer", bus_timer_properties, t },
- { NULL, }
- };
+ int r;
- SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
+ assert(t);
+ assert(name);
+ assert(message);
- return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
+ if (u->transient && u->load_state == UNIT_STUB) {
+ r = bus_timer_set_transient_property(t, name, message, mode, error);
+ if (r != 0)
+ return r;
+ }
+
+ return 0;
}