]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/shared/clock-util.c
io.systemd.Unit.List fix context/runtime split (#38172)
[thirdparty/systemd.git] / src / shared / clock-util.c
... / ...
CommitLineData
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3#include <stdio.h>
4#include <sys/time.h>
5
6#include "alloc-util.h"
7#include "clock-util.h"
8#include "fd-util.h"
9#include "fileio.h"
10#include "string-util.h"
11#include "time-util.h"
12
13int clock_is_localtime(const char *adjtime_path) {
14 int r;
15
16 if (!adjtime_path)
17 adjtime_path = "/etc/adjtime";
18
19 /*
20 * The third line of adjtime is "UTC" or "LOCAL" or nothing.
21 * # /etc/adjtime
22 * 0.0 0 0
23 * 0
24 * UTC
25 */
26 _cleanup_fclose_ FILE *f = fopen(adjtime_path, "re");
27 if (!f) {
28 if (errno != ENOENT)
29 return -errno;
30
31 /* adjtime_path not present → default to UTC */
32 return false;
33 }
34
35 _cleanup_free_ char *line = NULL;
36 for (unsigned i = 0; i < 2; i++) { /* skip the first two lines */
37 r = read_line(f, LONG_LINE_MAX, NULL);
38 if (r < 0)
39 return r;
40 if (r == 0)
41 return false; /* less than three lines → default to UTC */
42 }
43
44 r = read_line(f, LONG_LINE_MAX, &line);
45 if (r < 0)
46 return r;
47 if (r == 0)
48 return false; /* less than three lines → default to UTC */
49
50 return streq(line, "LOCAL");
51}
52
53int clock_set_timezone(int *ret_minutesdelta) {
54 struct tm tm;
55 int r;
56
57 r = localtime_or_gmtime_usec(now(CLOCK_REALTIME), /* utc= */ false, &tm);
58 if (r < 0)
59 return r;
60
61 int minutesdelta = tm.tm_gmtoff / 60;
62
63 struct timezone tz = {
64 .tz_minuteswest = -minutesdelta,
65 .tz_dsttime = 0, /* DST_NONE */
66 };
67
68 /* If the RTC does not run in UTC but in local time, the very first call to settimeofday() will set
69 * the kernel's timezone and will warp the system clock, so that it runs in UTC instead of the local
70 * time we have read from the RTC. */
71 if (settimeofday(NULL, &tz) < 0)
72 return -errno;
73
74 if (ret_minutesdelta)
75 *ret_minutesdelta = minutesdelta;
76
77 return 0;
78}