Bug Summary

File:build-scan/../src/timedate/timedated.c
Warning:line 294, column 9
Potential leak of memory pointed to by 'w'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name timedated.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I systemd-timedated.p -I . -I .. -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/timedate/timedated.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno(*__errno_location ()).h>
4#include <string.h>
5#include <unistd.h>
6
7#include "sd-bus.h"
8#include "sd-event.h"
9#include "sd-messages.h"
10
11#include "alloc-util.h"
12#include "bus-common-errors.h"
13#include "bus-error.h"
14#include "bus-util.h"
15#include "clock-util.h"
16#include "def.h"
17#include "fileio-label.h"
18#include "fs-util.h"
19#include "hashmap.h"
20#include "list.h"
21#include "path-util.h"
22#include "selinux-util.h"
23#include "string-util.h"
24#include "strv.h"
25#include "unit-def.h"
26#include "unit-name.h"
27#include "user-util.h"
28#include "util.h"
29
30#define NULL_ADJTIME_UTC"0.0 0 0\n0\nUTC\n" "0.0 0 0\n0\nUTC\n"
31#define NULL_ADJTIME_LOCAL"0.0 0 0\n0\nLOCAL\n" "0.0 0 0\n0\nLOCAL\n"
32
33typedef struct UnitStatusInfo {
34 char *name;
35 char *load_state;
36 char *unit_file_state;
37 char *active_state;
38
39 LIST_FIELDS(struct UnitStatusInfo, units)struct UnitStatusInfo *units_next, *units_prev;
40} UnitStatusInfo;
41
42typedef struct Context {
43 char *zone;
44 bool_Bool local_rtc;
45 Hashmap *polkit_registry;
46
47 LIST_HEAD(UnitStatusInfo, units)UnitStatusInfo *units;
48} Context;
49
50static void unit_status_info_clear(UnitStatusInfo *p) {
51 assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p"), "../src/timedate/timedated.c", 51,
__PRETTY_FUNCTION__); } while (0)
;
52
53 p->load_state = mfree(p->load_state);
54 p->unit_file_state = mfree(p->unit_file_state);
55 p->active_state = mfree(p->active_state);
56}
57
58static void unit_status_info_free(UnitStatusInfo *p) {
59 assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p"), "../src/timedate/timedated.c", 59,
__PRETTY_FUNCTION__); } while (0)
;
60
61 unit_status_info_clear(p);
62 free(p->name);
63 free(p);
64}
65
66static void context_free(Context *c) {
67 UnitStatusInfo *p;
68
69 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 69,
__PRETTY_FUNCTION__); } while (0)
;
70
71 free(c->zone);
72 bus_verify_polkit_async_registry_free(c->polkit_registry);
73
74 while ((p = c->units)) {
75 LIST_REMOVE(units, c->units, p)do { typeof(*(c->units)) **_head = &(c->units), *_item
= (p); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_item"), "../src/timedate/timedated.c",
75, __PRETTY_FUNCTION__); } while (0); if (_item->units_next
) _item->units_next->units_prev = _item->units_prev;
if (_item->units_prev) _item->units_prev->units_next
= _item->units_next; else { do { if ((__builtin_expect(!!
(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/timedate/timedated.c", 75, __PRETTY_FUNCTION__
); } while (0); *_head = _item->units_next; } _item->units_next
= _item->units_prev = ((void*)0); } while (0)
;
76 unit_status_info_free(p);
77 }
78}
79
80static int context_add_ntp_service(Context *c, const char *s) {
81 UnitStatusInfo *u;
82
83 if (!unit_name_is_valid(s, UNIT_NAME_PLAIN))
84 return -EINVAL22;
85
86 /* Do not add this if it is already listed */
87 LIST_FOREACH(units, u, c->units)for ((u) = (c->units); (u); (u) = (u)->units_next)
88 if (streq(u->name, s)(strcmp((u->name),(s)) == 0))
89 return 0;
90
91 u = new0(UnitStatusInfo, 1)((UnitStatusInfo*) calloc((1), sizeof(UnitStatusInfo)));
92 if (!u)
93 return -ENOMEM12;
94
95 u->name = strdup(s);
96 if (!u->name) {
97 free(u);
98 return -ENOMEM12;
99 }
100
101 LIST_APPEND(units, c->units, u)do { typeof(*(c->units)) *_tail; do { typeof(*(c->units
)) *_item = (c->units); if (!_item) (_tail) = ((void*)0); else
{ while (_item->units_next) _item = _item->units_next;
(_tail) = _item; } } while (0); do { typeof(*(c->units)) *
*_head = &(c->units), *_a = (_tail), *_b = (u); do { if
((__builtin_expect(!!(!(_b)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("_b"), "../src/timedate/timedated.c", 101, __PRETTY_FUNCTION__
); } while (0); if (!_a) { if ((_b->units_next = *_head)) _b
->units_next->units_prev = _b; _b->units_prev = ((void
*)0); *_head = _b; } else { if ((_b->units_next = _a->units_next
)) _b->units_next->units_prev = _b; _b->units_prev =
_a; _a->units_next = _b; } } while (0); } while (0)
;
102
103 return 0;
104}
105
106static int context_parse_ntp_services(Context *c) {
107 const char *env, *p;
108 int r;
109
110 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 110
, __PRETTY_FUNCTION__); } while (0)
;
111
112 env = getenv("SYSTEMD_TIMEDATED_NTP_SERVICES");
113 if (!env) {
114 r = context_add_ntp_service(c, "systemd-timesyncd.service");
115 if (r < 0)
116 log_warning_errno(r, "Failed to add NTP service \"systemd-timesyncd.service\", ignoring: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 116, __func__, "Failed to add NTP service \"systemd-timesyncd.service\", ignoring: %m"
) : -abs(_e); })
;
117
118 return 0;
119 }
120
121 for (p = env;;) {
122 _cleanup_free___attribute__((cleanup(freep))) char *word = NULL((void*)0);
123
124 r = extract_first_word(&p, &word, ":", 0);
125 if (r == 0)
126 break;
127 if (r == -ENOMEM12)
128 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/timedate/timedated.c"
, 128, __func__)
;
129 if (r < 0) {
130 log_error("Invalid syntax, ignoring: %s", env)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 130, __func__, "Invalid syntax, ignoring: %s"
, env) : -abs(_e); })
;
131 break;
132 }
133
134 r = context_add_ntp_service(c, word);
135 if (r < 0)
136 log_warning_errno(r, "Failed to add NTP service \"%s\", ignoring: %m", word)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 136, __func__, "Failed to add NTP service \"%s\", ignoring: %m"
, word) : -abs(_e); })
;
137 }
138
139 return 0;
140}
141
142static int context_ntp_service_is_active(Context *c) {
143 UnitStatusInfo *info;
144 int count = 0;
145
146 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 146
, __PRETTY_FUNCTION__); } while (0)
;
147
148 /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
149
150 LIST_FOREACH(units, info, c->units)for ((info) = (c->units); (info); (info) = (info)->units_next
)
151 count += streq_ptr(info->active_state, "active");
152
153 return count;
154}
155
156static int context_ntp_service_is_enabled(Context *c) {
157 UnitStatusInfo *info;
158 int count = 0;
159
160 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 160
, __PRETTY_FUNCTION__); } while (0)
;
161
162 /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
163
164 LIST_FOREACH(units, info, c->units)for ((info) = (c->units); (info); (info) = (info)->units_next
)
165 count += STRPTR_IN_SET(info->unit_file_state, "enabled", "enabled-runtime")({ const char* _x = (info->unit_file_state); _x &&
(!!strv_find((((char**) ((const char*[]) { "enabled", "enabled-runtime"
, ((void*)0) }))), (_x))); })
;
166
167 return count;
168}
169
170static int context_ntp_service_exists(Context *c) {
171 UnitStatusInfo *info;
172 int count = 0;
173
174 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 174
, __PRETTY_FUNCTION__); } while (0)
;
175
176 /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
177
178 LIST_FOREACH(units, info, c->units)for ((info) = (c->units); (info); (info) = (info)->units_next
)
179 count += streq_ptr(info->load_state, "loaded");
180
181 return count;
182}
183
184static int context_read_data(Context *c) {
185 _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0);
186 int r;
187
188 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 188
, __PRETTY_FUNCTION__); } while (0)
;
189
190 r = get_timezone(&t);
191 if (r == -EINVAL22)
192 log_warning_errno(r, "/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/.")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 192, __func__, "/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/."
) : -abs(_e); })
;
193 else if (r < 0)
194 log_warning_errno(r, "Failed to get target of /etc/localtime: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 194, __func__, "Failed to get target of /etc/localtime: %m"
) : -abs(_e); })
;
195
196 free_and_replace(c->zone, t)({ free(c->zone); (c->zone) = (t); (t) = ((void*)0); 0;
})
;
197
198 c->local_rtc = clock_is_localtime(NULL((void*)0)) > 0;
199
200 return 0;
201}
202
203static int context_write_data_timezone(Context *c) {
204 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
205 int r = 0;
206
207 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 207
, __PRETTY_FUNCTION__); } while (0)
;
208
209 if (isempty(c->zone)) {
210 if (unlink("/etc/localtime") < 0 && errno(*__errno_location ()) != ENOENT2)
211 r = -errno(*__errno_location ());
212
213 return r;
214 }
215
216 p = strappend("../usr/share/zoneinfo/", c->zone);
217 if (!p)
218 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/timedate/timedated.c"
, 218, __func__)
;
219
220 r = symlink_atomic(p, "/etc/localtime");
221 if (r < 0)
222 return r;
223
224 return 0;
225}
226
227static int context_write_data_local_rtc(Context *c) {
228 int r;
229 _cleanup_free___attribute__((cleanup(freep))) char *s = NULL((void*)0), *w = NULL((void*)0);
230
231 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 231
, __PRETTY_FUNCTION__); } while (0)
;
16
Taking false branch
17
Loop condition is false. Exiting loop
232
233 r = read_full_file("/etc/adjtime", &s, NULL((void*)0));
234 if (r < 0) {
18
Assuming 'r' is < 0
19
Taking true branch
235 if (r != -ENOENT2)
20
Assuming the condition is false
21
Taking false branch
236 return r;
237
238 if (!c->local_rtc)
22
Assuming field 'local_rtc' is true
23
Taking false branch
239 return 0;
240
241 w = strdup(NULL_ADJTIME_LOCAL"0.0 0 0\n0\nLOCAL\n");
24
Memory is allocated
242 if (!w)
25
Assuming 'w' is non-null
26
Taking false branch
243 return -ENOMEM12;
244 } else {
245 char *p;
246 const char *e = "\n"; /* default if there is less than 3 lines */
247 const char *prepend = "";
248 size_t a, b;
249
250 p = strchrnul(s, '\n');
251 if (*p == '\0')
252 /* only one line, no \n terminator */
253 prepend = "\n0\n";
254 else if (p[1] == '\0') {
255 /* only one line, with \n terminator */
256 ++p;
257 prepend = "0\n";
258 } else {
259 p = strchr(p+1, '\n');
260 if (!p) {
261 /* only two lines, no \n terminator */
262 prepend = "\n";
263 p = s + strlen(s);
264 } else {
265 char *end;
266 /* third line might have a \n terminator or not */
267 p++;
268 end = strchr(p, '\n');
269 /* if we actually have a fourth line, use that as suffix "e", otherwise the default \n */
270 if (end)
271 e = end;
272 }
273 }
274
275 a = p - s;
276 b = strlen(e);
277
278 w = new(char, a + (c->local_rtc ? 5 : 3) + strlen(prepend) + b + 1)((char*) malloc_multiply(sizeof(char), (a + (c->local_rtc ?
5 : 3) + strlen(prepend) + b + 1)))
;
279 if (!w)
280 return -ENOMEM12;
281
282 *(char*) mempcpy(stpcpy(stpcpy(mempcpy(w, s, a), prepend), c->local_rtc ? "LOCAL" : "UTC"), e, b) = 0;
283
284 if (streq(w, NULL_ADJTIME_UTC)(strcmp((w),("0.0 0 0\n0\nUTC\n")) == 0)) {
285 if (unlink("/etc/adjtime") < 0)
286 if (errno(*__errno_location ()) != ENOENT2)
287 return -errno(*__errno_location ());
288
289 return 0;
290 }
291 }
292
293 mac_selinux_init();
294 return write_string_file_atomic_label("/etc/adjtime", w);
27
Potential leak of memory pointed to by 'w'
295}
296
297static int context_update_ntp_status(Context *c, sd_bus *bus, sd_bus_message *m) {
298 static const struct bus_properties_map map[] = {
299 { "LoadState", "s", NULL((void*)0), offsetof(UnitStatusInfo, load_state)__builtin_offsetof(UnitStatusInfo, load_state) },
300 { "ActiveState", "s", NULL((void*)0), offsetof(UnitStatusInfo, active_state)__builtin_offsetof(UnitStatusInfo, active_state) },
301 { "UnitFileState", "s", NULL((void*)0), offsetof(UnitStatusInfo, unit_file_state)__builtin_offsetof(UnitStatusInfo, unit_file_state) },
302 {}
303 };
304 static sd_bus_message *_m = NULL((void*)0);
305 UnitStatusInfo *u;
306 int r;
307
308 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 308
, __PRETTY_FUNCTION__); } while (0)
;
309 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/timedate/timedated.c", 309
, __PRETTY_FUNCTION__); } while (0)
;
310
311 /* Suppress multiple call of context_update_ntp_status() within single DBus transaction. */
312 if (m && m == _m)
313 return 0;
314
315 _m = m;
316
317 LIST_FOREACH(units, u, c->units)for ((u) = (c->units); (u); (u) = (u)->units_next) {
318 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
319 _cleanup_free___attribute__((cleanup(freep))) char *path = NULL((void*)0);
320
321 unit_status_info_clear(u);
322
323 path = unit_dbus_path_from_name(u->name);
324 if (!path)
325 return -ENOMEM12;
326
327 r = bus_map_all_properties(
328 bus,
329 "org.freedesktop.systemd1",
330 path,
331 map,
332 BUS_MAP_STRDUP,
333 &error,
334 NULL((void*)0),
335 u);
336 if (r < 0)
337 return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r))({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 337, __func__, "Failed to get properties: %s"
, bus_error_message(&error, r)) : -abs(_e); })
;
338 }
339
340 return 0;
341}
342
343static int unit_start_or_stop(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool_Bool start) {
344 int r;
345
346 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/timedate/timedated.c", 346
, __PRETTY_FUNCTION__); } while (0)
;
347 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/timedate/timedated.c", 347
, __PRETTY_FUNCTION__); } while (0)
;
348 assert(error)do { if ((__builtin_expect(!!(!(error)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("error"), "../src/timedate/timedated.c",
348, __PRETTY_FUNCTION__); } while (0)
;
349
350 /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
351
352 if (streq(u->active_state, "active")(strcmp((u->active_state),("active")) == 0) == start)
353 return 0;
354
355 r = sd_bus_call_method(
356 bus,
357 "org.freedesktop.systemd1",
358 "/org/freedesktop/systemd1",
359 "org.freedesktop.systemd1.Manager",
360 start ? "StartUnit" : "StopUnit",
361 error,
362 NULL((void*)0),
363 "ss",
364 u->name,
365 "replace");
366 if (r < 0)
367 return r;
368
369 return 0;
370}
371
372static int unit_enable_or_disable(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool_Bool enable) {
373 int r;
374
375 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/timedate/timedated.c", 375
, __PRETTY_FUNCTION__); } while (0)
;
376 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/timedate/timedated.c", 376
, __PRETTY_FUNCTION__); } while (0)
;
377 assert(error)do { if ((__builtin_expect(!!(!(error)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("error"), "../src/timedate/timedated.c",
377, __PRETTY_FUNCTION__); } while (0)
;
378
379 /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
380
381 if (streq(u->unit_file_state, "enabled")(strcmp((u->unit_file_state),("enabled")) == 0) == enable)
382 return 0;
383
384 if (enable)
385 r = sd_bus_call_method(
386 bus,
387 "org.freedesktop.systemd1",
388 "/org/freedesktop/systemd1",
389 "org.freedesktop.systemd1.Manager",
390 "EnableUnitFiles",
391 error,
392 NULL((void*)0),
393 "asbb", 1,
394 u->name,
395 false0, true1);
396 else
397 r = sd_bus_call_method(
398 bus,
399 "org.freedesktop.systemd1",
400 "/org/freedesktop/systemd1",
401 "org.freedesktop.systemd1.Manager",
402 "DisableUnitFiles",
403 error,
404 NULL((void*)0),
405 "asb", 1,
406 u->name,
407 false0);
408 if (r < 0)
409 return r;
410
411 r = sd_bus_call_method(
412 bus,
413 "org.freedesktop.systemd1",
414 "/org/freedesktop/systemd1",
415 "org.freedesktop.systemd1.Manager",
416 "Reload",
417 error,
418 NULL((void*)0),
419 NULL((void*)0));
420 if (r < 0)
421 return r;
422 return 0;
423}
424
425static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_time, "t", now(CLOCK_REALTIME))int property_get_time(sd_bus *bus, const char *path, const char
*interface, const char *property, sd_bus_message *reply, void
*userdata, sd_bus_error *error) { do { if ((__builtin_expect
(!!(!(bus)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, (
"bus"), "../src/timedate/timedated.c", 425, __PRETTY_FUNCTION__
); } while (0); do { if ((__builtin_expect(!!(!(reply)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("reply"), "../src/timedate/timedated.c",
425, __PRETTY_FUNCTION__); } while (0); return sd_bus_message_append
(reply, "t", now(0)); }
;
426static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_ntp_sync, "b", ntp_synced())int property_get_ntp_sync(sd_bus *bus, const char *path, const
char *interface, const char *property, sd_bus_message *reply
, void *userdata, sd_bus_error *error) { do { if ((__builtin_expect
(!!(!(bus)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, (
"bus"), "../src/timedate/timedated.c", 426, __PRETTY_FUNCTION__
); } while (0); do { if ((__builtin_expect(!!(!(reply)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("reply"), "../src/timedate/timedated.c",
426, __PRETTY_FUNCTION__); } while (0); return sd_bus_message_append
(reply, "b", ntp_synced()); }
;
427
428static int property_get_rtc_time(
429 sd_bus *bus,
430 const char *path,
431 const char *interface,
432 const char *property,
433 sd_bus_message *reply,
434 void *userdata,
435 sd_bus_error *error) {
436
437 struct tm tm;
438 usec_t t;
439 int r;
440
441 zero(tm)(({ size_t _l_ = (sizeof(tm)); void *_x_ = (&(tm)); _l_ ==
0 ? _x_ : memset(_x_, 0, _l_); }))
;
442 r = clock_get_hwclock(&tm);
443 if (r == -EBUSY16) {
444 log_warning("/dev/rtc is busy. Is somebody keeping it open continuously? That's not a good idea... Returning a bogus RTC timestamp.")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 444, __func__, "/dev/rtc is busy. Is somebody keeping it open continuously? That's not a good idea... Returning a bogus RTC timestamp."
) : -abs(_e); })
;
445 t = 0;
446 } else if (r == -ENOENT2) {
447 log_debug("/dev/rtc not found.")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 447, __func__, "/dev/rtc not found."
) : -abs(_e); })
;
448 t = 0; /* no RTC found */
449 } else if (r < 0)
450 return sd_bus_error_set_errnof(error, r, "Failed to read RTC: %m");
451 else
452 t = (usec_t) timegm(&tm) * USEC_PER_SEC((usec_t) 1000000ULL);
453
454 return sd_bus_message_append(reply, "t", t);
455}
456
457static int property_get_can_ntp(
458 sd_bus *bus,
459 const char *path,
460 const char *interface,
461 const char *property,
462 sd_bus_message *reply,
463 void *userdata,
464 sd_bus_error *error) {
465
466 Context *c = userdata;
467 int r;
468
469 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 469
, __PRETTY_FUNCTION__); } while (0)
;
470 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/timedate/timedated.c", 470
, __PRETTY_FUNCTION__); } while (0)
;
471 assert(property)do { if ((__builtin_expect(!!(!(property)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("property"), "../src/timedate/timedated.c"
, 471, __PRETTY_FUNCTION__); } while (0)
;
472 assert(reply)do { if ((__builtin_expect(!!(!(reply)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("reply"), "../src/timedate/timedated.c",
472, __PRETTY_FUNCTION__); } while (0)
;
473 assert(error)do { if ((__builtin_expect(!!(!(error)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("error"), "../src/timedate/timedated.c",
473, __PRETTY_FUNCTION__); } while (0)
;
474
475 r = context_update_ntp_status(c, bus, reply);
476 if (r < 0)
477 return r;
478
479 return sd_bus_message_append(reply, "b", context_ntp_service_exists(c) > 0);
480}
481
482static int property_get_ntp(
483 sd_bus *bus,
484 const char *path,
485 const char *interface,
486 const char *property,
487 sd_bus_message *reply,
488 void *userdata,
489 sd_bus_error *error) {
490
491 Context *c = userdata;
492 int r;
493
494 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 494
, __PRETTY_FUNCTION__); } while (0)
;
495 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/timedate/timedated.c", 495
, __PRETTY_FUNCTION__); } while (0)
;
496 assert(property)do { if ((__builtin_expect(!!(!(property)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("property"), "../src/timedate/timedated.c"
, 496, __PRETTY_FUNCTION__); } while (0)
;
497 assert(reply)do { if ((__builtin_expect(!!(!(reply)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("reply"), "../src/timedate/timedated.c",
497, __PRETTY_FUNCTION__); } while (0)
;
498 assert(error)do { if ((__builtin_expect(!!(!(error)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("error"), "../src/timedate/timedated.c",
498, __PRETTY_FUNCTION__); } while (0)
;
499
500 r = context_update_ntp_status(c, bus, reply);
501 if (r < 0)
502 return r;
503
504 return sd_bus_message_append(reply, "b", context_ntp_service_is_active(c) > 0);
505}
506
507static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *error) {
508 Context *c = userdata;
509 int interactive, r;
510 const char *z;
511
512 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/timedate/timedated.c", 512
, __PRETTY_FUNCTION__); } while (0)
;
513 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 513
, __PRETTY_FUNCTION__); } while (0)
;
514
515 r = sd_bus_message_read(m, "sb", &z, &interactive);
516 if (r < 0)
517 return r;
518
519 if (!timezone_is_valid(z, LOG_DEBUG7))
520 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Invalid time zone '%s'", z);
521
522 if (streq_ptr(z, c->zone))
523 return sd_bus_reply_method_return(m, NULL((void*)0));
524
525 r = bus_verify_polkit_async(
526 m,
527 CAP_SYS_TIME25,
528 "org.freedesktop.timedate1.set-timezone",
529 NULL((void*)0),
530 interactive,
531 UID_INVALID((uid_t) -1),
532 &c->polkit_registry,
533 error);
534 if (r < 0)
535 return r;
536 if (r == 0)
537 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
538
539 r = free_and_strdup(&c->zone, z);
540 if (r < 0)
541 return r;
542
543 /* 1. Write new configuration file */
544 r = context_write_data_timezone(c);
545 if (r < 0) {
546 log_error_errno(r, "Failed to set time zone: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 546, __func__, "Failed to set time zone: %m"
) : -abs(_e); })
;
547 return sd_bus_error_set_errnof(error, r, "Failed to set time zone: %m");
548 }
549
550 /* 2. Make glibc notice the new timezone */
551 tzset();
552
553 /* 3. Tell the kernel our timezone */
554 r = clock_set_timezone(NULL((void*)0));
555 if (r < 0)
556 log_debug_errno(r, "Failed to tell kernel about timezone, ignoring: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 556, __func__, "Failed to tell kernel about timezone, ignoring: %m"
) : -abs(_e); })
;
557
558 if (c->local_rtc) {
559 struct timespec ts;
560 struct tm *tm;
561
562 /* 4. Sync RTC from system clock, with the new delta */
563 assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0)do { if ((__builtin_expect(!!(!(clock_gettime(0, &ts) == 0
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("clock_gettime(CLOCK_REALTIME, &ts) == 0"
), "../src/timedate/timedated.c", 563, __PRETTY_FUNCTION__); }
while (0)
;
564 assert_se(tm = localtime(&ts.tv_sec))do { if ((__builtin_expect(!!(!(tm = localtime(&ts.tv_sec
))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("tm = localtime(&ts.tv_sec)"
), "../src/timedate/timedated.c", 564, __PRETTY_FUNCTION__); }
while (0)
;
565
566 r = clock_set_hwclock(tm);
567 if (r < 0)
568 log_debug_errno(r, "Failed to sync time to hardware clock, ignoring: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 568, __func__, "Failed to sync time to hardware clock, ignoring: %m"
) : -abs(_e); })
;
569 }
570
571 log_struct(LOG_INFO,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/timedate/timedated.c", 576, __func__, "MESSAGE_ID="
"45" "f8" "2f" "4a" "ef" "7a" "4b" "bf" "94" "2c" "e8" "61" "d1"
"f2" "09" "90", "TIMEZONE=%s", c->zone, "TIMEZONE_SHORTNAME=%s"
, tzname[daylight], "DAYLIGHT=%i", daylight, "MESSAGE=" "Changed time zone to '%s' (%s)."
, c->zone, tzname[daylight], ((void*)0))
572 "MESSAGE_ID=" SD_MESSAGE_TIMEZONE_CHANGE_STR,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/timedate/timedated.c", 576, __func__, "MESSAGE_ID="
"45" "f8" "2f" "4a" "ef" "7a" "4b" "bf" "94" "2c" "e8" "61" "d1"
"f2" "09" "90", "TIMEZONE=%s", c->zone, "TIMEZONE_SHORTNAME=%s"
, tzname[daylight], "DAYLIGHT=%i", daylight, "MESSAGE=" "Changed time zone to '%s' (%s)."
, c->zone, tzname[daylight], ((void*)0))
573 "TIMEZONE=%s", c->zone,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/timedate/timedated.c", 576, __func__, "MESSAGE_ID="
"45" "f8" "2f" "4a" "ef" "7a" "4b" "bf" "94" "2c" "e8" "61" "d1"
"f2" "09" "90", "TIMEZONE=%s", c->zone, "TIMEZONE_SHORTNAME=%s"
, tzname[daylight], "DAYLIGHT=%i", daylight, "MESSAGE=" "Changed time zone to '%s' (%s)."
, c->zone, tzname[daylight], ((void*)0))
574 "TIMEZONE_SHORTNAME=%s", tzname[daylight],log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/timedate/timedated.c", 576, __func__, "MESSAGE_ID="
"45" "f8" "2f" "4a" "ef" "7a" "4b" "bf" "94" "2c" "e8" "61" "d1"
"f2" "09" "90", "TIMEZONE=%s", c->zone, "TIMEZONE_SHORTNAME=%s"
, tzname[daylight], "DAYLIGHT=%i", daylight, "MESSAGE=" "Changed time zone to '%s' (%s)."
, c->zone, tzname[daylight], ((void*)0))
575 "DAYLIGHT=%i", daylight,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/timedate/timedated.c", 576, __func__, "MESSAGE_ID="
"45" "f8" "2f" "4a" "ef" "7a" "4b" "bf" "94" "2c" "e8" "61" "d1"
"f2" "09" "90", "TIMEZONE=%s", c->zone, "TIMEZONE_SHORTNAME=%s"
, tzname[daylight], "DAYLIGHT=%i", daylight, "MESSAGE=" "Changed time zone to '%s' (%s)."
, c->zone, tzname[daylight], ((void*)0))
576 LOG_MESSAGE("Changed time zone to '%s' (%s).", c->zone, tzname[daylight]))log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/timedate/timedated.c", 576, __func__, "MESSAGE_ID="
"45" "f8" "2f" "4a" "ef" "7a" "4b" "bf" "94" "2c" "e8" "61" "d1"
"f2" "09" "90", "TIMEZONE=%s", c->zone, "TIMEZONE_SHORTNAME=%s"
, tzname[daylight], "DAYLIGHT=%i", daylight, "MESSAGE=" "Changed time zone to '%s' (%s)."
, c->zone, tzname[daylight], ((void*)0))
;
577
578 (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "Timezone", NULL((void*)0));
579
580 return sd_bus_reply_method_return(m, NULL((void*)0));
581}
582
583static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error *error) {
584 int lrtc, fix_system, interactive;
585 Context *c = userdata;
586 struct timespec ts;
587 int r;
588
589 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/timedate/timedated.c", 589
, __PRETTY_FUNCTION__); } while (0)
;
1
Assuming 'm' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
590 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 590
, __PRETTY_FUNCTION__); } while (0)
;
4
Assuming 'c' is non-null
5
Taking false branch
6
Loop condition is false. Exiting loop
591
592 r = sd_bus_message_read(m, "bbb", &lrtc, &fix_system, &interactive);
593 if (r < 0)
7
Assuming 'r' is >= 0
8
Taking false branch
594 return r;
595
596 if (lrtc == c->local_rtc)
9
Assuming 'lrtc' is not equal to field 'local_rtc'
10
Taking false branch
597 return sd_bus_reply_method_return(m, NULL((void*)0));
598
599 r = bus_verify_polkit_async(
600 m,
601 CAP_SYS_TIME25,
602 "org.freedesktop.timedate1.set-local-rtc",
603 NULL((void*)0),
604 interactive,
605 UID_INVALID((uid_t) -1),
606 &c->polkit_registry,
607 error);
608 if (r < 0)
11
Assuming 'r' is >= 0
12
Taking false branch
609 return r;
610 if (r == 0)
13
Assuming 'r' is not equal to 0
14
Taking false branch
611 return 1;
612
613 c->local_rtc = lrtc;
614
615 /* 1. Write new configuration file */
616 r = context_write_data_local_rtc(c);
15
Calling 'context_write_data_local_rtc'
617 if (r < 0) {
618 log_error_errno(r, "Failed to set RTC to local/UTC: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 618, __func__, "Failed to set RTC to local/UTC: %m"
) : -abs(_e); })
;
619 return sd_bus_error_set_errnof(error, r, "Failed to set RTC to local/UTC: %m");
620 }
621
622 /* 2. Tell the kernel our timezone */
623 r = clock_set_timezone(NULL((void*)0));
624 if (r < 0)
625 log_debug_errno(r, "Failed to tell kernel about timezone, ignoring: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 625, __func__, "Failed to tell kernel about timezone, ignoring: %m"
) : -abs(_e); })
;
626
627 /* 3. Synchronize clocks */
628 assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0)do { if ((__builtin_expect(!!(!(clock_gettime(0, &ts) == 0
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("clock_gettime(CLOCK_REALTIME, &ts) == 0"
), "../src/timedate/timedated.c", 628, __PRETTY_FUNCTION__); }
while (0)
;
629
630 if (fix_system) {
631 struct tm tm;
632
633 /* Sync system clock from RTC; first, initialize the timezone fields of struct tm. */
634 if (c->local_rtc)
635 tm = *localtime(&ts.tv_sec);
636 else
637 tm = *gmtime(&ts.tv_sec);
638
639 /* Override the main fields of struct tm, but not the timezone fields */
640 r = clock_get_hwclock(&tm);
641 if (r < 0)
642 log_debug_errno(r, "Failed to get hardware clock, ignoring: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 642, __func__, "Failed to get hardware clock, ignoring: %m"
) : -abs(_e); })
;
643 else {
644 /* And set the system clock with this */
645 if (c->local_rtc)
646 ts.tv_sec = mktime(&tm);
647 else
648 ts.tv_sec = timegm(&tm);
649
650 if (clock_settime(CLOCK_REALTIME0, &ts) < 0)
651 log_debug_errno(errno, "Failed to update system clock, ignoring: %m")({ int _level = ((7)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/timedate/timedated.c", 651, __func__
, "Failed to update system clock, ignoring: %m") : -abs(_e); }
)
;
652 }
653
654 } else {
655 struct tm *tm;
656
657 /* Sync RTC from system clock */
658 if (c->local_rtc)
659 tm = localtime(&ts.tv_sec);
660 else
661 tm = gmtime(&ts.tv_sec);
662
663 r = clock_set_hwclock(tm);
664 if (r < 0)
665 log_debug_errno(r, "Failed to sync time to hardware clock, ignoring: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 665, __func__, "Failed to sync time to hardware clock, ignoring: %m"
) : -abs(_e); })
;
666 }
667
668 log_info("RTC configured to %s time.", c->local_rtc ? "local" : "UTC")({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 668, __func__, "RTC configured to %s time."
, c->local_rtc ? "local" : "UTC") : -abs(_e); })
;
669
670 (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "LocalRTC", NULL((void*)0));
671
672 return sd_bus_reply_method_return(m, NULL((void*)0));
673}
674
675static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *error) {
676 sd_bus *bus = sd_bus_message_get_bus(m);
677 int relative, interactive, r;
678 Context *c = userdata;
679 int64_t utc;
680 struct timespec ts;
681 usec_t start;
682 struct tm* tm;
683
684 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/timedate/timedated.c", 684
, __PRETTY_FUNCTION__); } while (0)
;
685 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 685
, __PRETTY_FUNCTION__); } while (0)
;
686
687 r = context_update_ntp_status(c, bus, m);
688 if (r < 0)
689 return sd_bus_error_set_errnof(error, r, "Failed to update context: %m");
690
691 if (context_ntp_service_is_active(c) > 0)
692 return sd_bus_error_set(error, BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED"org.freedesktop.timedate1.AutomaticTimeSyncEnabled", "Automatic time synchronization is enabled");
693
694 /* this only gets used if dbus does not provide a timestamp */
695 start = now(CLOCK_MONOTONIC1);
696
697 r = sd_bus_message_read(m, "xbb", &utc, &relative, &interactive);
698 if (r < 0)
699 return r;
700
701 if (!relative && utc <= 0)
702 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Invalid absolute time");
703
704 if (relative && utc == 0)
705 return sd_bus_reply_method_return(m, NULL((void*)0));
706
707 if (relative) {
708 usec_t n, x;
709
710 n = now(CLOCK_REALTIME0);
711 x = n + utc;
712
713 if ((utc > 0 && x < n) ||
714 (utc < 0 && x > n))
715 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS"org.freedesktop.DBus.Error.InvalidArgs", "Time value overflow");
716
717 timespec_store(&ts, x);
718 } else
719 timespec_store(&ts, (usec_t) utc);
720
721 r = bus_verify_polkit_async(
722 m,
723 CAP_SYS_TIME25,
724 "org.freedesktop.timedate1.set-time",
725 NULL((void*)0),
726 interactive,
727 UID_INVALID((uid_t) -1),
728 &c->polkit_registry,
729 error);
730 if (r < 0)
731 return r;
732 if (r == 0)
733 return 1;
734
735 /* adjust ts for time spent in program */
736 r = sd_bus_message_get_monotonic_usec(m, &start);
737 /* when sd_bus_message_get_monotonic_usec() returns -ENODATA it does not modify &start */
738 if (r < 0 && r != -ENODATA61)
739 return r;
740
741 timespec_store(&ts, timespec_load(&ts) + (now(CLOCK_MONOTONIC1) - start));
742
743 /* Set system clock */
744 if (clock_settime(CLOCK_REALTIME0, &ts) < 0) {
745 log_error_errno(errno, "Failed to set local time: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/timedate/timedated.c", 745, __func__
, "Failed to set local time: %m") : -abs(_e); })
;
746 return sd_bus_error_set_errnof(error, errno(*__errno_location ()), "Failed to set local time: %m");
747 }
748
749 /* Sync down to RTC */
750 if (c->local_rtc)
751 tm = localtime(&ts.tv_sec);
752 else
753 tm = gmtime(&ts.tv_sec);
754
755 r = clock_set_hwclock(tm);
756 if (r < 0)
757 log_debug_errno(r, "Failed to update hardware clock, ignoring: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 757, __func__, "Failed to update hardware clock, ignoring: %m"
) : -abs(_e); })
;
758
759 log_struct(LOG_INFO,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/timedate/timedated.c", 762, __func__, "MESSAGE_ID="
"c7" "a7" "87" "07" "9b" "35" "4e" "aa" "a9" "e7" "7b" "37" "18"
"93" "cd" "27", "REALTIME=""%" "l" "u", timespec_load(&ts
), "MESSAGE=" "Changed local time to %s", ctime(&ts.tv_sec
), ((void*)0))
760 "MESSAGE_ID=" SD_MESSAGE_TIME_CHANGE_STR,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/timedate/timedated.c", 762, __func__, "MESSAGE_ID="
"c7" "a7" "87" "07" "9b" "35" "4e" "aa" "a9" "e7" "7b" "37" "18"
"93" "cd" "27", "REALTIME=""%" "l" "u", timespec_load(&ts
), "MESSAGE=" "Changed local time to %s", ctime(&ts.tv_sec
), ((void*)0))
761 "REALTIME="USEC_FMT, timespec_load(&ts),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/timedate/timedated.c", 762, __func__, "MESSAGE_ID="
"c7" "a7" "87" "07" "9b" "35" "4e" "aa" "a9" "e7" "7b" "37" "18"
"93" "cd" "27", "REALTIME=""%" "l" "u", timespec_load(&ts
), "MESSAGE=" "Changed local time to %s", ctime(&ts.tv_sec
), ((void*)0))
762 LOG_MESSAGE("Changed local time to %s", ctime(&ts.tv_sec)))log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0
, "../src/timedate/timedated.c", 762, __func__, "MESSAGE_ID="
"c7" "a7" "87" "07" "9b" "35" "4e" "aa" "a9" "e7" "7b" "37" "18"
"93" "cd" "27", "REALTIME=""%" "l" "u", timespec_load(&ts
), "MESSAGE=" "Changed local time to %s", ctime(&ts.tv_sec
), ((void*)0))
;
763
764 return sd_bus_reply_method_return(m, NULL((void*)0));
765}
766
767static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error) {
768 sd_bus *bus = sd_bus_message_get_bus(m);
769 Context *c = userdata;
770 UnitStatusInfo *u;
771 int enable, interactive, q, r;
772
773 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/timedate/timedated.c", 773
, __PRETTY_FUNCTION__); } while (0)
;
774 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/timedate/timedated.c", 774
, __PRETTY_FUNCTION__); } while (0)
;
775 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 775
, __PRETTY_FUNCTION__); } while (0)
;
776
777 r = sd_bus_message_read(m, "bb", &enable, &interactive);
778 if (r < 0)
779 return r;
780
781 r = context_update_ntp_status(c, bus, m);
782 if (r < 0)
783 return r;
784
785 if (context_ntp_service_exists(c) <= 0)
786 return sd_bus_error_set(error, BUS_ERROR_NO_NTP_SUPPORT"org.freedesktop.timedate1.NoNTPSupport", "NTP not supported");
787
788 r = bus_verify_polkit_async(
789 m,
790 CAP_SYS_TIME25,
791 "org.freedesktop.timedate1.set-ntp",
792 NULL((void*)0),
793 interactive,
794 UID_INVALID((uid_t) -1),
795 &c->polkit_registry,
796 error);
797 if (r < 0)
798 return r;
799 if (r == 0)
800 return 1;
801
802 if (!enable)
803 LIST_FOREACH(units, u, c->units)for ((u) = (c->units); (u); (u) = (u)->units_next) {
804 if (!streq(u->load_state, "loaded")(strcmp((u->load_state),("loaded")) == 0))
805 continue;
806
807 q = unit_enable_or_disable(u, bus, error, enable);
808 if (q < 0)
809 r = q;
810
811 q = unit_start_or_stop(u, bus, error, enable);
812 if (q < 0)
813 r = q;
814 }
815
816 else if (context_ntp_service_is_enabled(c) <= 0)
817 LIST_FOREACH(units, u, c->units)for ((u) = (c->units); (u); (u) = (u)->units_next) {
818 if (!streq(u->load_state, "loaded")(strcmp((u->load_state),("loaded")) == 0))
819 continue;
820
821 r = unit_enable_or_disable(u, bus, error, enable);
822 if (r < 0)
823 continue;
824
825 r = unit_start_or_stop(u, bus, error, enable);
826 break;
827 }
828
829 else if (context_ntp_service_is_active(c) <= 0)
830 LIST_FOREACH(units, u, c->units)for ((u) = (c->units); (u); (u) = (u)->units_next) {
831 if (!streq(u->load_state, "loaded")(strcmp((u->load_state),("loaded")) == 0) ||
832 !streq(u->unit_file_state, "enabled")(strcmp((u->unit_file_state),("enabled")) == 0))
833 continue;
834
835 r = unit_start_or_stop(u, bus, error, enable);
836 break;
837 }
838
839 if (r < 0)
840 return r;
841
842 log_info("Set NTP to %sd", enable_disable(enable))({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 842, __func__, "Set NTP to %sd"
, enable_disable(enable)) : -abs(_e); })
;
843
844 (void) sd_bus_emit_properties_changed(bus, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL((void*)0));
845
846 return sd_bus_reply_method_return(m, NULL((void*)0));
847}
848
849static const sd_bus_vtable timedate_vtable[] = {
850 SD_BUS_VTABLE_START(0){ .type = _SD_BUS_VTABLE_START, .flags = 0, .x = { .start = {
.element_size = sizeof(sd_bus_vtable) }, }, }
,
851 SD_BUS_PROPERTY("Timezone", "s", NULL, offsetof(Context, zone), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE){ .type = _SD_BUS_VTABLE_PROPERTY, .flags = SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
, .x = { .property = { .member = "Timezone", .signature = "s"
, .get = ((void*)0), .set = ((void*)0), .offset = __builtin_offsetof
(Context, zone), }, }, }
,
852 SD_BUS_PROPERTY("LocalRTC", "b", bus_property_get_bool, offsetof(Context, local_rtc), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE){ .type = _SD_BUS_VTABLE_PROPERTY, .flags = SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
, .x = { .property = { .member = "LocalRTC", .signature = "b"
, .get = bus_property_get_bool, .set = ((void*)0), .offset = __builtin_offsetof
(Context, local_rtc), }, }, }
,
853 SD_BUS_PROPERTY("CanNTP", "b", property_get_can_ntp, 0, 0){ .type = _SD_BUS_VTABLE_PROPERTY, .flags = 0, .x = { .property
= { .member = "CanNTP", .signature = "b", .get = property_get_can_ntp
, .set = ((void*)0), .offset = 0, }, }, }
,
854 SD_BUS_PROPERTY("NTP", "b", property_get_ntp, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE){ .type = _SD_BUS_VTABLE_PROPERTY, .flags = SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
, .x = { .property = { .member = "NTP", .signature = "b", .get
= property_get_ntp, .set = ((void*)0), .offset = 0, }, }, }
,
855 SD_BUS_PROPERTY("NTPSynchronized", "b", property_get_ntp_sync, 0, 0){ .type = _SD_BUS_VTABLE_PROPERTY, .flags = 0, .x = { .property
= { .member = "NTPSynchronized", .signature = "b", .get = property_get_ntp_sync
, .set = ((void*)0), .offset = 0, }, }, }
,
856 SD_BUS_PROPERTY("TimeUSec", "t", property_get_time, 0, 0){ .type = _SD_BUS_VTABLE_PROPERTY, .flags = 0, .x = { .property
= { .member = "TimeUSec", .signature = "t", .get = property_get_time
, .set = ((void*)0), .offset = 0, }, }, }
,
857 SD_BUS_PROPERTY("RTCTimeUSec", "t", property_get_rtc_time, 0, 0){ .type = _SD_BUS_VTABLE_PROPERTY, .flags = 0, .x = { .property
= { .member = "RTCTimeUSec", .signature = "t", .get = property_get_rtc_time
, .set = ((void*)0), .offset = 0, }, }, }
,
858 SD_BUS_METHOD("SetTime", "xbb", NULL, method_set_time, SD_BUS_VTABLE_UNPRIVILEGED){ .type = _SD_BUS_VTABLE_METHOD, .flags = SD_BUS_VTABLE_UNPRIVILEGED
, .x = { .method = { .member = "SetTime", .signature = "xbb",
.result = ((void*)0), .handler = method_set_time, .offset = 0
, }, }, }
,
859 SD_BUS_METHOD("SetTimezone", "sb", NULL, method_set_timezone, SD_BUS_VTABLE_UNPRIVILEGED){ .type = _SD_BUS_VTABLE_METHOD, .flags = SD_BUS_VTABLE_UNPRIVILEGED
, .x = { .method = { .member = "SetTimezone", .signature = "sb"
, .result = ((void*)0), .handler = method_set_timezone, .offset
= 0, }, }, }
,
860 SD_BUS_METHOD("SetLocalRTC", "bbb", NULL, method_set_local_rtc, SD_BUS_VTABLE_UNPRIVILEGED){ .type = _SD_BUS_VTABLE_METHOD, .flags = SD_BUS_VTABLE_UNPRIVILEGED
, .x = { .method = { .member = "SetLocalRTC", .signature = "bbb"
, .result = ((void*)0), .handler = method_set_local_rtc, .offset
= 0, }, }, }
,
861 SD_BUS_METHOD("SetNTP", "bb", NULL, method_set_ntp, SD_BUS_VTABLE_UNPRIVILEGED){ .type = _SD_BUS_VTABLE_METHOD, .flags = SD_BUS_VTABLE_UNPRIVILEGED
, .x = { .method = { .member = "SetNTP", .signature = "bb", .
result = ((void*)0), .handler = method_set_ntp, .offset = 0, }
, }, }
,
862 SD_BUS_VTABLE_END{ .type = _SD_BUS_VTABLE_END, .flags = 0, .x = { { 0 } }, },
863};
864
865static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
866 _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0);
867 int r;
868
869 assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("c"), "../src/timedate/timedated.c", 869
, __PRETTY_FUNCTION__); } while (0)
;
870 assert(event)do { if ((__builtin_expect(!!(!(event)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("event"), "../src/timedate/timedated.c",
870, __PRETTY_FUNCTION__); } while (0)
;
871 assert(_bus)do { if ((__builtin_expect(!!(!(_bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_bus"), "../src/timedate/timedated.c", 871
, __PRETTY_FUNCTION__); } while (0)
;
872
873 r = sd_bus_default_system(&bus);
874 if (r < 0)
875 return log_error_errno(r, "Failed to get system bus connection: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 875, __func__, "Failed to get system bus connection: %m"
) : -abs(_e); })
;
876
877 r = sd_bus_add_object_vtable(bus, NULL((void*)0), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", timedate_vtable, c);
878 if (r < 0)
879 return log_error_errno(r, "Failed to register object: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 879, __func__, "Failed to register object: %m"
) : -abs(_e); })
;
880
881 r = sd_bus_request_name_async(bus, NULL((void*)0), "org.freedesktop.timedate1", 0, NULL((void*)0), NULL((void*)0));
882 if (r < 0)
883 return log_error_errno(r, "Failed to request name: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 883, __func__, "Failed to request name: %m"
) : -abs(_e); })
;
884
885 r = sd_bus_attach_event(bus, event, 0);
886 if (r < 0)
887 return log_error_errno(r, "Failed to attach bus to event loop: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 887, __func__, "Failed to attach bus to event loop: %m"
) : -abs(_e); })
;
888
889 *_bus = TAKE_PTR(bus)({ typeof(bus) _ptr_ = (bus); (bus) = ((void*)0); _ptr_; });
890
891 return 0;
892}
893
894int main(int argc, char *argv[]) {
895 Context context = {};
896 _cleanup_(sd_event_unrefp)__attribute__((cleanup(sd_event_unrefp))) sd_event *event = NULL((void*)0);
897 _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0);
898 int r;
899
900 log_set_target(LOG_TARGET_AUTO);
901 log_parse_environment()log_parse_environment_realm(LOG_REALM_SYSTEMD);
902 log_open();
903
904 umask(0022);
905
906 if (argc != 1) {
907 log_error("This program takes no arguments.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 907, __func__, "This program takes no arguments."
) : -abs(_e); })
;
908 r = -EINVAL22;
909 goto finish;
910 }
911
912 r = sd_event_default(&event);
913 if (r < 0) {
914 log_error_errno(r, "Failed to allocate event loop: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 914, __func__, "Failed to allocate event loop: %m"
) : -abs(_e); })
;
915 goto finish;
916 }
917
918 sd_event_set_watchdog(event, true1);
919
920 r = connect_bus(&context, event, &bus);
921 if (r < 0)
922 goto finish;
923
924 (void) sd_bus_negotiate_timestamp(bus, true1);
925
926 r = context_read_data(&context);
927 if (r < 0) {
928 log_error_errno(r, "Failed to read time zone data: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 928, __func__, "Failed to read time zone data: %m"
) : -abs(_e); })
;
929 goto finish;
930 }
931
932 r = context_parse_ntp_services(&context);
933 if (r < 0)
934 goto finish;
935
936 r = bus_event_loop_with_idle(event, bus, "org.freedesktop.timedate1", DEFAULT_EXIT_USEC(30*((usec_t) 1000000ULL)), NULL((void*)0), NULL((void*)0));
937 if (r < 0) {
938 log_error_errno(r, "Failed to run event loop: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/timedate/timedated.c", 938, __func__, "Failed to run event loop: %m"
) : -abs(_e); })
;
939 goto finish;
940 }
941
942finish:
943 context_free(&context);
944
945 return r < 0 ? EXIT_FAILURE1 : EXIT_SUCCESS0;
946}