]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-timer.c
analyze: fix typo
[thirdparty/systemd.git] / src / core / dbus-timer.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
871d7de4 2
b5efdb8a 3#include "alloc-util.h"
40af3d02 4#include "bus-get-properties.h"
836e4e7e 5#include "calendarspec.h"
b5efdb8a 6#include "dbus-timer.h"
3e3c5a45 7#include "dbus-util.h"
836e4e7e 8#include "string-util.h"
d8a812d1 9#include "strv.h"
b5efdb8a
LP
10#include "timer.h"
11#include "unit.h"
718db961
LP
12
13static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, timer_result, TimerResult);
14
15static int property_get_monotonic_timers(
16 sd_bus *bus,
17 const char *path,
18 const char *interface,
19 const char *property,
20 sd_bus_message *reply,
ebcf1f97
LP
21 void *userdata,
22 sd_bus_error *error) {
718db961 23
99534007 24 Timer *t = ASSERT_PTR(userdata);
718db961
LP
25 int r;
26
27 assert(bus);
28 assert(reply);
718db961
LP
29
30 r = sd_bus_message_open_container(reply, 'a', "(stt)");
31 if (r < 0)
32 return r;
33
34 LIST_FOREACH(value, v, t->values) {
f8a990a0 35 _cleanup_free_ char *usec = NULL;
707e5e52 36
718db961 37 if (v->base == TIMER_CALENDAR)
b719810d 38 continue;
03fae018 39
f8a990a0
DDM
40 usec = timer_base_to_usec_string(v->base);
41 if (!usec)
b719810d 42 return -ENOMEM;
03fae018 43
f8a990a0 44 r = sd_bus_message_append(reply, "(stt)", usec, v->value, v->next_elapse);
718db961
LP
45 if (r < 0)
46 return r;
707e5e52
LP
47 }
48
718db961 49 return sd_bus_message_close_container(reply);
707e5e52
LP
50}
51
718db961
LP
52static int property_get_calendar_timers(
53 sd_bus *bus,
54 const char *path,
55 const char *interface,
56 const char *property,
57 sd_bus_message *reply,
ebcf1f97
LP
58 void *userdata,
59 sd_bus_error *error) {
b719810d 60
99534007 61 Timer *t = ASSERT_PTR(userdata);
718db961 62 int r;
b719810d 63
718db961
LP
64 assert(bus);
65 assert(reply);
b719810d 66
718db961
LP
67 r = sd_bus_message_open_container(reply, 'a', "(sst)");
68 if (r < 0)
69 return r;
70
71 LIST_FOREACH(value, v, t->values) {
b719810d 72 _cleanup_free_ char *buf = NULL;
b719810d 73
718db961 74 if (v->base != TIMER_CALENDAR)
b719810d
LP
75 continue;
76
718db961
LP
77 r = calendar_spec_to_string(v->calendar_spec, &buf);
78 if (r < 0)
79 return r;
b719810d 80
718db961
LP
81 r = sd_bus_message_append(reply, "(sst)", timer_base_to_string(v->base), buf, v->next_elapse);
82 if (r < 0)
83 return r;
b719810d
LP
84 }
85
718db961 86 return sd_bus_message_close_container(reply);
b719810d
LP
87}
88
dedabea4
LP
89static int property_get_next_elapse_monotonic(
90 sd_bus *bus,
91 const char *path,
92 const char *interface,
93 const char *property,
94 sd_bus_message *reply,
95 void *userdata,
96 sd_bus_error *error) {
97
99534007 98 Timer *t = ASSERT_PTR(userdata);
dedabea4
LP
99
100 assert(bus);
101 assert(reply);
dedabea4 102
f8a990a0 103 return sd_bus_message_append(reply, "t", timer_next_elapse_monotonic(t));
dedabea4
LP
104}
105
718db961
LP
106const sd_bus_vtable bus_timer_vtable[] = {
107 SD_BUS_VTABLE_START(0),
54138a8d 108 SD_BUS_PROPERTY("Unit", "s", bus_property_get_triggered_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
109 SD_BUS_PROPERTY("TimersMonotonic", "a(stt)", property_get_monotonic_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
110 SD_BUS_PROPERTY("TimersCalendar", "a(sst)", property_get_calendar_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
efebb613
LP
111 SD_BUS_PROPERTY("OnClockChange", "b", bus_property_get_bool, offsetof(Timer, on_clock_change), SD_BUS_VTABLE_PROPERTY_CONST),
112 SD_BUS_PROPERTY("OnTimezoneChange", "b", bus_property_get_bool, offsetof(Timer, on_timezone_change), SD_BUS_VTABLE_PROPERTY_CONST),
454f7158 113 SD_BUS_PROPERTY("NextElapseUSecRealtime", "t", bus_property_get_usec, offsetof(Timer, next_elapse_realtime), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
dedabea4
LP
114 SD_BUS_PROPERTY("NextElapseUSecMonotonic", "t", property_get_next_elapse_monotonic, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
115 BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
718db961 116 SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
556089dc 117 SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
9a0749c8
AV
118 SD_BUS_PROPERTY("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_delay_usec), SD_BUS_VTABLE_PROPERTY_CONST),
119 SD_BUS_PROPERTY("RandomizedOffsetUSec", "t", bus_property_get_usec, offsetof(Timer, random_offset_usec), SD_BUS_VTABLE_PROPERTY_CONST),
acf24a1a 120 SD_BUS_PROPERTY("FixedRandomDelay", "b", bus_property_get_bool, offsetof(Timer, fixed_random_delay), SD_BUS_VTABLE_PROPERTY_CONST),
06642d17 121 SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
dedabea4 122 SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
3e0c30ac 123 SD_BUS_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST),
cc0ab8c8 124 SD_BUS_PROPERTY("DeferReactivation", "b", bus_property_get_bool, offsetof(Timer, defer_reactivation), SD_BUS_VTABLE_PROPERTY_CONST),
718db961 125 SD_BUS_VTABLE_END
d200735e 126};
d8a812d1 127
cd87f634
ZJS
128static int timer_add_one_monotonic_spec(
129 Timer *t,
130 const char *name,
131 TimerBase base,
132 UnitWriteFlags flags,
133 usec_t usec,
134 sd_bus_error *error) {
135
136 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
cd87f634
ZJS
137 TimerValue *v;
138
139 unit_write_settingf(UNIT(t), flags|UNIT_ESCAPE_SPECIFIERS, name,
140 "%s=%s",
141 timer_base_to_string(base),
5291f26d 142 FORMAT_TIMESPAN(usec, USEC_PER_MSEC));
cd87f634
ZJS
143
144 v = new(TimerValue, 1);
145 if (!v)
146 return -ENOMEM;
147
148 *v = (TimerValue) {
149 .base = base,
150 .value = usec,
151 };
152
153 LIST_PREPEND(value, t->values, v);
154 }
155
156 return 1;
157}
158
d00a52c7
ZJS
159static int timer_add_one_calendar_spec(
160 Timer *t,
161 const char *name,
162 TimerBase base,
163 UnitWriteFlags flags,
164 const char *str,
165 sd_bus_error *error) {
166
167 _cleanup_(calendar_spec_freep) CalendarSpec *c = NULL;
168 int r;
169
170 r = calendar_spec_from_string(str, &c);
171 if (r == -EINVAL)
1b09b81c 172 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid calendar spec");
d00a52c7
ZJS
173 if (r < 0)
174 return r;
175
176 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
177 unit_write_settingf(UNIT(t), flags|UNIT_ESCAPE_SPECIFIERS, name,
178 "%s=%s", timer_base_to_string(base), str);
179
180 TimerValue *v = new(TimerValue, 1);
181 if (!v)
182 return -ENOMEM;
183
184 *v = (TimerValue) {
185 .base = base,
23f8fbb3 186 .calendar_spec = TAKE_PTR(c),
d00a52c7
ZJS
187 };
188
189 LIST_PREPEND(value, t->values, v);
190 }
191
192 return 1;
193};
194
d8a812d1
WC
195static int bus_timer_set_transient_property(
196 Timer *t,
197 const char *name,
198 sd_bus_message *message,
2e59b241 199 UnitWriteFlags flags,
d8a812d1
WC
200 sd_bus_error *error) {
201
3e3c5a45 202 Unit *u = UNIT(t);
d8a812d1
WC
203 int r;
204
205 assert(t);
206 assert(name);
207 assert(message);
208
2e59b241
LP
209 flags |= UNIT_PRIVATE;
210
3e3c5a45
YW
211 if (streq(name, "AccuracyUSec"))
212 return bus_set_transient_usec(u, name, &t->accuracy_usec, message, flags, error);
213
214 if (streq(name, "AccuracySec")) {
215 log_notice("Client is using obsolete AccuracySec= transient property, please use AccuracyUSec= instead.");
216 return bus_set_transient_usec(u, "AccuracyUSec", &t->accuracy_usec, message, flags, error);
217 }
218
219 if (streq(name, "RandomizedDelayUSec"))
9a0749c8
AV
220 return bus_set_transient_usec(u, name, &t->random_delay_usec, message, flags, error);
221
222 if (streq(name, "RandomizedOffsetUSec"))
223 return bus_set_transient_usec(u, name, &t->random_offset_usec, message, flags, error);
3e3c5a45 224
acf24a1a
KG
225 if (streq(name, "FixedRandomDelay"))
226 return bus_set_transient_bool(u, name, &t->fixed_random_delay, message, flags, error);
227
3e3c5a45
YW
228 if (streq(name, "WakeSystem"))
229 return bus_set_transient_bool(u, name, &t->wake_system, message, flags, error);
230
231 if (streq(name, "Persistent"))
232 return bus_set_transient_bool(u, name, &t->persistent, message, flags, error);
233
234 if (streq(name, "RemainAfterElapse"))
235 return bus_set_transient_bool(u, name, &t->remain_after_elapse, message, flags, error);
236
efebb613
LP
237 if (streq(name, "OnTimezoneChange"))
238 return bus_set_transient_bool(u, name, &t->on_timezone_change, message, flags, error);
239
240 if (streq(name, "OnClockChange"))
241 return bus_set_transient_bool(u, name, &t->on_clock_change, message, flags, error);
242
cc0ab8c8
AS
243 if (streq(name, "DeferReactivation"))
244 return bus_set_transient_bool(u, name, &t->defer_reactivation, message, flags, error);
245
3e3c5a45
YW
246 if (streq(name, "TimersMonotonic")) {
247 const char *base_name;
cd87f634 248 usec_t usec;
3e3c5a45
YW
249 bool empty = true;
250
251 r = sd_bus_message_enter_container(message, 'a', "(st)");
252 if (r < 0)
253 return r;
254
255 while ((r = sd_bus_message_read(message, "(st)", &base_name, &usec)) > 0) {
256 TimerBase b;
257
258 b = timer_base_from_string(base_name);
259 if (b < 0 || b == TIMER_CALENDAR)
cd87f634
ZJS
260 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
261 "Invalid timer base: %s", base_name);
3e3c5a45 262
cd87f634
ZJS
263 r = timer_add_one_monotonic_spec(t, name, b, flags, usec, error);
264 if (r < 0)
265 return r;
3e3c5a45
YW
266
267 empty = false;
268 }
269 if (r < 0)
270 return r;
271
272 r = sd_bus_message_exit_container(message);
273 if (r < 0)
274 return r;
275
276 if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) {
277 timer_free_values(t);
278 unit_write_setting(u, flags, name, "OnActiveSec=");
279 }
280
281 return 1;
282
283 } else if (streq(name, "TimersCalendar")) {
284 const char *base_name, *str;
285 bool empty = true;
286
287 r = sd_bus_message_enter_container(message, 'a', "(ss)");
288 if (r < 0)
289 return r;
290
291 while ((r = sd_bus_message_read(message, "(ss)", &base_name, &str)) > 0) {
3e3c5a45
YW
292 TimerBase b;
293
294 b = timer_base_from_string(base_name);
295 if (b != TIMER_CALENDAR)
d00a52c7
ZJS
296 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
297 "Invalid timer base: %s", base_name);
3e3c5a45 298
d00a52c7 299 r = timer_add_one_calendar_spec(t, name, b, flags, str, error);
3e3c5a45
YW
300 if (r < 0)
301 return r;
302
3e3c5a45
YW
303 empty = false;
304 }
305 if (r < 0)
306 return r;
307
308 r = sd_bus_message_exit_container(message);
309 if (r < 0)
310 return r;
311
312 if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) {
313 timer_free_values(t);
314 unit_write_setting(u, flags, name, "OnCalendar=");
315 }
316
317 return 1;
318
319 } else if (STR_IN_SET(name,
d8a812d1
WC
320 "OnActiveSec",
321 "OnBootSec",
322 "OnStartupSec",
323 "OnUnitActiveSec",
324 "OnUnitInactiveSec")) {
325
cd87f634
ZJS
326 TimerBase b;
327 usec_t usec;
3e3c5a45
YW
328
329 log_notice("Client is using obsolete %s= transient property, please use TimersMonotonic= instead.", name);
d8a812d1
WC
330
331 b = timer_base_from_string(name);
332 if (b < 0)
170d4026 333 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown timer base %s", name);
d8a812d1 334
3e3c5a45 335 r = sd_bus_message_read(message, "t", &usec);
d8a812d1
WC
336 if (r < 0)
337 return r;
338
cd87f634 339 return timer_add_one_monotonic_spec(t, name, b, flags, usec, error);
d8a812d1
WC
340
341 } else if (streq(name, "OnCalendar")) {
342
d8a812d1
WC
343 const char *str;
344
3e3c5a45
YW
345 log_notice("Client is using obsolete %s= transient property, please use TimersCalendar= instead.", name);
346
d8a812d1
WC
347 r = sd_bus_message_read(message, "s", &str);
348 if (r < 0)
349 return r;
350
d00a52c7 351 return timer_add_one_calendar_spec(t, name, TIMER_CALENDAR, flags, str, error);
d8a812d1
WC
352 }
353
354 return 0;
355}
356
357int bus_timer_set_property(
358 Unit *u,
359 const char *name,
360 sd_bus_message *message,
2e59b241 361 UnitWriteFlags mode,
d8a812d1
WC
362 sd_bus_error *error) {
363
364 Timer *t = TIMER(u);
d8a812d1
WC
365
366 assert(t);
367 assert(name);
368 assert(message);
369
2e59b241
LP
370 if (u->transient && u->load_state == UNIT_STUB)
371 return bus_timer_set_transient_property(t, name, message, mode, error);
d8a812d1
WC
372
373 return 0;
374}