[newlib-cygwin/main] Cygwin: clocks: read leap secs from /etc/leapsecs on older systems
Corinna Vinschen
corinna@sourceware.org
Fri Jul 18 12:06:43 GMT 2025
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=a0634931f181e9b46818f6fda15d6c28583dccbb
commit a0634931f181e9b46818f6fda15d6c28583dccbb
Author: Corinna Vinschen <corinna@vinschen.de>
AuthorDate: Fri Jul 18 14:06:16 2025 +0200
Commit: Corinna Vinschen <corinna@vinschen.de>
CommitDate: Fri Jul 18 14:06:16 2025 +0200
Cygwin: clocks: read leap secs from /etc/leapsecs on older systems
Systems prior to W10 1803 don't have the leapsecs registry key
HKLM\SYSTEM\CurrentControlSet\Control\LeapSecondInformation and
don't handle leap seconds at all.
Given that new leap seconds are a rather seldom, irregular event,
drop reading from /usr/share/zoneinfo/leapseconds. Just read the
same leap second records from a file /etc/leapsecs as stored in
the LeapSeconds registry value on newer systems instead.
As a sidenote, the code reading from /usr/share/zoneinfo/leapseconds
was wrong anyway, because it didn't take the timestamps into account.
Given IERS publishes new leap seconds about 6 months before they
occur, CLOCK_TAI would have been one second off for up to 6 months.
/etc/leapsecs doesn't exist yet, so we just default to 37 secs. If
new leap seconds get provided for newer systems, make sure to provide
the /etc/leapsecs file as part of the Cygwin distro with identical
entries.
Fixes: 2abb929f0ad2 ("Cygwin: clocks: Implement CLOCK_TAI")
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diff:
---
winsup/cygwin/clock.cc | 88 ++++++++++++++++++++++----------------------------
1 file changed, 39 insertions(+), 49 deletions(-)
diff --git a/winsup/cygwin/clock.cc b/winsup/cygwin/clock.cc
index 007657472961..5a4109c7ac03 100644
--- a/winsup/cygwin/clock.cc
+++ b/winsup/cygwin/clock.cc
@@ -1,10 +1,11 @@
#include "winsup.h"
+#include <unistd.h>
+#include <fcntl.h>
#include <realtimeapiset.h>
#include "pinfo.h"
#include "clock.h"
#include "miscfuncs.h"
#include "registry.h"
-#include <stdio.h>
static inline LONGLONG
system_qpc_tickspersec ()
@@ -66,6 +67,8 @@ struct reg_leap_secs_t
void inline
clk_tai_t::init ()
{
+ size_t size = 0;
+
/* Avoid a lock/unlock sequence */
if (leap_secs)
return;
@@ -91,66 +94,53 @@ clk_tai_t::init ()
we always ignore the file! */
if (!reg.error ())
{
- size_t size = 0;
-
if (!NT_SUCCESS (reg.get_binary (L"LeapSeconds", reg_leap_secs,
sizeof reg_leap_secs, size)))
{
ReleaseSRWLockExclusive (&leap_lock);
return;
}
-
- size /= sizeof reg_leap_secs[0];
- for (size_t i = 0; i < size; ++i)
- {
- struct tm tm = { tm_sec: 59,
- tm_min: 59,
- tm_hour: 23,
- tm_mday: reg_leap_secs[i].day,
- tm_mon: reg_leap_secs[i].month - 1,
- tm_year: reg_leap_secs[i].year - 1900,
- tm_wday: 0,
- tm_yday: 0,
- tm_isdst: 0,
- tm_gmtoff: 0,
- tm_zone: 0
- };
- /* Future timestamp? We're done. Note that the leap sec is
- second 60, therefore <=, not <! */
- if (time (NULL) <= timegm (&tm))
- break;
- leap_secs += reg_leap_secs[i].negative ? -1 : 1;
- }
}
+ /* Windows 8.1 and W10 prior to 1803. When (if) IERS adds new leap secs,
+ we'll create a file /etc/leapsecs in the same format as the aforementioned
+ registry value used on newer OSes. */
else
{
- FILE *fp = fopen ("/usr/share/zoneinfo/leapseconds", "r");
- if (fp)
+ int fd = open ("/etc/leapsecs", O_RDONLY);
+
+ if (fd < 0)
{
- char buf[256];
-
- leap_secs = 10; /* Leap secs 1972 */
- while (fgets (buf, sizeof buf, fp))
- {
- if (buf[0] != 'L')
- continue;
- if (strlen (buf) < 30)
- continue;
- switch (buf[26])
- {
- case '+':
- ++leap_secs;
- break;
- case '-':
- --leap_secs;
- break;
- default:
- break;
- }
- }
- fclose (fp);
+ ReleaseSRWLockExclusive (&leap_lock);
+ return;
}
+ size = (size_t) read (fd, reg_leap_secs, sizeof reg_leap_secs);
+ if ((ssize_t) size < 0)
+ size = 0;
+ close (fd);
+ }
+
+ size /= sizeof reg_leap_secs[0];
+ for (size_t i = 0; i < size; ++i)
+ {
+ struct tm tm = { tm_sec: 59,
+ tm_min: 59,
+ tm_hour: 23,
+ tm_mday: reg_leap_secs[i].day,
+ tm_mon: reg_leap_secs[i].month - 1,
+ tm_year: reg_leap_secs[i].year - 1900,
+ tm_wday: 0,
+ tm_yday: 0,
+ tm_isdst: 0,
+ tm_gmtoff: 0,
+ tm_zone: 0
+ };
+ /* Future timestamp? We're done. Note that the leap sec is
+ second 60, therefore <=, not <! */
+ if (time (NULL) <= timegm (&tm))
+ break;
+ leap_secs += reg_leap_secs[i].negative ? -1 : 1;
}
+
ReleaseSRWLockExclusive (&leap_lock);
}
More information about the Cygwin-cvs
mailing list