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&deg;
 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 &ndash;
 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);

Reply via email to