]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
bbc98d32 | 2 | |
07630cea | 3 | #include <stdio.h> |
bbc98d32 | 4 | #include <sys/time.h> |
bbc98d32 | 5 | |
6d3db278 | 6 | #include "alloc-util.h" |
3ffd4af2 LP |
7 | #include "clock-util.h" |
8 | #include "fd-util.h" | |
6d3db278 | 9 | #include "fileio.h" |
07630cea | 10 | #include "string-util.h" |
69a283c5 | 11 | #include "time-util.h" |
bbc98d32 | 12 | |
18c59794 | 13 | int clock_is_localtime(const char *adjtime_path) { |
6d3db278 | 14 | int r; |
bbc98d32 | 15 | |
234519ae | 16 | if (!adjtime_path) |
6369641d MP |
17 | adjtime_path = "/etc/adjtime"; |
18 | ||
bbc98d32 KS |
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 | */ | |
18c59794 ZJS |
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); | |
6d3db278 LP |
38 | if (r < 0) |
39 | return r; | |
40 | if (r == 0) | |
41 | return false; /* less than three lines → default to UTC */ | |
18c59794 | 42 | } |
bbc98d32 | 43 | |
18c59794 ZJS |
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 */ | |
bbc98d32 | 49 | |
18c59794 | 50 | return streq(line, "LOCAL"); |
bbc98d32 KS |
51 | } |
52 | ||
505061bb | 53 | int clock_set_timezone(int *ret_minutesdelta) { |
e0f691e1 | 54 | struct tm tm; |
6f5cf415 LP |
55 | int r; |
56 | ||
57 | r = localtime_or_gmtime_usec(now(CLOCK_REALTIME), /* utc= */ false, &tm); | |
58 | if (r < 0) | |
59 | return r; | |
bbc98d32 | 60 | |
18c59794 | 61 | int minutesdelta = tm.tm_gmtoff / 60; |
bbc98d32 | 62 | |
18c59794 | 63 | struct timezone tz = { |
505061bb LP |
64 | .tz_minuteswest = -minutesdelta, |
65 | .tz_dsttime = 0, /* DST_NONE */ | |
66 | }; | |
bbc98d32 | 67 | |
505061bb LP |
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; | |
9c4615fb | 76 | |
bbc98d32 KS |
77 | return 0; |
78 | } |