mirror of
https://git.FreeBSD.org/src.git
synced 2026-06-02 11:24:32 +00:00
Import tzcode 2026b
This commit is contained in:
@@ -1,10 +1,47 @@
|
|||||||
News for the tz database
|
News for the tz database
|
||||||
|
|
||||||
|
Release 2026b - 2026-04-22 23:06:43 -0700
|
||||||
|
|
||||||
|
Briefly:
|
||||||
|
British Columbia moved to permanent -07 on 2026-03-09.
|
||||||
|
Some more overflow bugs have been fixed in zic.
|
||||||
|
|
||||||
|
Changes to future timestamps
|
||||||
|
|
||||||
|
British Columbia’s 2026-03-08 spring forward was its last
|
||||||
|
foreseeable clock change, as it moved to permanent -07 thereafter.
|
||||||
|
(Thanks to Arthur David Olson.) Although the change to permanent
|
||||||
|
-07 legally took place on 2026-03-09, temporarily model the change
|
||||||
|
to occur on 2026-11-01 at 02:00 instead. This works around a
|
||||||
|
limitation in CLDR v48.2 (2026-03-17). This temporary hack is
|
||||||
|
planned to be removed after CLDR is fixed.
|
||||||
|
|
||||||
|
Changes to code
|
||||||
|
|
||||||
|
zic no longer mishandles a last transition to a new time type.
|
||||||
|
|
||||||
|
zic no longer overflows a buffer when generating a TZ string like
|
||||||
|
"PST-167:59:58PDT-167:59:59,M11.5.6/-167:59:59,M12.5.6/-167:59:59",
|
||||||
|
which can occur with adversarial input. (Thanks to Naveed Khan.)
|
||||||
|
|
||||||
|
zic no longer generates a longer TZif file than necessary when
|
||||||
|
an earlier time zone abbreviation is a suffix of a later one.
|
||||||
|
As a nice side effect, zic no longer overflows a buffer when given
|
||||||
|
a long series of abbreviations, each a suffix of the next.
|
||||||
|
(Buffer overflow reported by Arthur Chan.)
|
||||||
|
|
||||||
|
zic no longer overflows an int when processing input like ‘Zone
|
||||||
|
Ouch 2147483648:00:00 - LMT’. The int overflow can lead to buffer
|
||||||
|
overflow in adversarial cases. (Thanks to Naveed Khan.)
|
||||||
|
|
||||||
|
zic now checks for signals more often.
|
||||||
|
|
||||||
|
|
||||||
Release 2026a - 2026-03-01 22:59:49 -0800
|
Release 2026a - 2026-03-01 22:59:49 -0800
|
||||||
|
|
||||||
Briefly:
|
Briefly:
|
||||||
Moldova has used EU transition times since 2022.
|
Moldova has used EU transition times since 2022.
|
||||||
The "right" TZif files are no longer installed by default.
|
The “right” TZif files are no longer installed by default.
|
||||||
-DTZ_RUNTIME_LEAPS=0 disables runtime support for leap seconds.
|
-DTZ_RUNTIME_LEAPS=0 disables runtime support for leap seconds.
|
||||||
TZif files are no longer limited to 50 bytes of abbreviations.
|
TZif files are no longer limited to 50 bytes of abbreviations.
|
||||||
zic is no longer limited to 50 leap seconds.
|
zic is no longer limited to 50 leap seconds.
|
||||||
@@ -25,23 +62,23 @@ Release 2026a - 2026-03-01 22:59:49 -0800
|
|||||||
|
|
||||||
The Makefile no longer by default installs an alternate set
|
The Makefile no longer by default installs an alternate set
|
||||||
of TZif files for system clocks that count leap seconds.
|
of TZif files for system clocks that count leap seconds.
|
||||||
Install with 'make REDO=posix_right' to get the old default,
|
Install with ‘make REDO=posix_right’ to get the old default,
|
||||||
which is rarely used in major downstream distributions.
|
which is rarely used in major downstream distributions.
|
||||||
If your system clock counts leap seconds (contrary to POSIX),
|
If your system clock counts leap seconds (contrary to POSIX),
|
||||||
it is better to install with 'make REDO=right_only'.
|
it is better to install with ‘make REDO=right_only’.
|
||||||
This change does not affect the leapseconds file, which is still
|
This change does not affect the leapseconds file, which is still
|
||||||
installed as before.
|
installed as before.
|
||||||
|
|
||||||
The Makefile's POSIXRULES option, which was declared obsolete in
|
The Makefile’s POSIXRULES option, which was declared obsolete in
|
||||||
release 2019b, has been removed. The Makefile's build procedure
|
release 2019b, has been removed. The Makefile’s build procedure
|
||||||
thus no longer optionally installs the obsolete posixrules file.
|
thus no longer optionally installs the obsolete posixrules file.
|
||||||
|
|
||||||
Changes to code
|
Changes to code
|
||||||
|
|
||||||
Compiling with the new option -DTZ_RUNTIME_LEAPS=0 disables
|
Compiling with the new option -DTZ_RUNTIME_LEAPS=0 disables
|
||||||
runtime support for leap seconds. Although this conforms to
|
runtime support for leap seconds. Although this conforms to
|
||||||
POSIX, shrinks tzcode's attack surface, and is more efficient,
|
POSIX, shrinks tzcode’s attack surface, and is more efficient,
|
||||||
it fails to support Internet RFC 9636's leap seconds.
|
it fails to support Internet RFC 9636’s leap seconds.
|
||||||
|
|
||||||
zic now can generate, and localtime.c can now use, TZif files that
|
zic now can generate, and localtime.c can now use, TZif files that
|
||||||
hold up to 256 bytes of abbreviations, counting trailing NULs.
|
hold up to 256 bytes of abbreviations, counting trailing NULs.
|
||||||
@@ -51,7 +88,7 @@ Release 2026a - 2026-03-01 22:59:49 -0800
|
|||||||
|
|
||||||
zic -L can now generate TZif files with more than 50 leap seconds.
|
zic -L can now generate TZif files with more than 50 leap seconds.
|
||||||
This helps test TZif readers not limited to 50 leap seconds, as
|
This helps test TZif readers not limited to 50 leap seconds, as
|
||||||
tzcode's localtime.c is; it has little immediate need for
|
tzcode’s localtime.c is; it has little immediate need for
|
||||||
practical timekeeping as there have been only 27 leap seconds and
|
practical timekeeping as there have been only 27 leap seconds and
|
||||||
possibly there will be no more, due to planned changes to UTC.
|
possibly there will be no more, due to planned changes to UTC.
|
||||||
zic -v warns if its output exceeds the old 50-second limit.
|
zic -v warns if its output exceeds the old 50-second limit.
|
||||||
|
|||||||
+1
-1
@@ -446,7 +446,7 @@ Includes the song “Does Anybody Really Know What Time It Is?”.
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Emanuele Arciuli,
|
Emanuele Arciuli,
|
||||||
<a href="https://neumarecords.org/ols/products/william-duckworth-the-time-curve-preludes"><em>The Time Curve Preludes</em></a> (2023).
|
<a href="https://williamduckworth.bandcamp.com/album/the-time-curve-preludes"><em>The Time Curve Preludes</em></a> (2023).
|
||||||
Neuma 174, 44:46.
|
Neuma 174, 44:46.
|
||||||
The title piece, composed by
|
The title piece, composed by
|
||||||
<a href="https://en.wikipedia.org/wiki/William_Duckworth_(composer)">William
|
<a href="https://en.wikipedia.org/wiki/William_Duckworth_(composer)">William
|
||||||
|
|||||||
+15
-7
@@ -441,7 +441,7 @@ transition in the <code><abbr>tz</abbr></code> database.</li>
|
|||||||
Database Parser</a> is a
|
Database Parser</a> is a
|
||||||
<a href="https://en.wikipedia.org/wiki/C++">C++</a> parser and
|
<a href="https://en.wikipedia.org/wiki/C++">C++</a> parser and
|
||||||
runtime library with a <a
|
runtime library with a <a
|
||||||
href="https://en.cppreference.com/w/cpp/chrono.html"><code>std::chrono</code> API</a>
|
href="https://en.cppreference.com/cpp/chrono"><code>std::chrono</code> API</a>
|
||||||
that is a standard part of C++.
|
that is a standard part of C++.
|
||||||
It is freely available under the
|
It is freely available under the
|
||||||
<abbr title="Massachusetts Institute of Technology">MIT</abbr> license.</li>
|
<abbr title="Massachusetts Institute of Technology">MIT</abbr> license.</li>
|
||||||
@@ -1135,8 +1135,7 @@ Network Time Protocol Best Current Practices</a>
|
|||||||
applications requiring accurate <abbr>UTC</abbr> or civil time,
|
applications requiring accurate <abbr>UTC</abbr> or civil time,
|
||||||
and is intended for use only in single, well-controlled environments.</li>
|
and is intended for use only in single, well-controlled environments.</li>
|
||||||
<li>The <a
|
<li>The <a
|
||||||
href="https://pairlist6.pair.net/mailman/listinfo/leapsecs">Leap
|
href="https://groups.io/g/LEAPSECS">LEAPSECS List</a> covers <a
|
||||||
Second Discussion List</a> covers <a
|
|
||||||
href="https://gge.ext.unb.ca/Resources/gpsworld.november99.pdf">McCarthy
|
href="https://gge.ext.unb.ca/Resources/gpsworld.november99.pdf">McCarthy
|
||||||
and Klepczynski’s 1999 proposal to discontinue leap seconds</a>,
|
and Klepczynski’s 1999 proposal to discontinue leap seconds</a>,
|
||||||
discussed further in
|
discussed further in
|
||||||
@@ -1146,21 +1145,30 @@ leap second: its history and possible future</a>.
|
|||||||
might be redefined
|
might be redefined
|
||||||
without Leap Seconds</a> gives pointers on this
|
without Leap Seconds</a> gives pointers on this
|
||||||
contentious issue.
|
contentious issue.
|
||||||
The General Conference on Weights and Measures
|
The General Conference on Weights and Measures (CGPM)
|
||||||
<a href="https://www.bipm.org/en/cgpm-2022/resolution-4">decided in 2022</a>
|
<a href="https://www.bipm.org/en/cgpm-2022/resolution-4">decided in 2022</a>
|
||||||
to discontinue the use of leap seconds by 2035, and requested that no
|
to discontinue the use of leap seconds by 2035, and requested that no
|
||||||
discontinuous adjustments be made to UTC for at least a century.
|
discontinuous adjustments be made to UTC for at least a century.
|
||||||
The World Radiocommunication Conference <a
|
The World Radiocommunication Conference <a
|
||||||
href="https://www.itu.int/dms_pub/itu-r/opb/act/R-ACT-WRC.15-2023-PDF-E.pdf">resolved
|
href="https://www.itu.int/dms_pub/itu-r/opb/act/R-ACT-WRC.15-2023-PDF-E.pdf">resolved
|
||||||
in 2023</a> to cooperate with this process. One proposal to implement this
|
in 2023</a> to cooperate with this process. A draft <a
|
||||||
|
href="https://www.bipm.org/documents/d/guest/cgpm-2026-draft-resolutions">Resolution
|
||||||
|
C to make continuous UTC effective on 2027-05-20</a>,
|
||||||
|
and thereby discontinue leap seconds,
|
||||||
|
has been scheduled for the 28th CGPM starting 2026-10-13 in Paris.
|
||||||
|
One proposal to implement this
|
||||||
would replace leap seconds with seven 13-second leap smears occurring once per
|
would replace leap seconds with seven 13-second leap smears occurring once per
|
||||||
decade until 2100, with leap smears after that gradually increasing in size.
|
decade until 2100, with leap smears after that gradually increasing in size.
|
||||||
See:
|
See:
|
||||||
<ul>
|
<ul>
|
||||||
<li>Levine J. <a href="https://www.preprints.org/manuscript/202406.0043">A
|
<li>Levine J. <a href="https://tf.nist.gov/general/pdf/3242.pdf">A
|
||||||
proposal to change the leap-second adjustments to
|
proposal to change the leap-second adjustments to
|
||||||
coordinated universal time</a>. <em>Metrologia.</em> 2024;61(5):055002. doi:<a
|
coordinated universal time</a>. <em>Metrologia.</em> 2024;61(5):055002. doi:<a
|
||||||
href="https://doi.org/10.1088/1681-7575/ad6266">10.1088/1681-7575/ad6266</a>.</li>
|
href="https://doi.org/10.1088/1681-7575/ad6266">10.1088/1681-7575/ad6266</a>
|
||||||
|
with followups in doi:<a
|
||||||
|
href="https://doi.org/10.1088/1681-7575/ade314">10.1088/1681-7575/ade314</a>
|
||||||
|
and doi:<a
|
||||||
|
href="https://doi.org/10.1088/1681-7575/ade315">10.1088/1681-7575/ade315</a>.</li>
|
||||||
</ul>
|
</ul>
|
||||||
However, there is still no consensus on whether this is the best way
|
However, there is still no consensus on whether this is the best way
|
||||||
to replace leap seconds.
|
to replace leap seconds.
|
||||||
|
|||||||
@@ -253,11 +253,13 @@ symlink(char const *target, char const *linkname)
|
|||||||
(errno = ENOTSUP, -1)
|
(errno = ENOTSUP, -1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int addabbr(char[TZ_MAX_CHARS], int *, char const *);
|
||||||
static void addtt(zic_t starttime, int type);
|
static void addtt(zic_t starttime, int type);
|
||||||
static int addtype(zic_t, char const *, bool, bool, bool);
|
static int addtype(zic_t, char const *, bool, bool, bool);
|
||||||
static void leapadd(zic_t, int, int);
|
|
||||||
static void adjleap(void);
|
static void adjleap(void);
|
||||||
static void associate(void);
|
static void associate(void);
|
||||||
|
static void checkabbr(char const *);
|
||||||
|
static void check_for_signal(void);
|
||||||
static void dolink(const char *, const char *, bool);
|
static void dolink(const char *, const char *, bool);
|
||||||
static int getfields(char *, char **, int);
|
static int getfields(char *, char **, int);
|
||||||
static zic_t gethms(const char * string, const char * errstring);
|
static zic_t gethms(const char * string, const char * errstring);
|
||||||
@@ -270,11 +272,11 @@ static void inrule(char ** fields, int nfields);
|
|||||||
static bool inzcont(char ** fields, int nfields);
|
static bool inzcont(char ** fields, int nfields);
|
||||||
static bool inzone(char ** fields, int nfields);
|
static bool inzone(char ** fields, int nfields);
|
||||||
static bool inzsub(char **, int, bool);
|
static bool inzsub(char **, int, bool);
|
||||||
static int itssymlink(char const *, int *);
|
|
||||||
static bool is_alpha(char a);
|
static bool is_alpha(char a);
|
||||||
|
static int itssymlink(char const *, int *);
|
||||||
|
static void leapadd(zic_t, int, int);
|
||||||
static char lowerit(char);
|
static char lowerit(char);
|
||||||
static void mkdirs(char const *, bool);
|
static void mkdirs(char const *, bool);
|
||||||
static void newabbr(const char * abbr);
|
|
||||||
static zic_t oadd(zic_t t1, zic_t t2);
|
static zic_t oadd(zic_t t1, zic_t t2);
|
||||||
static zic_t omul(zic_t, zic_t);
|
static zic_t omul(zic_t, zic_t);
|
||||||
static void outzone(const struct zone * zp, ptrdiff_t ntzones);
|
static void outzone(const struct zone * zp, ptrdiff_t ntzones);
|
||||||
@@ -704,6 +706,7 @@ eat(int fnum, lineno num)
|
|||||||
ATTRIBUTE_FORMAT((printf, 1, 0)) static void
|
ATTRIBUTE_FORMAT((printf, 1, 0)) static void
|
||||||
verror(const char *const string, va_list args)
|
verror(const char *const string, va_list args)
|
||||||
{
|
{
|
||||||
|
check_for_signal();
|
||||||
/*
|
/*
|
||||||
** Match the format of "cc" to allow sh users to
|
** Match the format of "cc" to allow sh users to
|
||||||
** zic ... 2>&1 | error -t "*" -v
|
** zic ... 2>&1 | error -t "*" -v
|
||||||
@@ -1074,6 +1077,7 @@ make_links(void)
|
|||||||
warning(_("link %s targeting link %s"),
|
warning(_("link %s targeting link %s"),
|
||||||
links[i].l_linkname, links[i].l_target);
|
links[i].l_linkname, links[i].l_target);
|
||||||
}
|
}
|
||||||
|
check_for_signal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1391,6 +1395,7 @@ main(int argc, char **argv)
|
|||||||
for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
|
for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
|
||||||
continue;
|
continue;
|
||||||
outzone(&zones[i], j - i);
|
outzone(&zones[i], j - i);
|
||||||
|
check_for_signal();
|
||||||
}
|
}
|
||||||
make_links();
|
make_links();
|
||||||
if (lcltime != NULL) {
|
if (lcltime != NULL) {
|
||||||
@@ -1486,9 +1491,11 @@ get_rand_u64(void)
|
|||||||
static int nwords;
|
static int nwords;
|
||||||
if (!nwords) {
|
if (!nwords) {
|
||||||
ssize_t s;
|
ssize_t s;
|
||||||
do
|
for (;; check_for_signal()) {
|
||||||
s = getrandom(entropy_buffer, sizeof entropy_buffer, 0);
|
s = getrandom(entropy_buffer, sizeof entropy_buffer, 0);
|
||||||
while (s < 0 && errno == EINTR);
|
if (! (s < 0 && errno == EINTR))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
nwords = s < 0 ? -1 : s / sizeof *entropy_buffer;
|
nwords = s < 0 ? -1 : s / sizeof *entropy_buffer;
|
||||||
}
|
}
|
||||||
@@ -1516,7 +1523,7 @@ get_rand_u64(void)
|
|||||||
rmod = INT_MAX < UINT_FAST64_MAX ? 0 : UINT_FAST64_MAX / nrand + 1,
|
rmod = INT_MAX < UINT_FAST64_MAX ? 0 : UINT_FAST64_MAX / nrand + 1,
|
||||||
r = 0, rmax = 0;
|
r = 0, rmax = 0;
|
||||||
|
|
||||||
do {
|
for (;; check_for_signal()) {
|
||||||
uint_fast64_t rmax1 = rmax;
|
uint_fast64_t rmax1 = rmax;
|
||||||
if (rmod) {
|
if (rmod) {
|
||||||
/* Avoid signed integer overflow on theoretical platforms
|
/* Avoid signed integer overflow on theoretical platforms
|
||||||
@@ -1527,7 +1534,9 @@ get_rand_u64(void)
|
|||||||
rmax1 = nrand * rmax1 + rand_max;
|
rmax1 = nrand * rmax1 + rand_max;
|
||||||
r = nrand * r + rand();
|
r = nrand * r + rand();
|
||||||
rmax = rmax < rmax1 ? rmax1 : UINT_FAST64_MAX;
|
rmax = rmax < rmax1 ? rmax1 : UINT_FAST64_MAX;
|
||||||
} while (rmax < UINT_FAST64_MAX);
|
if (UINT_FAST64_MAX <= rmax)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -1574,9 +1583,11 @@ random_dirent(char const **name, char **namealloc)
|
|||||||
*name = *namealloc = dst;
|
*name = *namealloc = dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
for (;; check_for_signal()) {
|
||||||
r = get_rand_u64();
|
r = get_rand_u64();
|
||||||
while (unfair_min <= r);
|
if (r < unfair_min)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < suffixlen; i++) {
|
for (i = 0; i < suffixlen; i++) {
|
||||||
dst[dirlen + prefixlen + i] = alphabet[r % alphabetlen];
|
dst[dirlen + prefixlen + i] = alphabet[r % alphabetlen];
|
||||||
@@ -1611,7 +1622,7 @@ open_outfile(char const **outname, char **tempname)
|
|||||||
if (!*tempname)
|
if (!*tempname)
|
||||||
random_dirent(outname, tempname);
|
random_dirent(outname, tempname);
|
||||||
|
|
||||||
while (true) {
|
for (;; check_for_signal()) {
|
||||||
int oflags = O_WRONLY | O_BINARY | O_CREAT | O_EXCL;
|
int oflags = O_WRONLY | O_BINARY | O_CREAT | O_EXCL;
|
||||||
int fd = open(*outname, oflags, creat_perms);
|
int fd = open(*outname, oflags, creat_perms);
|
||||||
int err;
|
int err;
|
||||||
@@ -1725,8 +1736,6 @@ dolink(char const *target, char const *linkname, bool staysymlink)
|
|||||||
char const *outname = linkname;
|
char const *outname = linkname;
|
||||||
int targetissym = -2, linknameissym = -2;
|
int targetissym = -2, linknameissym = -2;
|
||||||
|
|
||||||
check_for_signal();
|
|
||||||
|
|
||||||
if (strcmp(target, "-") == 0) {
|
if (strcmp(target, "-") == 0) {
|
||||||
if (remove(linkname) == 0 || errno == ENOENT || errno == ENOTDIR)
|
if (remove(linkname) == 0 || errno == ENOENT || errno == ENOTDIR)
|
||||||
return;
|
return;
|
||||||
@@ -1739,7 +1748,7 @@ dolink(char const *target, char const *linkname, bool staysymlink)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
for (;; check_for_signal()) {
|
||||||
if (linkat(AT_FDCWD, target, AT_FDCWD, outname, AT_SYMLINK_FOLLOW)
|
if (linkat(AT_FDCWD, target, AT_FDCWD, outname, AT_SYMLINK_FOLLOW)
|
||||||
== 0) {
|
== 0) {
|
||||||
link_errno = 0;
|
link_errno = 0;
|
||||||
@@ -1791,7 +1800,7 @@ dolink(char const *target, char const *linkname, bool staysymlink)
|
|||||||
int symlink_errno = -1;
|
int symlink_errno = -1;
|
||||||
|
|
||||||
if (contents) {
|
if (contents) {
|
||||||
while (true) {
|
for (;; check_for_signal()) {
|
||||||
if (symlink(contents, outname) == 0) {
|
if (symlink(contents, outname) == 0) {
|
||||||
symlink_errno = 0;
|
symlink_errno = 0;
|
||||||
break;
|
break;
|
||||||
@@ -1822,7 +1831,7 @@ dolink(char const *target, char const *linkname, bool staysymlink)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
tp = open_outfile(&outname, &tempname);
|
tp = open_outfile(&outname, &tempname);
|
||||||
while ((c = getc(fp)) != EOF)
|
for (; (c = getc(fp)) != EOF; check_for_signal())
|
||||||
putc(c, tp);
|
putc(c, tp);
|
||||||
close_file(tp, directory, linkname, tempname);
|
close_file(tp, directory, linkname, tempname);
|
||||||
close_file(fp, directory, target, NULL);
|
close_file(fp, directory, target, NULL);
|
||||||
@@ -1946,7 +1955,7 @@ static bool
|
|||||||
inputline(FILE *fp, char *buf, ptrdiff_t bufsize)
|
inputline(FILE *fp, char *buf, ptrdiff_t bufsize)
|
||||||
{
|
{
|
||||||
ptrdiff_t linelen = 0, ch;
|
ptrdiff_t linelen = 0, ch;
|
||||||
while ((ch = getc(fp)) != '\n') {
|
for (; (ch = getc(fp)) != '\n'; check_for_signal()) {
|
||||||
if (ch < 0) {
|
if (ch < 0) {
|
||||||
if (ferror(fp)) {
|
if (ferror(fp)) {
|
||||||
error(_("input error"));
|
error(_("input error"));
|
||||||
@@ -2033,6 +2042,7 @@ infile(int fnum, char const *name)
|
|||||||
default: unreachable();
|
default: unreachable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
check_for_signal();
|
||||||
}
|
}
|
||||||
close_file(fp, NULL, filename(fnum), NULL);
|
close_file(fp, NULL, filename(fnum), NULL);
|
||||||
if (wantcont)
|
if (wantcont)
|
||||||
@@ -2927,30 +2937,27 @@ writezone(const char *const name, const char *const string, char version,
|
|||||||
: i == thisdefaulttype ? old0 : i]
|
: i == thisdefaulttype ? old0 : i]
|
||||||
= thistypecnt++;
|
= thistypecnt++;
|
||||||
|
|
||||||
for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
|
|
||||||
indmap[i] = -1;
|
|
||||||
thischarcnt = stdcnt = utcnt = 0;
|
thischarcnt = stdcnt = utcnt = 0;
|
||||||
for (i = old0; i < typecnt; i++) {
|
for (i = old0; i < typecnt; i++) {
|
||||||
register char * thisabbr;
|
|
||||||
|
|
||||||
if (omittype[i])
|
if (omittype[i])
|
||||||
continue;
|
continue;
|
||||||
if (ttisstds[i])
|
if (ttisstds[i])
|
||||||
stdcnt = thistypecnt;
|
stdcnt = thistypecnt;
|
||||||
if (ttisuts[i])
|
if (ttisuts[i])
|
||||||
utcnt = thistypecnt;
|
utcnt = thistypecnt;
|
||||||
if (indmap[desigidx[i]] >= 0)
|
addabbr(thischars, &thischarcnt, &chars[desigidx[i]]);
|
||||||
continue;
|
|
||||||
thisabbr = &chars[desigidx[i]];
|
|
||||||
for (j = 0; j < thischarcnt; ++j)
|
|
||||||
if (strcmp(&thischars[j], thisabbr) == 0)
|
|
||||||
break;
|
|
||||||
if (j == thischarcnt) {
|
|
||||||
strcpy(&thischars[thischarcnt], thisabbr);
|
|
||||||
thischarcnt += strlen(thisabbr) + 1;
|
|
||||||
}
|
|
||||||
indmap[desigidx[i]] = j;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now that all abbrevs have been added to THISCHARS,
|
||||||
|
it is safe to set INDMAP without worrying about
|
||||||
|
whether the abbrevs might move later. */
|
||||||
|
for (i = 0; i < TZ_MAX_CHARS; i++)
|
||||||
|
indmap[i] = -1;
|
||||||
|
for (i = old0; i < typecnt; i++)
|
||||||
|
if (!omittype[i] && indmap[desigidx[i]] < 0)
|
||||||
|
indmap[desigidx[i]] = addabbr(thischars, &thischarcnt,
|
||||||
|
&chars[desigidx[i]]);
|
||||||
|
|
||||||
if (pass == 1 && !want_bloat()) {
|
if (pass == 1 && !want_bloat()) {
|
||||||
hicut = thisleapexpiry = false;
|
hicut = thisleapexpiry = false;
|
||||||
pretranstype = -1;
|
pretranstype = -1;
|
||||||
@@ -3173,11 +3180,11 @@ stringoffset(char *result, zic_t offset)
|
|||||||
offset /= SECSPERMIN;
|
offset /= SECSPERMIN;
|
||||||
minutes = offset % MINSPERHOUR;
|
minutes = offset % MINSPERHOUR;
|
||||||
offset /= MINSPERHOUR;
|
offset /= MINSPERHOUR;
|
||||||
hours = offset;
|
if (offset >= HOURSPERDAY * DAYSPERWEEK) {
|
||||||
if (hours >= HOURSPERDAY * DAYSPERWEEK) {
|
|
||||||
result[0] = '\0';
|
result[0] = '\0';
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
hours = offset;
|
||||||
len += sprintf(result + len, "%d", hours);
|
len += sprintf(result + len, "%d", hours);
|
||||||
if (minutes != 0 || seconds != 0) {
|
if (minutes != 0 || seconds != 0) {
|
||||||
len += sprintf(result + len, ":%02d", minutes);
|
len += sprintf(result + len, ":%02d", minutes);
|
||||||
@@ -3416,12 +3423,16 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
|||||||
int nonTZlimtype = -1;
|
int nonTZlimtype = -1;
|
||||||
zic_t max_year0;
|
zic_t max_year0;
|
||||||
int defaulttype = -1;
|
int defaulttype = -1;
|
||||||
|
int max_stringoffset_len = sizeof "-167:59:59" - 1;
|
||||||
|
int max_comma_stringrule_len = (sizeof ",M12.5.6/" - 1
|
||||||
|
+ max_stringoffset_len);
|
||||||
|
|
||||||
check_for_signal();
|
check_for_signal();
|
||||||
|
|
||||||
/* This cannot overflow; see FORMAT_LEN_GROWTH_BOUND. */
|
/* This cannot overflow; see FORMAT_LEN_GROWTH_BOUND. */
|
||||||
max_abbr_len = 2 + max_format_len + max_abbrvar_len;
|
max_abbr_len = 2 + max_format_len + max_abbrvar_len;
|
||||||
max_envvar_len = 2 * max_abbr_len + 5 * 9;
|
max_envvar_len = 2 * (max_abbr_len + max_stringoffset_len
|
||||||
|
+ max_comma_stringrule_len);
|
||||||
|
|
||||||
startbuf = xmalloc(max_abbr_len + 1);
|
startbuf = xmalloc(max_abbr_len + 1);
|
||||||
ab = xmalloc(max_abbr_len + 1);
|
ab = xmalloc(max_abbr_len + 1);
|
||||||
@@ -3522,7 +3533,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
|||||||
startttisut);
|
startttisut);
|
||||||
if (usestart) {
|
if (usestart) {
|
||||||
addtt(starttime, type);
|
addtt(starttime, type);
|
||||||
if (useuntil && nonTZlimtime < starttime) {
|
if (nonTZlimtime < starttime) {
|
||||||
nonTZlimtime = starttime;
|
nonTZlimtime = starttime;
|
||||||
nonTZlimtype = type;
|
nonTZlimtype = type;
|
||||||
}
|
}
|
||||||
@@ -3769,6 +3780,7 @@ static int
|
|||||||
addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut)
|
addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut)
|
||||||
{
|
{
|
||||||
register int i, j;
|
register int i, j;
|
||||||
|
int charcnt0;
|
||||||
|
|
||||||
/* RFC 9636 section 3.2 specifies this range for utoff. */
|
/* RFC 9636 section 3.2 specifies this range for utoff. */
|
||||||
if (! (-TWO_31_MINUS_1 <= utoff && utoff <= TWO_31_MINUS_1)) {
|
if (! (-TWO_31_MINUS_1 <= utoff && utoff <= TWO_31_MINUS_1)) {
|
||||||
@@ -3778,12 +3790,18 @@ addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut)
|
|||||||
if (!want_bloat())
|
if (!want_bloat())
|
||||||
ttisstd = ttisut = false;
|
ttisstd = ttisut = false;
|
||||||
|
|
||||||
for (j = 0; j < charcnt; ++j)
|
checkabbr(abbr);
|
||||||
if (strcmp(&chars[j], abbr) == 0)
|
|
||||||
break;
|
charcnt0 = charcnt;
|
||||||
if (j == charcnt)
|
j = addabbr(chars, &charcnt, abbr);
|
||||||
newabbr(abbr);
|
if (charcnt0 < charcnt) {
|
||||||
else {
|
/* If an abbreviation was inserted, increment indexes no
|
||||||
|
earlier than the insert by the size of the insertion,
|
||||||
|
so that they continue to point to the same contents. */
|
||||||
|
for (i = 0; i < typecnt; i++)
|
||||||
|
if (j <= desigidx[i])
|
||||||
|
desigidx[i] += charcnt - charcnt0;
|
||||||
|
} else {
|
||||||
/* If there's already an entry, return its index. */
|
/* If there's already an entry, return its index. */
|
||||||
for (i = 0; i < typecnt; i++)
|
for (i = 0; i < typecnt; i++)
|
||||||
if (utoff == utoffs[i] && isdst == isdsts[i] && j == desigidx[i]
|
if (utoff == utoffs[i] && isdst == isdsts[i] && j == desigidx[i]
|
||||||
@@ -4168,10 +4186,8 @@ will not work with pre-2004 versions of zic"));
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
newabbr(const char *string)
|
checkabbr(char const *string)
|
||||||
{
|
{
|
||||||
register int i;
|
|
||||||
|
|
||||||
if (strcmp(string, GRANDPARENTED) != 0) {
|
if (strcmp(string, GRANDPARENTED) != 0) {
|
||||||
register const char * cp;
|
register const char * cp;
|
||||||
const char * mp;
|
const char * mp;
|
||||||
@@ -4190,13 +4206,50 @@ mp = _("time zone abbreviation differs from POSIX standard");
|
|||||||
if (mp != NULL)
|
if (mp != NULL)
|
||||||
warning("%s (%s)", mp, string);
|
warning("%s (%s)", mp, string);
|
||||||
}
|
}
|
||||||
i = strnlen(string, TZ_MAX_CHARS - charcnt) + 1;
|
}
|
||||||
if (charcnt + i > TZ_MAX_CHARS) {
|
|
||||||
error(_("too many, or too long, time zone abbreviations"));
|
/* Put into CHS, which currently contains *PNCHS bytes containing
|
||||||
exit(EXIT_FAILURE);
|
NUL-terminated abbreviations none of which are suffixes of another,
|
||||||
}
|
the abbreviation ABBR including its trailing NUL.
|
||||||
strcpy(&chars[charcnt], string);
|
If ABBR does not already appear in CHS,
|
||||||
charcnt += i;
|
possibly as a suffix of an existing abbreviation,
|
||||||
|
add ABBR to CHS, remove from CHS any abbreviation
|
||||||
|
that is a suffix of ABBR, and increment *PNCHS accordingly.
|
||||||
|
Return the index of ABBR after any modifications to CHS are made.
|
||||||
|
|
||||||
|
If all abbreviations have already been added, this function
|
||||||
|
lets the caller look up the index of an existing abbreviation. */
|
||||||
|
static int
|
||||||
|
addabbr(char chs[TZ_MAX_CHARS], int *pnchs, char const *abbr)
|
||||||
|
{
|
||||||
|
int nchs = *pnchs;
|
||||||
|
int alen = strlen(abbr), nchs_incr = alen + 1;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < nchs; ) {
|
||||||
|
int clen = strlen(&chs[i]);
|
||||||
|
if (alen <= clen) {
|
||||||
|
/* If ABBR is a suffix of an abbreviation in CHS,
|
||||||
|
return the index of ABBR in CHS. */
|
||||||
|
int isuff = i + (clen - alen);
|
||||||
|
if (memcmp(&chs[isuff], abbr, alen) == 0)
|
||||||
|
return isuff;
|
||||||
|
} else if (memcmp(&chs[i], &abbr[alen - clen], clen) == 0) {
|
||||||
|
/* An abbreviation in CHS is a substring of ABBR.
|
||||||
|
Replace it with ABBR, instead of the more-common
|
||||||
|
actions of appending ABBR or doing nothing. */
|
||||||
|
nchs_incr = alen - clen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i += clen + 1;
|
||||||
|
}
|
||||||
|
if (TZ_MAX_CHARS < nchs + nchs_incr) {
|
||||||
|
error(_("too many, or too long, time zone abbreviations"));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
memmove(&chs[i + nchs_incr], &chs[i], nchs - i);
|
||||||
|
memcpy(&chs[i], abbr, nchs_incr);
|
||||||
|
*pnchs = nchs + nchs_incr;
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure that the directories of ARGNAME exist, by making any missing
|
/* Ensure that the directories of ARGNAME exist, by making any missing
|
||||||
|
|||||||
Reference in New Issue
Block a user