1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include "dbus-unit.h"
25 #include "dbus-timer.h"
27 #include "errno-list.h"
30 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, timer_result, TimerResult);
32 static int property_get_monotonic_timers(
35 const char *interface,
37 sd_bus_message *reply,
39 sd_bus_error *error) {
49 r = sd_bus_message_open_container(reply, 'a', "(stt)");
53 LIST_FOREACH(value, v, t->values) {
54 _cleanup_free_ char *buf = NULL;
58 if (v->base == TIMER_CALENDAR)
61 s = timer_base_to_string(v->base);
62 assert(endswith(s, "Sec"));
71 memcpy(buf+l-3, "USec", 5);
73 r = sd_bus_message_append(reply, "(stt)", buf, v->value, v->next_elapse);
78 return sd_bus_message_close_container(reply);
81 static int property_get_calendar_timers(
84 const char *interface,
86 sd_bus_message *reply,
88 sd_bus_error *error) {
98 r = sd_bus_message_open_container(reply, 'a', "(sst)");
102 LIST_FOREACH(value, v, t->values) {
103 _cleanup_free_ char *buf = NULL;
105 if (v->base != TIMER_CALENDAR)
108 r = calendar_spec_to_string(v->calendar_spec, &buf);
112 r = sd_bus_message_append(reply, "(sst)", timer_base_to_string(v->base), buf, v->next_elapse);
117 return sd_bus_message_close_container(reply);
120 static int property_get_unit(
123 const char *interface,
124 const char *property,
125 sd_bus_message *reply,
127 sd_bus_error *error) {
129 Unit *u = userdata, *trigger;
135 trigger = UNIT_TRIGGER(u);
137 return sd_bus_message_append(reply, "s", trigger ? trigger->id : "");
140 static int property_get_next_elapse_monotonic(
143 const char *interface,
144 const char *property,
145 sd_bus_message *reply,
147 sd_bus_error *error) {
156 if (t->next_elapse_monotonic_or_boottime <= 0)
158 else if (t->wake_system) {
161 a = now(CLOCK_MONOTONIC);
162 b = now(CLOCK_BOOTTIME);
164 if (t->next_elapse_monotonic_or_boottime + a > b)
165 x = t->next_elapse_monotonic_or_boottime + a - b;
169 x = t->next_elapse_monotonic_or_boottime;
171 return sd_bus_message_append(reply, "t", x);
174 const sd_bus_vtable bus_timer_vtable[] = {
175 SD_BUS_VTABLE_START(0),
176 SD_BUS_PROPERTY("Unit", "s", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
177 SD_BUS_PROPERTY("TimersMonotonic", "a(stt)", property_get_monotonic_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
178 SD_BUS_PROPERTY("TimersCalendar", "a(sst)", property_get_calendar_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
179 SD_BUS_PROPERTY("NextElapseUSecRealtime", "t", bus_property_get_usec, offsetof(Timer, next_elapse_realtime), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
180 SD_BUS_PROPERTY("NextElapseUSecMonotonic", "t", property_get_next_elapse_monotonic, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
181 BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
182 SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
183 SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
184 SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
185 SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
189 static int bus_timer_set_transient_property(
192 sd_bus_message *message,
193 UnitSetPropertiesMode mode,
194 sd_bus_error *error) {
207 "OnUnitInactiveSec")) {
210 TimerBase b = _TIMER_BASE_INVALID;
213 b = timer_base_from_string(name);
217 r = sd_bus_message_read(message, "t", &u);
221 if (mode != UNIT_CHECK) {
222 char time[FORMAT_TIMESPAN_MAX];
224 unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
226 v = new0(TimerValue, 1);
233 LIST_PREPEND(value, t->values, v);
238 } else if (streq(name, "OnCalendar")) {
241 CalendarSpec *c = NULL;
244 r = sd_bus_message_read(message, "s", &str);
248 if (mode != UNIT_CHECK) {
249 r = calendar_spec_from_string(str, &c);
253 unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, str);
255 v = new0(TimerValue, 1);
258 calendar_spec_free(c);
262 v->base = TIMER_CALENDAR;
263 v->calendar_spec = c;
265 LIST_PREPEND(value, t->values, v);
270 } else if (streq(name, "AccuracySec")) {
274 r = sd_bus_message_read(message, "t", &u);
278 if (mode != UNIT_CHECK) {
279 char time[FORMAT_TIMESPAN_MAX];
281 t->accuracy_usec = u;
282 unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
287 } else if (streq(name, "WakeSystem")) {
291 r = sd_bus_message_read(message, "b", &b);
295 if (mode != UNIT_CHECK) {
297 unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, yes_no(t->wake_system));
307 int bus_timer_set_property(
310 sd_bus_message *message,
311 UnitSetPropertiesMode mode,
312 sd_bus_error *error) {
321 if (u->transient && u->load_state == UNIT_STUB) {
322 r = bus_timer_set_transient_property(t, name, message, mode, error);