Module Name: src Committed By: christos Date: Tue Mar 22 17:48:39 UTC 2022
Modified Files: src/lib/libc/time: CONTRIBUTING Makefile NEWS localtime.c private.h theory.html tz-link.html tzselect.8 tzselect.ksh version zdump.c zic.c Log Message: welcome to tzcode-2022a Changes to code Fix bug when mktime gets confused by truncated TZif files with unspecified local time. (Problem reported by Almaz Mingaleev.) Fix bug when 32-bit time_t code reads malformed 64-bit TZif data. (Problem reported by Christos Zoulas.) When reading a version 2 or later TZif file, the TZif reader now validates the version 1 header and data block only enough to skip over them, as recommended by RFC 8536 section 4. Also, the TZif reader no longer mistakenly attempts to parse a version 1 TZIf file header as a TZ string. zdump -v now outputs "(localtime failed)" and "(gmtime failed)" when local time and UT cannot be determined for a timestamp. To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/lib/libc/time/CONTRIBUTING cvs rdiff -u -r1.49 -r1.50 src/lib/libc/time/Makefile cvs rdiff -u -r1.34 -r1.35 src/lib/libc/time/NEWS cvs rdiff -u -r1.126 -r1.127 src/lib/libc/time/localtime.c cvs rdiff -u -r1.57 -r1.58 src/lib/libc/time/private.h cvs rdiff -u -r1.12 -r1.13 src/lib/libc/time/theory.html cvs rdiff -u -r1.10 -r1.11 src/lib/libc/time/tz-link.html cvs rdiff -u -r1.9 -r1.10 src/lib/libc/time/tzselect.8 cvs rdiff -u -r1.18 -r1.19 src/lib/libc/time/tzselect.ksh cvs rdiff -u -r1.17 -r1.18 src/lib/libc/time/version cvs rdiff -u -r1.55 -r1.56 src/lib/libc/time/zdump.c cvs rdiff -u -r1.80 -r1.81 src/lib/libc/time/zic.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/time/CONTRIBUTING diff -u src/lib/libc/time/CONTRIBUTING:1.6 src/lib/libc/time/CONTRIBUTING:1.7 --- src/lib/libc/time/CONTRIBUTING:1.6 Fri Oct 22 10:26:04 2021 +++ src/lib/libc/time/CONTRIBUTING Tue Mar 22 13:48:39 2022 @@ -1,53 +1,58 @@ -Contributing to the tz code and data +# Contributing to the tz code and data + +Please do not create issues or pull requests on GitHub, as the +proper procedure for proposing and distributing patches is via +email as described below. The time zone database is by no means authoritative: governments change timekeeping rules erratically and sometimes with little warning, the data entries do not cover all of civil time before 1970, and undoubtedly errors remain in the code and data. Feel free to fill gaps or fix mistakes, and please email improvements -to t...@iana.org for use in the future. In your email, please give +to <t...@iana.org> for use in the future. In your email, please give reliable sources that reviewers can check. ------ - -Developers can contribute technical changes to the source code and -data as follows. +## Contributing technical changes To email small changes, please run a POSIX shell command like 'diff -u old/europe new/europe >myfix.patch', and attach -myfix.patch to the email. +'myfix.patch' to the email. For more-elaborate or possibly-controversial changes, such as renaming, adding or removing zones, please read -<https://www.iana.org/time-zones/repository/theory.html> or the file -theory.html. It is also good to browse the mailing list archives +"Theory and pragmatics of the tz code and data" +<https://www.iana.org/time-zones/repository/theory.html>. +It is also good to browse the mailing list archives <https://mm.icann.org/pipermail/tz/> for examples of patches that tend to work well. Additions to data should contain commentary citing -reliable sources as justification. Citations should use https: URLs +reliable sources as justification. Citations should use "https:" URLs if available. For changes that fix sensitive security-related bugs, please see the -file SECURITY. +distribution's 'SECURITY' file. -Please submit changes against either the latest release in +Please submit changes against either the latest release <https://www.iana.org/time-zones> or the main branch of the development -repository. The latter is preferred. If you use Git the following -workflow may be helpful: +repository. The latter is preferred. + +## Sample Git workflow for developing contributions + +If you use Git the following workflow may be helpful: * Copy the development repository. - git clone https://github.com/eggert/tz.git - cd tz + git clone https://github.com/eggert/tz.git + cd tz * Get current with the main branch. - git checkout main - git pull + git checkout main + git pull * Switch to a new branch for the changes. Choose a different branch name for each change set. - git checkout -b mybranch + git checkout -b mybranch * Sleuth by using 'git blame'. For example, when fixing data for Africa/Sao_Tome, if the command 'git blame africa' outputs a line @@ -60,32 +65,33 @@ workflow may be helpful: * Debug the changes, e.g.: - make check - make install - ./zdump -v America/Los_Angeles + make check + make install + ./zdump -v America/Los_Angeles * For each separable change, commit it in the new branch, e.g.: - git add northamerica - git commit + git add northamerica + git commit See recent 'git log' output for the commit-message style. - * Create patch files 0001-*, 0002-*, ... + * Create patch files 0001-..., 0002-..., ... - git format-patch main + git format-patch main - * After reviewing the patch files, send the patches to t...@iana.org + * After reviewing the patch files, send the patches to <t...@iana.org> for others to review. - git send-email main + git send-email main For an archived example of such an email, see + "[PROPOSED] Fix off-by-1 error for Jamaica and T&C before 1913" <https://mm.icann.org/pipermail/tz/2018-February/026122.html>. * Start anew by getting current with the main branch again (the second step above). -Please do not create issues or pull requests on GitHub, as the -proper procedure for proposing and distributing patches is via -email as illustrated above. +----- + +This file is in the public domain. Index: src/lib/libc/time/Makefile diff -u src/lib/libc/time/Makefile:1.49 src/lib/libc/time/Makefile:1.50 --- src/lib/libc/time/Makefile:1.49 Fri Oct 22 10:26:04 2021 +++ src/lib/libc/time/Makefile Tue Mar 22 13:48:39 2022 @@ -399,9 +399,10 @@ ZFLAGS= ZIC_INSTALL= $(ZIC) -d '$(DESTDIR)$(TZDIR)' $(LEAPSECONDS) # The name of a Posix-compliant 'awk' on your system. -# Older 'mawk' versions, such as the 'mawk' in Ubuntu 16.04, might dump core; -# on Ubuntu you can work around this with -# AWK= gawk +# mawk 1.3.3 and Solaris 10 /usr/bin/awk do not work. +# Also, it is better (though not essential) if 'awk' supports UTF-8, +# and unfortunately mawk and busybox awk do not support UTF-8. +# Try AWK=gawk or AWK=nawk if your awk has the abovementioned problems. AWK= awk # The full path name of a Posix-compliant shell, preferably one that supports @@ -466,7 +467,9 @@ OK_LINE= '^'$(OK_CHAR)'*$$' # Flags to give 'tar' when making a distribution. # Try to use flags appropriate for GNU tar. -GNUTARFLAGS= --numeric-owner --owner=0 --group=0 --mode=go+u,go-w --sort=name +GNUTARFLAGS= --format=pax --pax-option='delete=atime,delete=ctime' \ + --numeric-owner --owner=0 --group=0 \ + --mode=go+u,go-w --sort=name TARFLAGS= `if tar $(GNUTARFLAGS) --version >/dev/null 2>&1; \ then echo $(GNUTARFLAGS); \ else :; \ @@ -742,7 +745,7 @@ date: $(DATEOBJS) tzselect: tzselect.ksh version VERSION=`cat version` && sed \ -e 's|#!/bin/bash|#!$(KSHELL)|g' \ - -e 's|AWK=[^}]*|AWK=$(AWK)|g' \ + -e 's|AWK=[^}]*|AWK='\''$(AWK)'\''|g' \ -e 's|\(PKGVERSION\)=.*|\1='\''($(PACKAGE)) '\''|' \ -e 's|\(REPORT_BUGS_TO\)=.*|\1=$(BUGEMAIL)|' \ -e 's|TZDIR=[^}]*|TZDIR=$(TZDIR)|' \ Index: src/lib/libc/time/NEWS diff -u src/lib/libc/time/NEWS:1.34 src/lib/libc/time/NEWS:1.35 --- src/lib/libc/time/NEWS:1.34 Fri Oct 22 10:26:04 2021 +++ src/lib/libc/time/NEWS Tue Mar 22 13:48:39 2022 @@ -1,5 +1,65 @@ News for the tz database +Release 2022a - 2022-03-15 23:02:01 -0700 + + Briefly: + Palestine will spring forward on 2022-03-27, not -03-26. + zdump -v now outputs better failure indications. + Bug fixes for code that reads corrupted TZif data. + + Changes to future timestamps + + Palestine will spring forward on 2022-03-27, not 2022-03-26. + (Thanks to Heba Hamad.) Predict future transitions for first + Sunday >= March 25. Additionally, predict fallbacks to be the first + Friday on or after October 23, not October's last Friday, to be more + consistent with recent practice. The first differing fallback + prediction is on 2025-10-24, not 2025-10-31. + + Changes to past timestamps + + From 1992 through spring 1996, Ukraine's DST transitions were at + 02:00 standard time, not at 01:00 UTC. (Thanks to Alois Treindl.) + + Chile's Santiago Mean Time and its LMT precursor have been adjusted + eastward by 1 second to align with past and present law. + + Changes to commentary + + Add several references for Chile's 1946/1947 transitions, some of + which only affected portions of the country. + + Changes to code + + Fix bug when mktime gets confused by truncated TZif files with + unspecified local time. (Problem reported by Almaz Mingaleev.) + + Fix bug when 32-bit time_t code reads malformed 64-bit TZif data. + (Problem reported by Christos Zoulas.) + + When reading a version 2 or later TZif file, the TZif reader now + validates the version 1 header and data block only enough to skip + over them, as recommended by RFC 8536 section 4. Also, the TZif + reader no longer mistakenly attempts to parse a version 1 TZIf + file header as a TZ string. + + zdump -v now outputs "(localtime failed)" and "(gmtime failed)" + when local time and UT cannot be determined for a timestamp. + + Changes to build procedure + + Distribution tarballs now use standard POSIX.1-1988 ustar format + instead of GNU format. Although the formats are almost identical + for these tarballs, ustar headers' magic fields contain "ustar" + instead of "ustar ", and their version fields contain "00" instead + of " ". The two formats are planned to diverge more significantly + for tzdb releases after 2242-03-16 12:56:31 UTC, when the ustar + format becomes obsolete and the tarballs switch to pax format, an + extension of ustar. For details about these formats, please see + "pax - portable archive interchange", IEEE Std 1003.1-2017, + <https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13>. + + Release 2021e - 2021-10-21 18:41:00 -0700 Changes to future timestamps Index: src/lib/libc/time/localtime.c diff -u src/lib/libc/time/localtime.c:1.126 src/lib/libc/time/localtime.c:1.127 --- src/lib/libc/time/localtime.c:1.126 Sun Dec 5 13:06:24 2021 +++ src/lib/libc/time/localtime.c Tue Mar 22 13:48:39 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: localtime.c,v 1.126 2021/12/05 18:06:24 christos Exp $ */ +/* $NetBSD: localtime.c,v 1.127 2022/03/22 17:48:39 christos Exp $ */ /* Convert timestamp from time_t to struct tm. */ @@ -12,7 +12,7 @@ #if 0 static char elsieid[] = "@(#)localtime.c 8.17"; #else -__RCSID("$NetBSD: localtime.c,v 1.126 2021/12/05 18:06:24 christos Exp $"); +__RCSID("$NetBSD: localtime.c,v 1.127 2022/03/22 17:48:39 christos Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -115,6 +115,15 @@ struct lsinfo { /* leap second inform #define SMALLEST(a, b) (((a) < (b)) ? (a) : (b)) #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) +/* This abbreviation means local time is unspecified. */ +static char const UNSPEC[] = "-00"; + +/* How many extra bytes are needed at the end of struct state's chars array. + This needs to be at least 1 for null termination in case the input + data isn't properly terminated, and it also needs to be big enough + for ttunspecified to work without crashing. */ +enum { CHARS_EXTRA = BIGGEST(sizeof UNSPEC, 2) - 1 }; + #ifdef TZNAME_MAX #define MY_TZNAME_MAX TZNAME_MAX #endif /* defined TZNAME_MAX */ @@ -133,8 +142,9 @@ struct state { __time_t ats[TZ_MAX_TIMES]; unsigned char types[TZ_MAX_TIMES]; struct ttinfo ttis[TZ_MAX_TYPES]; - char chars[/*CONSTCOND*/BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, - sizeof gmt), (2 * (MY_TZNAME_MAX + 1)))]; + char chars[/*CONSTCOND*/ + BIGGEST(BIGGEST(TZ_MAX_CHARS + CHARS_EXTRA, + sizeof gmt), (2 * (MY_TZNAME_MAX + 1)))]; struct lsinfo lsis[TZ_MAX_LEAPS]; /* The time type to use for early times or if no transitions. @@ -235,6 +245,15 @@ init_ttinfo(struct ttinfo *s, int_fast32 s->tt_ttisut = false; } +/* Return true if SP's time type I does not specify local time. */ +static bool +ttunspecified(struct state const *sp, int i) +{ + char const *abbr = &sp->chars[sp->ttis[i].tt_desigidx]; + /* memcmp is likely faster than strcmp, and is safe due to CHARS_EXTRA. */ + return memcmp(abbr, UNSPEC, sizeof UNSPEC) == 0; +} + static int_fast32_t detzcode(const char *const codep) { @@ -491,35 +510,45 @@ tzloadbody(char const *name, struct stat if (close(fid) < 0) return errno; for (stored = 4; stored <= 8; stored *= 2) { - int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt); - int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt); - int_fast64_t prevtr = -1; - int_fast32_t prevcorr = 0; - int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt); - int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt); - int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt); - int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt); - char const *p = up->buf + tzheadsize; - /* Although tzfile(5) currently requires typecnt to be nonzero, - support future formats that may allow zero typecnt - in files that have a TZ string and no transitions. */ - if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS - && 0 <= typecnt && typecnt < TZ_MAX_TYPES - && 0 <= timecnt && timecnt < TZ_MAX_TIMES - && 0 <= charcnt && charcnt < TZ_MAX_CHARS - && (ttisstdcnt == typecnt || ttisstdcnt == 0) - && (ttisutcnt == typecnt || ttisutcnt == 0))) - return EINVAL; - if ((size_t)nread - < (tzheadsize /* struct tzhead */ - + timecnt * stored /* ats */ + char version = up->tzhead.tzh_version[0]; + bool skip_datablock = stored == 4 && version; + int_fast32_t datablock_size; + int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt); + int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt); + int_fast64_t prevtr = -1; + int_fast32_t prevcorr = 0; + int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt); + int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt); + int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt); + int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt); + char const *p = up->buf + tzheadsize; + /* Although tzfile(5) currently requires typecnt to be nonzero, + support future formats that may allow zero typecnt + in files that have a TZ string and no transitions. */ + if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS + && 0 <= typecnt && typecnt < TZ_MAX_TYPES + && 0 <= timecnt && timecnt < TZ_MAX_TIMES + && 0 <= charcnt && charcnt < TZ_MAX_CHARS + && 0 <= ttisstdcnt && ttisstdcnt < TZ_MAX_TYPES + && 0 <= ttisutcnt && ttisutcnt < TZ_MAX_TYPES)) + return EINVAL; + datablock_size + = (timecnt * stored /* ats */ + timecnt /* types */ + typecnt * 6 /* ttinfos */ + charcnt /* chars */ + leapcnt * (stored + 4) /* lsinfos */ + ttisstdcnt /* ttisstds */ - + ttisutcnt)) /* ttisuts */ + + ttisutcnt); /* ttisuts */ + if (nread < (ssize_t)(tzheadsize + datablock_size)) + return EINVAL; + if (skip_datablock) + p += datablock_size; + else { + if (! ((ttisstdcnt == typecnt || ttisstdcnt == 0) + && (ttisutcnt == typecnt || ttisutcnt == 0))) return EINVAL; + sp->leapcnt = leapcnt; sp->timecnt = timecnt; sp->typecnt = typecnt; @@ -576,7 +605,9 @@ tzloadbody(char const *name, struct stat } for (i = 0; i < sp->charcnt; ++i) sp->chars[i] = *p++; - sp->chars[i] = '\0'; /* ensure '\0' at end */ + /* Ensure '\0'-terminated, and make it safe to call + ttunspecified later. */ + memset(&sp->chars[i], 0, CHARS_EXTRA); /* Read leap seconds, discarding those out of time_t range. */ leapcnt = 0; @@ -590,6 +621,7 @@ tzloadbody(char const *name, struct stat or out of order. */ if (tr <= prevtr) return EINVAL; + /* To avoid other botches in this code, each leap second's correction must differ from the previous one's by 1 second or less, except that the first correction can be @@ -603,6 +635,7 @@ tzloadbody(char const *name, struct stat return EINVAL; prevtr = tr; prevcorr = corr; + if (tr <= TIME_T_MAX) { sp->lsis[leapcnt].ls_trans = (time_t)tr; sp->lsis[leapcnt].ls_corr = corr; @@ -635,13 +668,13 @@ tzloadbody(char const *name, struct stat ttisp->tt_ttisut = *p++; } } - /* - ** If this is an old file, we're done. - */ - if (up->tzhead.tzh_version[0] == '\0') - break; nread -= p - up->buf; memmove(up->buf, p, (size_t)nread); + } + + /* If this is an old file, we're done. */ + if (!version) + break; } if (doextend && nread > 2 && up->buf[0] == '\n' && up->buf[nread - 1] == '\n' && @@ -745,13 +778,13 @@ tzloadbody(char const *name, struct stat standard-time type. See: https://mm.icann.org/pipermail/tz/2013-May/019368.html */ /* - ** If type 0 is unused in transitions, + ** If type 0 does not specify local time, or is unused in transitions, ** it's the type to use for early times. */ for (i = 0; i < sp->timecnt; ++i) if (sp->types[i] == 0) break; - i = i < sp->timecnt ? -1 : 0; + i = i < sp->timecnt && ! ttunspecified(sp, 0) ? -1 : 0; /* ** Absent the above, ** if there are transition times @@ -2179,6 +2212,8 @@ again: if (sp->ttis[j].tt_isdst == sp->ttis[i].tt_isdst) continue; + if (ttunspecified(sp, j)) + continue; off = sp->ttis[j].tt_utoff - sp->ttis[i].tt_utoff; yourtm.tm_sec += off < 0 ? @@ -2347,7 +2382,7 @@ time1(struct tm *const tmp, seen[i] = false; nseen = 0; for (i = sp->timecnt - 1; i >= 0; --i) - if (!seen[sp->types[i]]) { + if (!seen[sp->types[i]] && !ttunspecified(sp, sp->types[i])) { seen[sp->types[i]] = true; types[nseen++] = sp->types[i]; } Index: src/lib/libc/time/private.h diff -u src/lib/libc/time/private.h:1.57 src/lib/libc/time/private.h:1.58 --- src/lib/libc/time/private.h:1.57 Fri Oct 22 10:26:04 2021 +++ src/lib/libc/time/private.h Tue Mar 22 13:48:39 2022 @@ -1,6 +1,6 @@ /* Private header for tzdb code. */ -/* $NetBSD: private.h,v 1.57 2021/10/22 14:26:04 christos Exp $ */ +/* $NetBSD: private.h,v 1.58 2022/03/22 17:48:39 christos Exp $ */ #ifndef PRIVATE_H #define PRIVATE_H @@ -712,6 +712,12 @@ time_t time2posix_z(timezone_t __restric # define INITIALIZE(x) #endif +/* Whether memory access must strictly follow the C standard. + If 0, it's OK to read uninitialized storage so long as the value is + not relied upon. Defining it to 0 lets mktime access parts of + struct tm that might be uninitialized, as a heuristic when the + standard doesn't say what to return and when tm_gmtoff can help + mktime likely infer a better value. */ #ifndef UNINIT_TRAP # define UNINIT_TRAP 0 #endif Index: src/lib/libc/time/theory.html diff -u src/lib/libc/time/theory.html:1.12 src/lib/libc/time/theory.html:1.13 --- src/lib/libc/time/theory.html:1.12 Fri Oct 22 10:26:04 2021 +++ src/lib/libc/time/theory.html Tue Mar 22 13:48:39 2022 @@ -296,7 +296,7 @@ in decreasing order of importance: </li> <li> If a name is changed, put its old spelling in the - '<code>backward</code>' file. + '<code>backward</code>' file as a link to the new spelling. This means old spellings will continue to work. Ordinarily a name change should occur only in the rare case when a location's consensus English-language spelling changes; for example, @@ -348,22 +348,37 @@ timestamps correctly and it increased ma </ul> <p> -The file '<code>zone1970.tab</code>' lists geographical locations used +The file <code>zone1970.tab</code> lists geographical locations used to name timezones. It is intended to be an exhaustive list of names for geographic regions as described above; this is a subset of the timezones in the data. -Although a '<code>zone1970.tab</code>' location's +Although a <code>zone1970.tab</code> location's <a href="https://en.wikipedia.org/wiki/Longitude">longitude</a> corresponds to its <a href="https://en.wikipedia.org/wiki/Local_mean_time">local mean time (<abbr>LMT</abbr>)</a> offset with one hour for every 15° east longitude, this relationship is not exact. +The backward-compatibility file <code>zone.tab</code> is similar +but conforms to the older-version guidelines related to <abbr>ISO</abbr> 3166-1; +it lists only one country code per entry and unlike <code>zone1970.tab</code> +it can list names defined in <code>backward</code>. </p> <p> -Excluding '<code>backward</code>' should not affect the other data. -If '<code>backward</code>' is excluded, excluding -'<code>etcetera</code>' should not affect the remaining data. +The database defines each timezone name to be a zone, or a link to a zone. +The source file <code>backward</code> defines links for backward +compatibility; it does not define zones. +Although <code>backward</code> was originally designed to be optional, +nowadays distributions typically use it +and no great weight should be attached to whether a link +is defined in <code>backward</code> or in some other file. +The source file <code>etcetera</code> defines names that may be useful +on platforms that do not support POSIX-style <code>TZ</code> strings; +no other source file other than <code>backward</code> +contains links to its zones. +One of <code>etcetera</code>'s names is <code>GMT</code>, +used by functions like <code>gmtime</code> to obtain leap +second information on platforms that support leap seconds. </p> </section> Index: src/lib/libc/time/tz-link.html diff -u src/lib/libc/time/tz-link.html:1.10 src/lib/libc/time/tz-link.html:1.11 --- src/lib/libc/time/tz-link.html:1.10 Fri Oct 22 10:26:04 2021 +++ src/lib/libc/time/tz-link.html Tue Mar 22 13:48:39 2022 @@ -89,7 +89,6 @@ title="Berkeley Software Distribution">B title="Web Operating System">webOS</abbr></a>, <a href="https://en.wikipedia.org/wiki/IBM_AIX"><abbr title="Advanced Interactive eXecutive">AIX</abbr></a>, -<a href="https://en.wikipedia.org/wiki/BlackBerry_10">BlackBerry 10</a>, <a href="https://www.apple.com/ios"><abbr title="iPhone OS">iOS</abbr></a>, <a href="https://www.apple.com/macos">macOS</a>, @@ -243,18 +242,18 @@ the process by tailoring the generic ins the <code><abbr>tz</abbr> README</code> file and installing the latest data yourself. System-specific instructions for installing the latest <code><abbr>tz</abbr></code> data have also been published -for <a href="https://www.ibm.com/developerworks/aix/library/au-aix-olson-time-zone/index.html"><abbr>AIX</abbr></a>, +for <a href="https://developer.ibm.com/articles/au-aix-olson-time-zone/"><abbr>AIX</abbr></a>, <a href="https://source.android.com/devices/tech/config/timezone-rules">Android</a>, <a -href="http://userguide.icu-project.org/datetime/timezone"><abbr +href="https://unicode-org.github.io/icu/userguide/datetime/timezone/"><abbr title="International Components for Unicode">ICU</abbr></a>, -<a href="https://developer.ibm.com/javasdk/support/dst/jtzu/"><abbr>IBM</abbr> +<a href="https://www.ibm.com/support/pages/java-sdk-time-zone-update-utility"><abbr>IBM</abbr> JDK</a>, <a href="https://www.joda.org/joda-time/tz_update.html">Joda-Time</a>, <a href="https://dev.mysql.com/doc/refman/en/time-zone-support.html">MySQL</a>, <a href="https://nodatime.org/userguide/tzdb">Noda Time</a>, and <a -href="https://www.oracle.com/java/technologies/javase/tzupdater-readme.html#usage">OpenJDK/Oracle JDK</a>. +href="https://www.oracle.com/java/technologies/javase/tzupdater-readme.html">OpenJDK/Oracle JDK</a>. </p> <p>Sources for the <code><abbr>tz</abbr></code> database are <a href="https://en.wikipedia.org/wiki/UTF-8"><abbr @@ -488,11 +487,6 @@ many of which also support runtimes lack href="https://github.com/formatjs/date-time-format-timezone"><samp>Intl.DateTimeFormat</samp> timezone polyfill</a> is freely available under a <abbr>BSD</abbr>-style license.</li> -<li><a -href="https://github.com/kshetline/compact-time-zone-generator">CompactTimeZoneGenerator</a> -compiles time zone data into a compact form designed for -JavaScript. It is freely available under a combination of -the <abbr>MIT</abbr> license and the Apache License.</li> <li>The <a href="https://date-fns.org/">date-fns</a> library manipulates timezone-aware timestamps in browsers and in <a href="https://nodejs.org/en/">Node.js</a>. @@ -546,9 +540,9 @@ It is freely available under a <abbr>BSD Definitions for Python</a> compiles <code><abbr>tz</abbr></code> source into <a href="https://www.python.org">Python</a>. It is freely available under a <abbr>BSD</abbr>-style license. -In code that can assume Python 3.9 or later it is superseded by -<a href="#python-zoneinfo"><code>zoneinfo.ZoneInfo</code></a> -and the <a href="#pypi-tzdata"><code>tzdata</code> Python package</a>.</li> +In code that can assume Python 3.6 or later it is largely superseded; see <a +href="https://blog.ganssle.io/articles/2018/03/pytz-fastest-footgun.html">pytz: +The Fastest Footgun in the West</a>.</li> <li><a href="https://tzinfo.github.io">TZInfo – Ruby Timezone Library</a> compiles <code><abbr>tz</abbr></code> source into @@ -610,11 +604,11 @@ is a <abbr>TZif</abbr> file reader writt It is freely available under the same terms as Perl (dual <abbr>GPL</abbr> and Artistic license).</li> <li>Python has a <a id="python-zoneinfo" -href="https://docs.python.org/3.9/library/zoneinfo.html"><code>zoneinfo.ZoneInfo</code> +href="https://docs.python.org/3/library/zoneinfo.html"><code>zoneinfo.ZoneInfo</code> class</a> that reads <abbr>TZif</abbr> data and creates objects that represent <code><abbr>tzdb</abbr></code> timezones. Python is freely available under the -<a href="https://docs.python.org/3.9/license.html">Python Software Foundation +<a href="https://docs.python.org/3/license.html">Python Software Foundation License</a>. A companion <a id="pypi-tzdata" href="https://pypi.org/">PyPI</a> module <a href="https://pypi.org/project/tzdata/"><code>tzdata</code></a> @@ -641,7 +635,7 @@ available under a <abbr>BSD</abbr>-style <li><a href="https://foxclocks.org">FoxClocks</a> is an extension for <a href="https://www.google.com/chrome/">Google Chrome</a> and for <a -href="https://developer.mozilla.org/en-US/docs/Mozilla/Tech/Toolkit_API">Mozilla +href="https://wiki.mozilla.org/Modules/Toolkit">Mozilla Toolkit</a> applications like <a href="https://www.mozilla.org/en-US/firefox/new/">Firefox</a> and <a href="https://www.mozilla.org/en-US/thunderbird/">Thunderbird</a>. @@ -873,7 +867,7 @@ href="https://nrc.canada.ca/en/certifica zones and daylight saving time</a>.</dd> <dt>Chile</dt> <dd>The Hydrographic and Oceanographic Service of the Chilean Navy publishes a -<a href="https://www.horaoficial.cl/historia_hora.html" hreflang="es">history of +<a href="https://www.horaoficial.cl/historia_hora.php" hreflang="es">history of Chile's official time (in Spanish)</a>.</dd> <dt>China</dt> <dd>The Hong Kong Observatory maintains a @@ -1010,14 +1004,11 @@ specifies a <a href="https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol"><abbr>DHCP</abbr></a> option for a server to configure a client's time zone and daylight saving settings automatically.</li> -<li><a -href="https://www.cv.nrao.edu/~rfisher/Ephemerides/times.html">Astronomical -Times</a> explains more abstruse astronomical time scales like +<li><a href="https://www.ucolick.org/~sla/leapsecs/timescales.html">Time +Scales</a> describes astronomical time scales like <abbr title="Terrestrial Dynamic Time">TDT</abbr>, <abbr title="Geocentric Coordinate Time">TCG</abbr>, and <abbr title="Barycentric Dynamic Time">TDB</abbr>. -<a href="https://www.ucolick.org/~sla/leapsecs/timescales.html">Time -Scales</a> goes into more detail, particularly for historical variants.</li> <li>The <a href="https://www.iau.org"><abbr title="International Astronomical Union">IAU</abbr></a>'s <a href="http://www.iausofa.org"><abbr Index: src/lib/libc/time/tzselect.8 diff -u src/lib/libc/time/tzselect.8:1.9 src/lib/libc/time/tzselect.8:1.10 --- src/lib/libc/time/tzselect.8:1.9 Fri Oct 9 14:38:48 2020 +++ src/lib/libc/time/tzselect.8 Tue Mar 22 13:48:39 2022 @@ -1,11 +1,11 @@ -.\" $NetBSD: tzselect.8,v 1.9 2020/10/09 18:38:48 christos Exp $ +.\" $NetBSD: tzselect.8,v 1.10 2022/03/22 17:48:39 christos Exp $ .\" .TH TZSELECT 8 .SH NAME tzselect \- select a timezone .SH SYNOPSIS .ie \n(.g .ds - \f(CW-\fP -.el ds - \- +.el .ds - \- .B tzselect [ .B \*-c Index: src/lib/libc/time/tzselect.ksh diff -u src/lib/libc/time/tzselect.ksh:1.18 src/lib/libc/time/tzselect.ksh:1.19 --- src/lib/libc/time/tzselect.ksh:1.18 Fri Oct 19 19:05:35 2018 +++ src/lib/libc/time/tzselect.ksh Tue Mar 22 13:48:39 2022 @@ -3,7 +3,7 @@ # Ask the user about the time zone, and output the resulting TZ value to stdout. # Interact with the user via stderr and stdin. # -# $NetBSD: tzselect.ksh,v 1.18 2018/10/19 23:05:35 christos Exp $ +# $NetBSD: tzselect.ksh,v 1.19 2022/03/22 17:48:39 christos Exp $ # PKGVERSION='(tzcode) ' TZVERSION=see_Makefile @@ -21,11 +21,13 @@ REPORT_BUGS_TO=t...@iana.org # # Bash <https://www.gnu.org/software/bash/> # Korn Shell <http://www.kornshell.com/> -# MirBSD Korn Shell <https://www.mirbsd.org/mksh.htm> +# MirBSD Korn Shell <http://www.mirbsd.org/mksh.htm> # -# For portability to Solaris 9 /bin/sh this script avoids some POSIX -# features and common extensions, such as $(...) (which works sometimes -# but not others), $((...)), and $10. +# For portability to Solaris 10 /bin/sh (supported by Oracle through +# January 2024) this script avoids some POSIX features and common +# extensions, such as $(...) (which works sometimes but not others), +# $((...)), ! CMD, ${#ID}, ${ID##PAT}, ${ID%%PAT}, and $10. + # # This script also uses several features of modern awk programs. # If your host lacks awk, or has an old awk that does not conform to Posix, @@ -104,14 +106,6 @@ then esac done || exit } - - # Work around a bug in bash 1.14.7 and earlier, where $PS3 is sent to stdout. - case $BASH_VERSION in - [01].*) - case `echo 1 | (select x in x; do break; done) 2>/dev/null` in - ?*) PS3= - esac - esac ' else doselect() { @@ -188,7 +182,7 @@ done # If the current locale does not support UTF-8, convert data to current # locale's format if possible, as the shell aligns columns better that way. # Check the UTF-8 of U+12345 CUNEIFORM SIGN URU TIMES KI. -! $AWK 'BEGIN { u12345 = "\360\222\215\205"; exit length(u12345) != 1 }' && +$AWK 'BEGIN { u12345 = "\360\222\215\205"; exit length(u12345) != 1 }' || { { tmp=`(mktemp -d) 2>/dev/null` || { tmp=${TMPDIR-/tmp}/tzselect.$$ && (umask 77 && mkdir -- "$tmp") @@ -199,6 +193,7 @@ done TZ_COUNTRY_TABLE=$tmp/iso3166.tab && iconv -f UTF-8 -t //TRANSLIT <"$TZ_ZONE_TABLE" >$tmp/$zonetabtype.tab && TZ_ZONE_TABLE=$tmp/$zonetabtype.tab +} newline=' ' Index: src/lib/libc/time/version diff -u src/lib/libc/time/version:1.17 src/lib/libc/time/version:1.18 --- src/lib/libc/time/version:1.17 Fri Oct 22 10:26:04 2021 +++ src/lib/libc/time/version Tue Mar 22 13:48:39 2022 @@ -1 +1 @@ -2021e +2022a Index: src/lib/libc/time/zdump.c diff -u src/lib/libc/time/zdump.c:1.55 src/lib/libc/time/zdump.c:1.56 --- src/lib/libc/time/zdump.c:1.55 Fri Oct 22 12:57:14 2021 +++ src/lib/libc/time/zdump.c Tue Mar 22 13:48:39 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: zdump.c,v 1.55 2021/10/22 16:57:14 ryoon Exp $ */ +/* $NetBSD: zdump.c,v 1.56 2022/03/22 17:48:39 christos Exp $ */ /* Dump time zone data in a textual format. */ /* @@ -8,7 +8,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: zdump.c,v 1.55 2021/10/22 16:57:14 ryoon Exp $"); +__RCSID("$NetBSD: zdump.c,v 1.56 2022/03/22 17:48:39 christos Exp $"); #endif /* !defined lint */ #ifndef NETBSD_INSPIRED @@ -61,6 +61,21 @@ __RCSID("$NetBSD: zdump.c,v 1.55 2021/10 */ enum { SECSPER400YEARS_FITS = SECSPERLYEAR <= INTMAX_MAX / 400 }; +#if !defined HAVE_GENERIC && defined __has_extension +# if __has_extension(c_generic_selections) +# define HAVE_GENERIC 1 +# else +# define HAVE_GENERIC 0 +# endif +#endif +/* _Generic is buggy in pre-4.9 GCC. */ +#if !defined HAVE_GENERIC && defined __GNUC__ +# define HAVE_GENERIC (4 < __GNUC__ + (9 <= __GNUC_MINOR__)) +#endif +#ifndef HAVE_GENERIC +# define HAVE_GENERIC (201112 <= __STDC_VERSION__) +#endif + #if HAVE_GETTEXT #include <locale.h> /* for setlocale */ #endif /* HAVE_GETTEXT */ @@ -136,7 +151,7 @@ sumsize(size_t a, size_t b) { size_t sum = a + b; if (sum < a) - errx(EXIT_FAILURE, "size overflow"); + errx(EXIT_FAILURE, _("size overflow")); return sum; } @@ -799,6 +814,7 @@ show(timezone_t tz, char *zone, time_t t gmtmp = my_gmtime_r(&t, &gmtm); if (gmtmp == NULL) { printf(tformat(), t); + printf(_(" (gmtime failed)")); } else { dumptime(gmtmp); (void) printf(" UT"); @@ -806,8 +822,11 @@ show(timezone_t tz, char *zone, time_t t (void) printf(" = "); } tmp = my_localtime_rz(tz, &t, &tm); - dumptime(tmp); - if (tmp != NULL) { + if (tmp == NULL) { + printf(tformat(), t); + printf(_(" (localtime failed)")); + } else { + dumptime(tmp); if (*abbr(tmp) != '\0') (void) printf(" %s", abbr(tmp)); if (v) { @@ -1120,12 +1139,29 @@ abbr(struct tm const *tmp) /* ** The code below can fail on certain theoretical systems; -** it works on all known real-world systems as of 2004-12-30. +** it works on all known real-world systems as of 2022-01-25. */ static const char * tformat(void) { +#if HAVE_GENERIC + /* C11-style _Generic is more likely to return the correct + format when distinct types have the same size. */ + char const *fmt = + _Generic(+ (time_t) 0, + int: "%d", long: "%ld", long long: "%lld", + unsigned: "%u", unsigned long: "%lu", + unsigned long long: "%llu", + default: NULL); + if (fmt) + return fmt; + fmt = _Generic((time_t) 0, + intmax_t: "%"PRIdMAX, uintmax_t: "%"PRIuMAX, + default: NULL); + if (fmt) + return fmt; +#endif if (0 > (time_t) -1) { /* signed */ if (sizeof(time_t) == sizeof(intmax_t)) return "%"PRIdMAX; @@ -1159,10 +1195,6 @@ dumptime(const struct tm *timeptr) int lead; int trail; - if (timeptr == NULL) { - printf("NULL"); - return; - } /* ** The packaged localtime_rz and gmtime_r never put out-of-range ** values in tm_wday or tm_mon, but since this code might be compiled Index: src/lib/libc/time/zic.c diff -u src/lib/libc/time/zic.c:1.80 src/lib/libc/time/zic.c:1.81 --- src/lib/libc/time/zic.c:1.80 Sat Jan 1 16:01:21 2022 +++ src/lib/libc/time/zic.c Tue Mar 22 13:48:39 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: zic.c,v 1.80 2022/01/01 21:01:21 christos Exp $ */ +/* $NetBSD: zic.c,v 1.81 2022/03/22 17:48:39 christos Exp $ */ /* ** This file is in the public domain, so clarified as of ** 2006-07-17 by Arthur David Olson. @@ -11,7 +11,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: zic.c,v 1.80 2022/01/01 21:01:21 christos Exp $"); +__RCSID("$NetBSD: zic.c,v 1.81 2022/03/22 17:48:39 christos Exp $"); #endif /* !defined lint */ /* Use the system 'time' function, instead of any private replacement. @@ -1001,9 +1001,10 @@ random_dirent(char const **name, char ** char const *src = *name; char *dst = *namealloc; static char const prefix[] = ".zic"; - static char const alphabet[] = ("abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"); + static char const alphabet[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; enum { prefixlen = sizeof prefix - 1, alphabetlen = sizeof alphabet - 1 }; int suffixlen = 6; char const *lastslash = strrchr(src, '/'); @@ -3585,9 +3586,11 @@ mkdirs(char const *argname, bool ancesto if (mkdir(name, MKDIR_UMASK) != 0) { /* Do not report an error if err == EEXIST, because some other process might have made the directory - in the meantime. */ + in the meantime. Likewise for ENOSYS, because + Solaris 10 mkdir fails with ENOSYS if the + directory is an automounted mount point. */ int err = errno; - if (err != EEXIST) { + if (err != EEXIST && err != ENOSYS) { error(_("%s: Can't create directory %s: %s"), progname, name, strerror(err)); exit(EXIT_FAILURE);