]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-timer.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / core / dbus-timer.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
871d7de4
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
871d7de4
LP
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 15 Lesser General Public License for more details.
871d7de4 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
871d7de4
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
b5efdb8a 21#include "alloc-util.h"
718db961 22#include "bus-util.h"
b5efdb8a 23#include "dbus-timer.h"
d8a812d1 24#include "strv.h"
b5efdb8a
LP
25#include "timer.h"
26#include "unit.h"
718db961
LP
27
28static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, timer_result, TimerResult);
29
30static int property_get_monotonic_timers(
31 sd_bus *bus,
32 const char *path,
33 const char *interface,
34 const char *property,
35 sd_bus_message *reply,
ebcf1f97
LP
36 void *userdata,
37 sd_bus_error *error) {
718db961
LP
38
39 Timer *t = userdata;
40 TimerValue *v;
41 int r;
42
43 assert(bus);
44 assert(reply);
45 assert(t);
46
47 r = sd_bus_message_open_container(reply, 'a', "(stt)");
48 if (r < 0)
49 return r;
50
51 LIST_FOREACH(value, v, t->values) {
3761902e 52 _cleanup_free_ char *buf = NULL;
718db961 53 const char *s;
03fae018 54 size_t l;
707e5e52 55
718db961 56 if (v->base == TIMER_CALENDAR)
b719810d 57 continue;
03fae018 58
718db961
LP
59 s = timer_base_to_string(v->base);
60 assert(endswith(s, "Sec"));
3761902e 61
b719810d 62 /* s/Sec/USec/ */
718db961 63 l = strlen(s);
b719810d
LP
64 buf = new(char, l+2);
65 if (!buf)
66 return -ENOMEM;
03fae018 67
718db961 68 memcpy(buf, s, l-3);
b719810d 69 memcpy(buf+l-3, "USec", 5);
03fae018 70
718db961
LP
71 r = sd_bus_message_append(reply, "(stt)", buf, v->value, v->next_elapse);
72 if (r < 0)
73 return r;
707e5e52
LP
74 }
75
718db961 76 return sd_bus_message_close_container(reply);
707e5e52
LP
77}
78
718db961
LP
79static int property_get_calendar_timers(
80 sd_bus *bus,
81 const char *path,
82 const char *interface,
83 const char *property,
84 sd_bus_message *reply,
ebcf1f97
LP
85 void *userdata,
86 sd_bus_error *error) {
b719810d 87
718db961
LP
88 Timer *t = userdata;
89 TimerValue *v;
90 int r;
b719810d 91
718db961
LP
92 assert(bus);
93 assert(reply);
94 assert(t);
b719810d 95
718db961
LP
96 r = sd_bus_message_open_container(reply, 'a', "(sst)");
97 if (r < 0)
98 return r;
99
100 LIST_FOREACH(value, v, t->values) {
b719810d 101 _cleanup_free_ char *buf = NULL;
b719810d 102
718db961 103 if (v->base != TIMER_CALENDAR)
b719810d
LP
104 continue;
105
718db961
LP
106 r = calendar_spec_to_string(v->calendar_spec, &buf);
107 if (r < 0)
108 return r;
b719810d 109
718db961
LP
110 r = sd_bus_message_append(reply, "(sst)", timer_base_to_string(v->base), buf, v->next_elapse);
111 if (r < 0)
112 return r;
b719810d
LP
113 }
114
718db961 115 return sd_bus_message_close_container(reply);
b719810d
LP
116}
117
718db961
LP
118static int property_get_unit(
119 sd_bus *bus,
120 const char *path,
121 const char *interface,
122 const char *property,
123 sd_bus_message *reply,
ebcf1f97
LP
124 void *userdata,
125 sd_bus_error *error) {
718db961
LP
126
127 Unit *u = userdata, *trigger;
b284eabd 128
718db961
LP
129 assert(bus);
130 assert(reply);
b284eabd
LP
131 assert(u);
132
3ecaa09b 133 trigger = UNIT_TRIGGER(u);
b284eabd 134
718db961 135 return sd_bus_message_append(reply, "s", trigger ? trigger->id : "");
b284eabd
LP
136}
137
dedabea4
LP
138static int property_get_next_elapse_monotonic(
139 sd_bus *bus,
140 const char *path,
141 const char *interface,
142 const char *property,
143 sd_bus_message *reply,
144 void *userdata,
145 sd_bus_error *error) {
146
147 Timer *t = userdata;
dedabea4
LP
148
149 assert(bus);
150 assert(reply);
151 assert(t);
152
79fc8b96
LP
153 return sd_bus_message_append(reply, "t",
154 (uint64_t) usec_shift_clock(t->next_elapse_monotonic_or_boottime,
155 TIMER_MONOTONIC_CLOCK(t), CLOCK_MONOTONIC));
dedabea4
LP
156}
157
718db961
LP
158const sd_bus_vtable bus_timer_vtable[] = {
159 SD_BUS_VTABLE_START(0),
556089dc
LP
160 SD_BUS_PROPERTY("Unit", "s", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
161 SD_BUS_PROPERTY("TimersMonotonic", "a(stt)", property_get_monotonic_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
162 SD_BUS_PROPERTY("TimersCalendar", "a(sst)", property_get_calendar_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
454f7158 163 SD_BUS_PROPERTY("NextElapseUSecRealtime", "t", bus_property_get_usec, offsetof(Timer, next_elapse_realtime), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
dedabea4
LP
164 SD_BUS_PROPERTY("NextElapseUSecMonotonic", "t", property_get_next_elapse_monotonic, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
165 BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
718db961 166 SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
556089dc 167 SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
6f5d7998 168 SD_BUS_PROPERTY("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
06642d17 169 SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
dedabea4 170 SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
3e0c30ac 171 SD_BUS_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST),
718db961 172 SD_BUS_VTABLE_END
d200735e 173};
d8a812d1
WC
174
175static int bus_timer_set_transient_property(
176 Timer *t,
177 const char *name,
178 sd_bus_message *message,
179 UnitSetPropertiesMode mode,
180 sd_bus_error *error) {
181
182 int r;
183
184 assert(t);
185 assert(name);
186 assert(message);
187
188 if (STR_IN_SET(name,
189 "OnActiveSec",
190 "OnBootSec",
191 "OnStartupSec",
192 "OnUnitActiveSec",
193 "OnUnitInactiveSec")) {
194
195 TimerValue *v;
196 TimerBase b = _TIMER_BASE_INVALID;
197 usec_t u = 0;
198
199 b = timer_base_from_string(name);
200 if (b < 0)
201 return -EINVAL;
202
203 r = sd_bus_message_read(message, "t", &u);
204 if (r < 0)
205 return r;
206
207 if (mode != UNIT_CHECK) {
208 char time[FORMAT_TIMESPAN_MAX];
209
b27b4b51 210 unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s", name, format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
d8a812d1
WC
211
212 v = new0(TimerValue, 1);
213 if (!v)
214 return -ENOMEM;
215
216 v->base = b;
217 v->value = u;
218
219 LIST_PREPEND(value, t->values, v);
220 }
221
222 return 1;
223
224 } else if (streq(name, "OnCalendar")) {
225
226 TimerValue *v;
227 CalendarSpec *c = NULL;
228 const char *str;
229
230 r = sd_bus_message_read(message, "s", &str);
231 if (r < 0)
232 return r;
233
234 if (mode != UNIT_CHECK) {
235 r = calendar_spec_from_string(str, &c);
236 if (r < 0)
237 return r;
238
b27b4b51 239 unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s", name, str);
d8a812d1
WC
240
241 v = new0(TimerValue, 1);
242 if (!v) {
3e044c49 243 calendar_spec_free(c);
d8a812d1
WC
244 return -ENOMEM;
245 }
246
247 v->base = TIMER_CALENDAR;
248 v->calendar_spec = c;
249
250 LIST_PREPEND(value, t->values, v);
251 }
252
253 return 1;
254
b93ea5d3 255 } else if (STR_IN_SET(name, "AccuracyUSec", "AccuracySec")) {
d8a812d1
WC
256 usec_t u = 0;
257
b93ea5d3
LP
258 if (streq(name, "AccuracySec"))
259 log_notice("Client is using obsolete AccuracySec= transient property, please use AccuracyUSec= instead.");
260
d8a812d1
WC
261 r = sd_bus_message_read(message, "t", &u);
262 if (r < 0)
263 return r;
264
265 if (mode != UNIT_CHECK) {
d8a812d1 266 t->accuracy_usec = u;
b27b4b51 267 unit_write_drop_in_private_format(UNIT(t), mode, name, "AccuracySec=" USEC_FMT "us", u);
d8a812d1
WC
268 }
269
270 return 1;
271
6f5d7998 272 } else if (streq(name, "RandomizedDelayUSec")) {
744c7693
LP
273 usec_t u = 0;
274
275 r = sd_bus_message_read(message, "t", &u);
276 if (r < 0)
277 return r;
278
279 if (mode != UNIT_CHECK) {
744c7693 280 t->random_usec = u;
b27b4b51 281 unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomizedDelaySec=" USEC_FMT "us", u);
744c7693
LP
282 }
283
284 return 1;
285
d8a812d1 286 } else if (streq(name, "WakeSystem")) {
d8a812d1
WC
287 int b;
288
289 r = sd_bus_message_read(message, "b", &b);
290 if (r < 0)
291 return r;
292
293 if (mode != UNIT_CHECK) {
294 t->wake_system = b;
b27b4b51 295 unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s", name, yes_no(b));
d8a812d1
WC
296 }
297
298 return 1;
299
3e0c30ac
LP
300 } else if (streq(name, "RemainAfterElapse")) {
301 int b;
302
303 r = sd_bus_message_read(message, "b", &b);
304 if (r < 0)
305 return r;
306
307 if (mode != UNIT_CHECK) {
308 t->remain_after_elapse = b;
b27b4b51 309 unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s", name, yes_no(b));
3e0c30ac
LP
310 }
311
312 return 1;
d8a812d1
WC
313 }
314
315 return 0;
316}
317
318int bus_timer_set_property(
319 Unit *u,
320 const char *name,
321 sd_bus_message *message,
322 UnitSetPropertiesMode mode,
323 sd_bus_error *error) {
324
325 Timer *t = TIMER(u);
326 int r;
327
328 assert(t);
329 assert(name);
330 assert(message);
331
332 if (u->transient && u->load_state == UNIT_STUB) {
333 r = bus_timer_set_transient_property(t, name, message, mode, error);
334 if (r != 0)
335 return r;
336 }
337
338 return 0;
339}