]>
Commit | Line | Data |
---|---|---|
67a912cd AM |
1 | From cd781c405be82540484da3bfe3d3f17a39b8eb5c Mon Sep 17 00:00:00 2001 |
2 | From: J William Piggott <elseifthen@gmx.com> | |
3 | Date: Fri, 21 Feb 2020 20:03:47 -0500 | |
4 | Subject: [PATCH] hwclock: make glibc 2.31 compatible | |
5 | ||
6 | ______________________________________________________ | |
7 | GNU C Library NEWS -- history of user-visible changes. | |
8 | Version 2.31 | |
9 | Deprecated and removed features, and other changes affecting compatibility: | |
10 | ||
11 | * The settimeofday function can still be used to set a system-wide time | |
12 | zone when the operating system supports it. This is because the Linux | |
13 | kernel reused the API, on some architectures, to describe a system-wide | |
14 | time-zone-like offset between the software clock maintained by the kernel, | |
15 | and the "RTC" clock that keeps time when the system is shut down. | |
16 | ||
17 | However, to reduce the odds of this offset being set by accident, | |
18 | settimeofday can no longer be used to set the time and the offset | |
19 | simultaneously. If both of its two arguments are non-null, the call | |
20 | will fail (setting errno to EINVAL). | |
21 | ||
22 | Callers attempting to set this offset should also be prepared for the call | |
23 | to fail and set errno to ENOSYS; this already happens on the Hurd and on | |
24 | some Linux architectures. The Linux kernel maintainers are discussing a | |
25 | more principled replacement for the reused API. After a replacement | |
26 | becomes available, we will change settimeofday to fail with ENOSYS on all | |
27 | platforms when its 'tzp' argument is not a null pointer. | |
28 | ||
29 | settimeofday itself is obsolescent according to POSIX. Programs that set | |
30 | the system time should use clock_settime and/or the adjtime family of | |
31 | functions instead. We may cease to make settimeofday available to newly | |
32 | linked binaries after there is a replacement for Linux's time-zone-like | |
33 | offset API. | |
34 | ______________________________________________________ | |
35 | ||
36 | hwclock(8) had one settimeofday(2) call where both args were set for | |
37 | --hctosys when the RTC was ticking UTC. This allowed setting the system | |
38 | time, timezone, and locking the warp_clock function with a single call. | |
39 | That operation now takes 3 calls of settimeofday(2). | |
40 | ||
41 | Although this common operation now takes three calls, the overall logic | |
42 | for the set_system_clock() function was simplified. | |
43 | ||
44 | Co-Author: Karel Zak <kzak@redhat.com> | |
45 | Signed-off-by: J William Piggott <elseifthen@gmx.com> | |
46 | --- | |
47 | sys-utils/hwclock.c | 71 +++++++++++++++++++++++---------------------- | |
48 | 1 file changed, 37 insertions(+), 34 deletions(-) | |
49 | ||
50 | diff --git a/sys-utils/hwclock.c b/sys-utils/hwclock.c | |
51 | index e736da717..1191a8571 100644 | |
52 | --- a/sys-utils/hwclock.c | |
53 | +++ b/sys-utils/hwclock.c | |
54 | @@ -643,28 +643,28 @@ display_time(struct timeval hwctime) | |
55 | * tz.tz_minuteswest argument and sets PCIL (see below). At boot settimeofday(2) | |
56 | * has one-shot access to this function as shown in the table below. | |
57 | * | |
58 | - * +-------------------------------------------------------------------+ | |
59 | - * | settimeofday(tv, tz) | | |
60 | - * |-------------------------------------------------------------------| | |
61 | - * | Arguments | System Time | PCIL | | warp_clock | | |
62 | - * | tv | tz | set | warped | set | firsttime | locked | | |
63 | - * |---------|---------|---------------|------|-----------|------------| | |
64 | - * | pointer | NULL | yes | no | no | 1 | no | | |
65 | - * | pointer | pointer | yes | no | no | 0 | yes | | |
66 | - * | NULL | ptr2utc | no | no | no | 0 | yes | | |
67 | - * | NULL | pointer | no | yes | yes | 0 | yes | | |
68 | - * +-------------------------------------------------------------------+ | |
69 | + * +-------------------------------------------------------------------------+ | |
70 | + * | settimeofday(tv, tz) | | |
71 | + * |-------------------------------------------------------------------------| | |
72 | + * | Arguments | System Time | TZ | PCIL | | warp_clock | | |
73 | + * | tv | tz | set | warped | set | set | firsttime | locked | | |
74 | + * |---------|---------|---------------|-----|------|-----------|------------| | |
75 | + * | pointer | NULL | yes | no | no | no | 1 | no | | |
76 | + * | NULL | ptr2utc | no | no | yes | no | 0 | yes | | |
77 | + * | NULL | pointer | no | yes | yes | yes | 0 | yes | | |
78 | + * +-------------------------------------------------------------------------+ | |
79 | * ptr2utc: tz.tz_minuteswest is zero (UTC). | |
80 | * PCIL: persistent_clock_is_local, sets the "11 minute mode" timescale. | |
81 | * firsttime: locks the warp_clock function (initialized to 1 at boot). | |
82 | + * Since glibc v2.31 settimeofday() will fail if both args are non NULL | |
83 | * | |
84 | * +---------------------------------------------------------------------------+ | |
85 | * | op | RTC scale | settimeofday calls | | |
86 | * |---------|-----------|-----------------------------------------------------| | |
87 | * | systz | Local | 1) warps system time*, sets PCIL* and kernel tz | | |
88 | * | systz | UTC | 1st) locks warp_clock* 2nd) sets kernel tz | | |
89 | - * | hctosys | Local | 1st) sets PCIL* 2nd) sets system time and kernel tz | | |
90 | - * | hctosys | UTC | 1) sets system time and kernel tz | | |
91 | + * | hctosys | Local | 1st) sets PCIL* & kernel tz 2nd) sets system time | | |
92 | + * | hctosys | UTC | 1st) locks warp* 2nd) sets tz 3rd) sets system time | | |
93 | * +---------------------------------------------------------------------------+ | |
94 | * * only on first call after boot | |
95 | */ | |
96 | @@ -675,42 +675,45 @@ set_system_clock(const struct hwclock_control *ctl, | |
97 | struct tm broken; | |
98 | int minuteswest; | |
99 | int rc = 0; | |
100 | - const struct timezone tz_utc = { 0 }; | |
101 | ||
102 | localtime_r(&newtime.tv_sec, &broken); | |
103 | minuteswest = -get_gmtoff(&broken) / 60; | |
104 | ||
105 | if (ctl->verbose) { | |
106 | - if (ctl->hctosys && !ctl->universal) | |
107 | - printf(_("Calling settimeofday(NULL, %d) to set " | |
108 | - "persistent_clock_is_local.\n"), minuteswest); | |
109 | - if (ctl->systz && ctl->universal) | |
110 | + if (ctl->universal) { | |
111 | puts(_("Calling settimeofday(NULL, 0) " | |
112 | - "to lock the warp function.")); | |
113 | + "to lock the warp_clock function.")); | |
114 | + if (!( ctl->universal && !minuteswest )) | |
115 | + printf(_("Calling settimeofday(NULL, %d) " | |
116 | + "to set the kernel timezone.\n"), | |
117 | + minuteswest); | |
118 | + } else | |
119 | + printf(_("Calling settimeofday(NULL, %d) to warp " | |
120 | + "System time, set PCIL and the kernel tz.\n"), | |
121 | + minuteswest); | |
122 | + | |
123 | if (ctl->hctosys) | |
124 | - printf(_("Calling settimeofday(%ld.%06ld, %d)\n"), | |
125 | - newtime.tv_sec, newtime.tv_usec, minuteswest); | |
126 | - else { | |
127 | - printf(_("Calling settimeofday(NULL, %d) "), minuteswest); | |
128 | - if (ctl->universal) | |
129 | - puts(_("to set the kernel timezone.")); | |
130 | - else | |
131 | - puts(_("to warp System time.")); | |
132 | - } | |
133 | + printf(_("Calling settimeofday(%ld.%06ld, NULL) " | |
134 | + "to set the System time.\n"), | |
135 | + newtime.tv_sec, newtime.tv_usec); | |
136 | } | |
137 | ||
138 | if (!ctl->testing) { | |
139 | + const struct timezone tz_utc = { 0 }; | |
140 | const struct timezone tz = { minuteswest }; | |
141 | ||
142 | - if (ctl->hctosys && !ctl->universal) /* set PCIL */ | |
143 | - rc = settimeofday(NULL, &tz); | |
144 | - if (ctl->systz && ctl->universal) /* lock warp_clock */ | |
145 | + /* If UTC RTC: lock warp_clock and PCIL */ | |
146 | + if (ctl->universal) | |
147 | rc = settimeofday(NULL, &tz_utc); | |
148 | - if (!rc && ctl->hctosys) | |
149 | - rc = settimeofday(&newtime, &tz); | |
150 | - else if (!rc) | |
151 | + | |
152 | + /* Set kernel tz; if localtime RTC: warp_clock and set PCIL */ | |
153 | + if (!rc && !( ctl->universal && !minuteswest )) | |
154 | rc = settimeofday(NULL, &tz); | |
155 | ||
156 | + /* Set the System Clock */ | |
157 | + if ((!rc || errno == ENOSYS) && ctl->hctosys) | |
158 | + rc = settimeofday(&newtime, NULL); | |
159 | + | |
160 | if (rc) { | |
161 | warn(_("settimeofday() failed")); | |
162 | return EXIT_FAILURE; |