Module Name:    src
Committed By:   christos
Date:           Thu Oct 23 18:45:58 UTC 2014

Modified Files:
        src/lib/libc/time: Makefile NEWS asctime.c localtime.c private.h
            tz-art.htm tz-link.htm tzset.3 zdump.8 zdump.c

Log Message:
merge 2014i


To generate a diff of this commit:
cvs rdiff -u -r1.23 -r1.24 src/lib/libc/time/Makefile
cvs rdiff -u -r1.6 -r1.7 src/lib/libc/time/NEWS
cvs rdiff -u -r1.19 -r1.20 src/lib/libc/time/asctime.c
cvs rdiff -u -r1.90 -r1.91 src/lib/libc/time/localtime.c
cvs rdiff -u -r1.37 -r1.38 src/lib/libc/time/private.h
cvs rdiff -u -r1.7 -r1.8 src/lib/libc/time/tz-art.htm
cvs rdiff -u -r1.18 -r1.19 src/lib/libc/time/tz-link.htm
cvs rdiff -u -r1.30 -r1.31 src/lib/libc/time/tzset.3
cvs rdiff -u -r1.13 -r1.14 src/lib/libc/time/zdump.8
cvs rdiff -u -r1.38 -r1.39 src/lib/libc/time/zdump.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/Makefile
diff -u src/lib/libc/time/Makefile:1.23 src/lib/libc/time/Makefile:1.24
--- src/lib/libc/time/Makefile:1.23	Tue Oct  7 17:51:03 2014
+++ src/lib/libc/time/Makefile	Thu Oct 23 14:45:58 2014
@@ -5,7 +5,7 @@
 PACKAGE=	tzcode
 
 # Version numbers of the code and data distributions.
-VERSION=	2014h
+VERSION=	2014i
 
 # Email address for bug reports.
 BUGEMAIL=	t...@iana.org
@@ -129,6 +129,7 @@ LDLIBS=
 #  -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU=1
 #	if you do not want run time warnings about formats that may cause
 #	year 2000 grief
+#  -Dssize_t=long on ancient hosts that lack ssize_t
 #  -DTHREAD_SAFE=1 to make localtime.c thread-safe, as POSIX requires;
 #	not needed by the main-program tz code, which is single-threaded.
 #	Append other compiler flags as needed, e.g., -pthread on GNU/Linux.

Index: src/lib/libc/time/NEWS
diff -u src/lib/libc/time/NEWS:1.6 src/lib/libc/time/NEWS:1.7
--- src/lib/libc/time/NEWS:1.6	Tue Oct  7 17:51:03 2014
+++ src/lib/libc/time/NEWS	Thu Oct 23 14:45:58 2014
@@ -1,5 +1,71 @@
 News for the tz database
 
+Release 2014i - 2014-10-21 22:04:57 -0700
+
+  Changes affecting future time stamps
+
+    Pacific/Fiji will observe DST from 2014-11-02 02:00 to 2015-01-18 03:00.
+    (Thanks to Ken Rylander for the heads-up.)  Guess that future
+    years will use a similar pattern.
+
+    A new Zone Pacific/Bougainville, for the part of Papua New Guinea
+    that plans to switch from UTC+10 to UTC+11 on 2014-12-28 at 02:00.
+    (Thanks to Kiley Walbom for the heads-up.)
+
+  Changes affecting time zone abbreviations
+
+    Since Belarus is not changing its clocks even though Moscow is,
+    the time zone abbreviation in Europe/Minsk is changing from FET
+    to its more-traditional value MSK on 2014-10-26 at 01:00.
+    (Thanks to Alexander Bokovoy for the heads-up about Belarus.)
+
+    The new abbreviation IDT stands for the pre-1976 use of UT+8 in
+    Indochina, to distinguish it better from ICT (UT+7).
+
+  Changes affecting past time stamps
+
+    Many time stamps have been corrected for Asia/Ho_Chi_Minh before 1976
+    (thanks to Trần Ngọc Quân for an indirect pointer to Trần Tiến Bình's
+    authoritative book).  Asia/Ho_Chi_Minh has been added to
+    zone1970.tab, to give tzselect users in Vietnam two choices,
+    since north and south Vietnam disagreed after our 1970 cutoff.
+
+    Asia/Phnom_Penh and Asia/Vientiane have been turned into links, as
+    they differed from existing zones only for older time stamps.  As
+    usual, these changes affect pre-1970 time stamps only.  Their old
+    contents have been moved to the 'backzone' file.
+
+  Changes affecting code
+
+    The time-related library functions now set errno on failure, and
+    some crashes in the new tzalloc-related library functions have
+    been fixed.  (Thanks to Christos Zoulas for reporting most of
+    these problems and for suggesting fixes.)
+
+    If USG_COMPAT is defined and the requested time stamp is standard time,
+    the tz library's localtime and mktime functions now set the extern
+    variable timezone to a value appropriate for that time stamp; and
+    similarly for ALTZONE, daylight saving time, and the altzone variable.
+    This change is a companion to the tzname change in 2014h, and is
+    designed to make timezone and altzone more compatible with tzname.
+
+    The tz library's functions now set errno to EOVERFLOW if they fail
+    because the result cannot be represented.  ctime and ctime_r now
+    return NULL and set errno when a time stamp is out of range, rather
+    than having undefined behavior.
+
+    Some bugs associated with the new 2014g functions have been fixed.
+    This includes a bug that largely incapacitated the new functions
+    time2posix_z and posix2time_z.  (Thanks to Christos Zoulas.)
+    It also includes some uses of uninitialized variables after tzalloc.
+    The new code uses the standard type 'ssize_t', which the Makefile
+    now gives porting advice about.
+
+  Changes affecting commentary
+
+    Updated URLs for NRC Canada (thanks to Matt Johnson and Brian Inglis).
+
+
 Release 2014h - 2014-09-25 18:59:03 -0700
 
   Changes affecting past time stamps

Index: src/lib/libc/time/asctime.c
diff -u src/lib/libc/time/asctime.c:1.19 src/lib/libc/time/asctime.c:1.20
--- src/lib/libc/time/asctime.c:1.19	Fri Aug 15 07:04:07 2014
+++ src/lib/libc/time/asctime.c	Thu Oct 23 14:45:58 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: asctime.c,v 1.19 2014/08/15 11:04:07 christos Exp $	*/
+/*	$NetBSD: asctime.c,v 1.20 2014/10/23 18:45:58 christos Exp $	*/
 
 /*
 ** This file is in the public domain, so clarified as of
@@ -16,7 +16,7 @@
 #if 0
 static char	elsieid[] = "@(#)asctime.c	8.5";
 #else
-__RCSID("$NetBSD: asctime.c,v 1.19 2014/08/15 11:04:07 christos Exp $");
+__RCSID("$NetBSD: asctime.c,v 1.20 2014/10/23 18:45:58 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -126,11 +126,7 @@ asctime_r(const struct tm *timeptr, char
 	if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime)
 		return strcpy(buf, result);
 	else {
-#ifdef EOVERFLOW
 		errno = EOVERFLOW;
-#else /* !defined EOVERFLOW */
-		errno = EINVAL;
-#endif /* !defined EOVERFLOW */
 		return NULL;
 	}
 }

Index: src/lib/libc/time/localtime.c
diff -u src/lib/libc/time/localtime.c:1.90 src/lib/libc/time/localtime.c:1.91
--- src/lib/libc/time/localtime.c:1.90	Thu Oct 16 13:53:32 2014
+++ src/lib/libc/time/localtime.c	Thu Oct 23 14:45:58 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: localtime.c,v 1.90 2014/10/16 17:53:32 christos Exp $	*/
+/*	$NetBSD: localtime.c,v 1.91 2014/10/23 18:45:58 christos Exp $	*/
 
 /*
 ** This file is in the public domain, so clarified as of
@@ -10,7 +10,7 @@
 #if 0
 static char	elsieid[] = "@(#)localtime.c	8.17";
 #else
-__RCSID("$NetBSD: localtime.c,v 1.90 2014/10/16 17:53:32 christos Exp $");
+__RCSID("$NetBSD: localtime.c,v 1.91 2014/10/23 18:45:58 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -216,6 +216,17 @@ extern long		timezone __RENAME(__timezon
 long			altzone = 0;
 #endif /* defined ALTZONE */
 
+/* Initialize *S to a value based on GMTOFF, ISDST, and ABBRIND.  */
+static void
+init_ttinfo(struct ttinfo *s, int_fast32_t gmtoff, bool isdst, int abbrind)
+{
+	s->tt_gmtoff = gmtoff;
+	s->tt_isdst = isdst;
+	s->tt_abbrind = abbrind;
+	s->tt_ttisstd = false;
+	s->tt_ttisgmt = false;
+}
+
 static int_fast32_t
 detzcode(const char *const codep)
 {
@@ -327,61 +338,63 @@ differ_by_repeat(const time_t t1, const 
 	return (int_fast64_t)t1 - (int_fast64_t)t0 == SECSPERREPEAT;
 }
 
-static bool
-tzload(const char *name, timezone_t sp, bool doextend)
+union input_buffer {
+	/* The first part of the buffer, interpreted as a header.  */
+	struct tzhead tzhead;
+
+	/* The entire buffer.  */
+	char buf[2 * sizeof(struct tzhead) + 2 * sizeof (struct state)
+	  + 4 * TZ_MAX_TIMES];
+};
+
+/* Local storage needed for 'tzloadbody'.  */
+union local_storage {
+	/* The file name to be opened.  */
+	char fullname[FILENAME_MAX + 1];
+
+	/* The results of analyzing the file's contents after it is opened.  */
+	struct {
+		/* The input buffer.  */
+		union input_buffer u;
+
+		/* A temporary state used for parsing a TZ string in the file.  */
+		struct state st;
+	} u;
+};
+
+/* Load tz data from the file named NAME into *SP.  Read extended
+   format if DOEXTEND.  Use *LSP for temporary storage.  Return 0 on
+   success, an errno value on failure.  */
+static int
+tzloadbody(char const *name, struct state *sp, bool doextend,
+  union local_storage *lsp)
 {
-	const char *		p;
 	int			i;
 	int			fid;
 	int			stored;
 	ssize_t			nread;
-	typedef union {
-		struct tzhead	tzhead;
-		char		buf[2 * sizeof(struct tzhead) +
-					2 * sizeof *sp +
-					4 * TZ_MAX_TIMES];
-	} u_t;
-	union local_storage {
-		/*
-		** Section 4.9.1 of the C standard says that
-		** "FILENAME_MAX expands to an integral constant expression
-		** that is the size needed for an array of char large enough
-		** to hold the longest file name string that the implementation
-		** guarantees can be opened."
-		*/
-		char		fullname[FILENAME_MAX + 1];
-
-		/* The main part of the storage for this function.  */
-		struct {
-			u_t u;
-			struct state st;
-		} u;
-	};
-	char *fullname;
-	u_t *up;
-	bool doaccess;
-	union local_storage *lsp;
-	lsp = malloc(sizeof *lsp);
-	if (!lsp)
-		return false;
-	fullname = lsp->fullname;
-	up = &lsp->u.u;
+	bool			doaccess;
+	char			*fullname = lsp->fullname;
+	union input_buffer	*up = &lsp->u.u;
+	size_t			tzheadsize = sizeof(struct tzhead);
 
 	sp->goback = sp->goahead = false;
 
 	if (! name) {
 		name = TZDEFAULT;
 		if (! name)
-			goto oops;
+			return EINVAL;
 	}
 
 	if (name[0] == ':')
 		++name;
 	doaccess = name[0] == '/';
 	if (!doaccess) {
-		p = TZDIR;
-		if (! p || sizeof lsp->fullname - 1 <= strlen(p) + strlen(name))
-			goto oops;
+		char const *p = TZDIR;
+		if (! p)
+			return EINVAL;
+		if (sizeof lsp->fullname - 1 <= strlen(p) + strlen(name))
+			return ENAMETOOLONG;
 		strcpy(fullname, p);
 		strcat(fullname, "/");
 		strcat(fullname, name);
@@ -391,14 +404,19 @@ tzload(const char *name, timezone_t sp, 
 		name = fullname;
 	}
 	if (doaccess && access(name, R_OK) != 0)
-		goto oops;
+		return errno;
 
 	fid = open(name, OPEN_MODE);
 	if (fid < 0)
-		goto oops;
+		return errno;
 	nread = read(fid, up->buf, sizeof up->buf);
-	if (close(fid) < 0 || nread <= 0)
-		goto oops;
+	if (nread < (ssize_t)tzheadsize) {
+		int err = nread < 0 ? errno : EINVAL;
+		close(fid);
+		return err;
+	}
+	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 ttisgmtcnt = detzcode(up->tzhead.tzh_ttisgmtcnt);
@@ -406,23 +424,24 @@ tzload(const char *name, timezone_t sp, 
 		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);
-		p = up->tzhead.tzh_charcnt + sizeof up->tzhead.tzh_charcnt;
+		char const *p = up->buf + tzheadsize;
 		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)
 		       && (ttisgmtcnt == typecnt || ttisgmtcnt == 0)))
-				goto oops;
-		if (nread - (p - up->buf)
-		    < (timecnt * stored		/* ats */
+		  return EINVAL;
+		if ((size_t)nread
+		    < (tzheadsize		/* struct tzhead */
+		       + timecnt * stored	/* ats */
 		       + timecnt		/* types */
 		       + typecnt * 6		/* ttinfos */
 		       + charcnt		/* chars */
 		       + leapcnt * (stored + 4)	/* lsinfos */
 		       + ttisstdcnt		/* ttisstds */
 		       + ttisgmtcnt))		/* ttisgmts */
-				goto oops;
+		  return EINVAL;
 		sp->leapcnt = leapcnt;
 		sp->timecnt = timecnt;
 		sp->typecnt = typecnt;
@@ -443,7 +462,7 @@ tzload(const char *name, timezone_t sp, 
 				    ? time_t_min : (time_t)at);
 				if (timecnt && attime <= sp->ats[timecnt - 1]) {
 					if (attime < sp->ats[timecnt - 1])
-						goto oops;
+						return EINVAL;
 					sp->types[i - 1] = 0;
 					timecnt--;
 				}
@@ -456,7 +475,7 @@ tzload(const char *name, timezone_t sp, 
 		for (i = 0; i < sp->timecnt; ++i) {
 			unsigned char typ = *p++;
 			if (sp->typecnt <= typ)
-				goto oops;
+			  return EINVAL;
 			if (sp->types[i])
 				sp->types[timecnt++] = typ;
 		}
@@ -470,11 +489,11 @@ tzload(const char *name, timezone_t sp, 
 			p += 4;
 			isdst = *p++;
 			if (! (isdst < 2))
-				goto oops;
+				return EINVAL;
 			ttisp->tt_isdst = isdst;
 			abbrind = *p++;
 			if (! (abbrind < sp->charcnt))
-				goto oops;
+				return EINVAL;
 			ttisp->tt_abbrind = abbrind;
 		}
 		for (i = 0; i < sp->charcnt; ++i)
@@ -496,7 +515,7 @@ tzload(const char *name, timezone_t sp, 
 				    sp->lsis[leapcnt - 1].ls_trans) {
 					if (trans <
 					    sp->lsis[leapcnt - 1].ls_trans)
-						goto oops;
+						return EINVAL;
 					leapcnt--;
 				}
 				sp->lsis[leapcnt].ls_trans = trans;
@@ -514,7 +533,7 @@ tzload(const char *name, timezone_t sp, 
 				ttisp->tt_ttisstd = false;
 			else {
 				if (*p != true && *p != false)
-						goto oops;
+				  return EINVAL;
 				ttisp->tt_ttisstd = *p++;
 			}
 		}
@@ -526,7 +545,7 @@ tzload(const char *name, timezone_t sp, 
 				ttisp->tt_ttisgmt = false;
 			else {
 				if (*p != true && *p != false)
-						goto oops;
+						return EINVAL;
 				ttisp->tt_ttisgmt = *p++;
 			}
 		}
@@ -536,8 +555,7 @@ tzload(const char *name, timezone_t sp, 
 		if (up->tzhead.tzh_version[0] == '\0')
 			break;
 		nread -= p - up->buf;
-		for (i = 0; i < nread; ++i)
-			up->buf[i] = p[i];
+		memmove(up->buf, p, (size_t)nread);
 		/*
 		** If this is a signed narrow time_t system, we're done.
 		*/
@@ -628,11 +646,22 @@ tzload(const char *name, timezone_t sp, 
 			}
 	}
 	sp->defaulttype = i;
-	free(up);
-	return true;
-oops:
-	free(up);
-	return false;
+	return 0;
+}
+
+/* Load tz data from the file named NAME into *SP.  Read extended
+   format if DOEXTEND.  Return 0 on success, an errno value on failure.  */
+static int
+tzload(char const *name, struct state *sp, bool doextend)
+{
+	union local_storage *lsp = malloc(sizeof *lsp);
+	if (!lsp)
+		return errno;
+	else {
+		int err = tzloadbody(name, sp, doextend, lsp);
+		free(lsp);
+		return err;
+	}
 }
 
 static bool
@@ -991,7 +1020,7 @@ tzparse(const char *name, timezone_t sp,
 		if (name == NULL)
 			return false;
 	}
-	load_ok = tzload(TZDEFRULES, sp, false);
+	load_ok = tzload(TZDEFRULES, sp, false) == 0;
 	if (!load_ok)
 		sp->leapcnt = 0;		/* so, we're off a little */
 	if (*name != '\0') {
@@ -1035,13 +1064,9 @@ tzparse(const char *name, timezone_t sp,
 			/*
 			** Two transitions per year, from EPOCH_YEAR forward.
 			*/
-			memset(sp->ttis, 0, sizeof(sp->ttis));
-			sp->ttis[0].tt_gmtoff = -dstoffset;
-			sp->ttis[0].tt_isdst = true;
-			sp->ttis[0].tt_abbrind = (int)(stdlen + 1);
-			sp->ttis[1].tt_gmtoff = -stdoffset;
-			sp->ttis[1].tt_isdst = false;
-			sp->ttis[1].tt_abbrind = 0;
+			init_ttinfo(&sp->ttis[0], -dstoffset, true, 
+			    (int)(stdlen + 1));
+			init_ttinfo(&sp->ttis[1], -stdoffset, false, 0);
 			sp->defaulttype = 0;
 			timecnt = 0;
 			janfirst = 0;
@@ -1160,13 +1185,9 @@ tzparse(const char *name, timezone_t sp,
 			/*
 			** Finally, fill in ttis.
 			*/
-			memset(sp->ttis, 0, sizeof(sp->ttis));
-			sp->ttis[0].tt_gmtoff = -stdoffset;
-			sp->ttis[0].tt_isdst = false;
-			sp->ttis[0].tt_abbrind = 0;
-			sp->ttis[1].tt_gmtoff = -dstoffset;
-			sp->ttis[1].tt_isdst = true;
-			sp->ttis[1].tt_abbrind = (int)(stdlen + 1);
+			init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
+			init_ttinfo(&sp->ttis[1], -dstoffset, true,
+			    (int)(stdlen + 1));
 			sp->typecnt = 2;
 			sp->defaulttype = 0;
 		}
@@ -1174,10 +1195,8 @@ tzparse(const char *name, timezone_t sp,
 		dstlen = 0;
 		sp->typecnt = 1;		/* only standard time */
 		sp->timecnt = 0;
-		memset(sp->ttis, 0, sizeof(sp->ttis));
-		sp->ttis[0].tt_gmtoff = -stdoffset;
-		sp->ttis[0].tt_isdst = false;
-		sp->ttis[0].tt_abbrind = 0;
+		init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
+		init_ttinfo(&sp->ttis[1], 0, false, 0);
 		sp->defaulttype = 0;
 	}
 	sp->charcnt = (int)(stdlen + 1);
@@ -1199,54 +1218,53 @@ tzparse(const char *name, timezone_t sp,
 static void
 gmtload(struct state *const sp)
 {
-	if (! tzload(gmt, sp, true))
+	if (tzload(gmt, sp, true) != 0)
 		(void) tzparse(gmt, sp, true);
 }
 
-static struct state *
+static int
 zoneinit(struct state *sp, char const *name)
 {
-	if (!sp)
-		return NULL;
 	if (name && ! name[0]) {
-		/*	
-		 ** User wants it fast rather than right.
-		 */
-		sp->leapcnt = 0;	/* so, we're off a little */
+		/*
+		** User wants it fast rather than right.
+		*/
+		sp->leapcnt = 0;		/* so, we're off a little */
 		sp->timecnt = 0;
 		sp->typecnt = 0;
-		sp->ttis[0].tt_isdst = 0;
-		sp->ttis[0].tt_gmtoff = 0;
-		sp->ttis[0].tt_abbrind = 0;
+		sp->charcnt = 0;
+		sp->goback = sp->goahead = false;
+		init_ttinfo(&sp->ttis[0], 0, false, 0);
 		strcpy(sp->chars, gmt);
-		return sp;
+		sp->defaulttype = 0;
+		return 0;
+	} else {
+		int err = tzload(name, sp, true);
+		if (err != 0 && name && name[0] != ':' &&
+		    tzparse(name, sp, false))
+			return 0;
+		return err;
 	}
-	if (! (tzload(name, sp, true)
-	    || (name && name[0] != ':' && tzparse(name, sp, false))))
-		return NULL;
-	return sp;
 }
  
 static void
 tzsetlcl(char const *name)
 {
+	struct state *sp = lclptr;
 	int lcl = name ? strlen(name) < sizeof lcl_TZname : -1;
 	if (lcl < 0 ? lcl_is_set < 0
 	    : 0 < lcl_is_set && strcmp(lcl_TZname, name) == 0)
 		return;
 
-	if (!lclptr && !(lclptr = malloc(sizeof *lclptr)))
-		return;
-
-	if (!zoneinit(lclptr, name)) {
-		free(lclptr);
-		lclptr = NULL;
-		return;
+	if (! sp)
+		lclptr = sp = malloc(sizeof *lclptr);
+	if (sp) {
+		if (zoneinit(sp, name) != 0)
+			zoneinit(sp, "");
+		if (0 < lcl)
+			strcpy(lcl_TZname, name);
 	}
-
 	settzname();
-	if (0 < lcl)
-		(void)strcpy(lcl_TZname, name);
 	lcl_is_set = lcl;
 }
 
@@ -1294,10 +1312,15 @@ timezone_t
 tzalloc(const char *name)
 {
 	timezone_t sp = malloc(sizeof *sp);
-	timezone_t tp = sp ? zoneinit(sp, name) : sp;
-	if (!tp)
-		free(sp);
-	return tp;
+	if (sp) {
+		int err = zoneinit(sp, name);
+		if (err != 0) {
+			free(sp);
+			errno = err;
+			return NULL;
+		}
+	}
+	return sp;
 }
 
 void
@@ -1324,7 +1347,10 @@ tzfree(timezone_t sp)
 ** freely called. (And no, the PANS doesn't require the above behavior,
 ** but it *is* desirable.)
 **
-** If OFFSET is nonzero, set tzname if successful.
+** If successful and OFFSET is nonzero,
+** set the applicable parts of tzname, timezone and altzone;
+** however, it's OK to omit this step if the time zone is POSIX-compatible,
+** since in that case tzset should have already done this step correctly.
 ** OFFSET's type is intfast32_t for compatibility with gmtsub.
 */
 
@@ -1339,10 +1365,8 @@ localsub(struct state const *sp, time_t 
 	const time_t			t = *timep;
 
 	if (sp == NULL) {
-		result = gmtsub(gmtptr, timep, 0, tmp);
-		if (result && offset)
-			tzname[0] = gmtptr ? gmtptr->chars : __UNCONST(gmt);
-		return result;
+		/* Don't bother to set tzname etc.; tzset has already done it.  */
+		return gmtsub(gmtptr, timep, 0, tmp);
 	}
 	if ((sp->goback && t < sp->ats[0]) ||
 		(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
@@ -1404,13 +1428,23 @@ localsub(struct state const *sp, time_t 
 	*/
 	result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
 	if (result) {
-		result->tm_isdst = ttisp->tt_isdst;
-		if (offset)
-			tzname[result->tm_isdst] =
-			    __UNCONST(&sp->chars[ttisp->tt_abbrind]);
-#ifdef TM_ZONE
-		result->TM_ZONE = __UNCONST(&sp->chars[ttisp->tt_abbrind]);
-#endif /* defined TM_ZONE */
+		bool tm_isdst = ttisp->tt_isdst;
+		char *tm_zone = __UNCONST(&sp->chars[ttisp->tt_abbrind]);
+		result->tm_isdst = tm_isdst;
+		if (offset) {
+		    /* Always set the tzname etc. vars whose values can easily
+		       be determined, as it's too much trouble to tell whether
+	    	       tzset has already done it correctly.  */
+			tzname[tm_isdst] = tm_zone;
+#ifdef USG_COMPAT
+			if (!tm_isdst)
+				timezone = - ttisp->tt_gmtoff;
+#endif
+#ifdef ALTZONE
+			if (tm_isdst)
+				altzone = - ttisp->tt_gmtoff;
+#endif
+		}
 	}
 	return result;
 }
@@ -1568,14 +1602,14 @@ timesub(time_t const *timep, int_fast32_
 		tdelta = tdays / DAYSPERLYEAR;
 		if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
 		       && tdelta <= INT_MAX))
-		       goto overflow;
+			goto out_of_range;
 		_DIAGASSERT(__type_fit(int, tdelta));
 		idelta = (int)tdelta;
 		if (idelta == 0)
 			idelta = (tdays < 0) ? -1 : 1;
 		newy = y;
 		if (increment_overflow(&newy, idelta))
-			goto overflow;
+			goto out_of_range;
 		leapdays = leaps_thru_end_of(newy - 1) -
 			leaps_thru_end_of(y - 1);
 		tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
@@ -1604,17 +1638,17 @@ timesub(time_t const *timep, int_fast32_
 	}
 	while (idays < 0) {
 		if (increment_overflow(&y, -1))
-			goto overflow;
+			goto out_of_range;
 		idays += year_lengths[isleap(y)];
 	}
 	while (idays >= year_lengths[isleap(y)]) {
 		idays -= year_lengths[isleap(y)];
 		if (increment_overflow(&y, 1))
-			goto overflow;
+			goto out_of_range;
 	}
 	tmp->tm_year = y;
 	if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
-		goto overflow;
+		goto out_of_range;
 	tmp->tm_yday = idays;
 	/*
 	** The "extra" mods below avoid overflow problems.
@@ -1645,7 +1679,7 @@ timesub(time_t const *timep, int_fast32_
 	tmp->TM_GMTOFF = offset;
 #endif /* defined TM_GMTOFF */
 	return tmp;
-overflow:
+out_of_range:
 	errno = EOVERFLOW;
 	return NULL;
 }
@@ -1659,21 +1693,16 @@ ctime(const time_t *const timep)
 **	to local time in the form of a string. It is equivalent to
 **		asctime(localtime(timer))
 */
-	struct tm *rtm = localtime(timep);
-	if (rtm == NULL)
-		return NULL;
-	return asctime(rtm);
+	struct tm *tmp = localtime(timep);
+	return tmp ? asctime(tmp) : NULL;
 }
 
 char *
 ctime_r(const time_t *const timep, char *buf)
 {
-	struct tm	mytm, *rtm;
-
-	rtm = localtime_r(timep, &mytm);
-	if (rtm == NULL)
-		return NULL;
-	return asctime_r(rtm, buf);
+	struct tm mytm;
+	struct tm *tmp = localtime_r(timep, &mytm);
+	return tmp ? asctime_r(tmp, buf) : NULL;
 }
 
 char *
@@ -1820,24 +1849,24 @@ again:
 	if (do_norm_secs) {
 		if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
 		    SECSPERMIN))
-			goto overflow;
+			goto out_of_range;
 	}
 	if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
-		goto overflow;
+		goto out_of_range;
 	if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
-		goto overflow;
+		goto out_of_range;
 	y = yourtm.tm_year;
 	if (normalize_overflow32(&y, &yourtm.tm_mon, MONSPERYEAR))
-		goto overflow;
+		goto out_of_range;
 	/*
 	** Turn y into an actual year number for now.
 	** It is converted back to an offset from TM_YEAR_BASE later.
 	*/
 	if (increment_overflow32(&y, TM_YEAR_BASE))
-		goto overflow;
+		goto out_of_range;
 	while (yourtm.tm_mday <= 0) {
 		if (increment_overflow32(&y, -1))
-			goto overflow;
+			goto out_of_range;
 		li = y + (1 < yourtm.tm_mon);
 		yourtm.tm_mday += year_lengths[isleap(li)];
 	}
@@ -1845,7 +1874,7 @@ again:
 		li = y + (1 < yourtm.tm_mon);
 		yourtm.tm_mday -= year_lengths[isleap(li)];
 		if (increment_overflow32(&y, 1))
-			goto overflow;
+			goto out_of_range;
 	}
 	for ( ; ; ) {
 		i = mon_lengths[isleap(y)][yourtm.tm_mon];
@@ -1855,13 +1884,13 @@ again:
 		if (++yourtm.tm_mon >= MONSPERYEAR) {
 			yourtm.tm_mon = 0;
 			if (increment_overflow32(&y, 1))
-				goto overflow;
+				goto out_of_range;
 		}
 	}
 	if (increment_overflow32(&y, -TM_YEAR_BASE))
-		goto overflow;
+		goto out_of_range;
 	if (! (INT_MIN <= y && y <= INT_MAX))
-		goto overflow;
+		goto out_of_range;
 	yourtm.tm_year = (int)y;
 	if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
 		saved_seconds = 0;
@@ -1875,7 +1904,7 @@ again:
 		** which is a safer assumption than using 58 would be.
 		*/
 		if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
-			goto overflow;
+			goto out_of_range;
 		saved_seconds = yourtm.tm_sec;
 		yourtm.tm_sec = SECSPERMIN - 1;
 	} else {
@@ -1915,12 +1944,12 @@ again:
 		if (dir != 0) {
 			if (t == lo) {
 				if (t == time_t_max)
-					goto overflow;
+					goto out_of_range;
 				++t;
 				++lo;
 			} else if (t == hi) {
 				if (t == time_t_min)
-					goto overflow;
+					goto out_of_range;
 				--t;
 				--hi;
 			}
@@ -2015,13 +2044,13 @@ again:
 label:
 	newt = t + saved_seconds;
 	if ((newt < t) != (saved_seconds < 0))
-		goto overflow;
+		goto out_of_range;
 	t = newt;
 	if (funcp(sp, &t, offset, tmp)) {
 		*okayp = true;
 		return t;
 	}
-overflow:
+out_of_range:
 	errno = EOVERFLOW;
 	return WRONG;
 invalid:

Index: src/lib/libc/time/private.h
diff -u src/lib/libc/time/private.h:1.37 src/lib/libc/time/private.h:1.38
--- src/lib/libc/time/private.h:1.37	Tue Oct  7 18:20:33 2014
+++ src/lib/libc/time/private.h	Thu Oct 23 14:45:58 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: private.h,v 1.37 2014/10/07 22:20:33 christos Exp $	*/
+/*	$NetBSD: private.h,v 1.38 2014/10/23 18:45:58 christos Exp $	*/
 
 #ifndef PRIVATE_H
 #define PRIVATE_H
@@ -117,11 +117,19 @@
 
 #include "sys/types.h"	/* for time_t */
 #include "stdio.h"
-#include "errno.h"
 #include "string.h"
 #include "limits.h"	/* for CHAR_BIT et al. */
 #include "stdlib.h"
 
+#include "errno.h"
+
+#ifndef ENAMETOOLONG
+# define ENAMETOOLONG EINVAL
+#endif
+#ifndef EOVERFLOW
+# define EOVERFLOW EINVAL
+#endif
+
 #if HAVE_GETTEXT
 #include "libintl.h"
 #endif /* HAVE_GETTEXT */

Index: src/lib/libc/time/tz-art.htm
diff -u src/lib/libc/time/tz-art.htm:1.7 src/lib/libc/time/tz-art.htm:1.8
--- src/lib/libc/time/tz-art.htm:1.7	Tue Oct  7 17:51:03 2014
+++ src/lib/libc/time/tz-art.htm	Thu Oct 23 14:45:58 2014
@@ -216,7 +216,7 @@ Supernaw.</td></tr>
 <tr><td>&nbsp;</td></tr>
 
 <tr><td>Artist</td><td>Bob Dylan</td></tr>
-<tr><td>CD</td><td>The Time They Are A-Changin'</td></tr>
+<tr><td>CD</td><td>The Times They Are a-Changin'</td></tr>
 <tr><td>Copyright Date</td><td>1964</td></tr>
 <tr><td>Label</td><td>Columbia</td></tr>
 <tr><td>ID</td><td>CK-8905</td></tr>
@@ -291,6 +291,14 @@ An on-line English-language translation 
 <a href="http://www.literature.org/Works/Jules-Verne/eighty";>http://www.literature.org/Works/Jules-Verne/eighty</a></td></tr>
 
 <tr><td>&nbsp;</td></tr>
+<tr><td>Artist</td><td>Nick Enright</td></tr>
+<tr><td>Play</td><td><em>Daylight Saving</em></td></tr>
+<tr><td>Copyright Date</td><td>1989</td></tr>
+<tr><td>Notes</td><td>
+A fast-paced comedy about love and loneliness as the clocks turn back.
+</td></tr>
+
+<tr><td>&nbsp;</td></tr>
 <tr><td>Artist</td><td>Umberto Eco</td></tr>
 <tr><td>Book</td><td><em>The Island of the Day Before</em>
 (<em>L'isola del giorno prima</em>)</td></tr>

Index: src/lib/libc/time/tz-link.htm
diff -u src/lib/libc/time/tz-link.htm:1.18 src/lib/libc/time/tz-link.htm:1.19
--- src/lib/libc/time/tz-link.htm:1.18	Tue Oct  7 17:51:03 2014
+++ src/lib/libc/time/tz-link.htm	Thu Oct 23 14:45:58 2014
@@ -8,7 +8,7 @@
 <meta http-equiv="Content-type" content='text/html; charset="UTF-8"'>
 <meta name="DC.Creator" content="Eggert, Paul">
 <meta name="DC.Contributor" content="Olson, Arthur David">
-<meta name="DC.Date" content="2014-09-23">
+<meta name="DC.Date" content="2014-10-21">
 <meta name="DC.Description"
  content="Sources of information about time zones and daylight saving time">
 <meta name="DC.Identifier"
@@ -429,7 +429,7 @@ time zone history atlases published in b
 href="http://astrocom.com/astrology-products/software/acs-atlas-software";>computer</a>
 and book form (<a
 href="http://www.astrocom.com/astrology/books/american-atlas";>one volume
-for the U.S.</a>, and <a
+for the <abbr>US</abbr></a>, and <a
 href="http://www.astrocom.com/astrology/books/international-atlas";>one for
 other locations</a>) by <a
 href="http://astrocom.com/";>Astro Computing Services</a>.</li>
@@ -496,10 +496,6 @@ href="http://manifold.net/info/freestuff
 Manifold System Users</a> includes a Manifold-format map of
 world time zone boundaries distributed under the
 <abbr>GPL</abbr>.</li>
-<li>The <abbr>US</abbr> Geological Survey's National Atlas of
-the United States
-publishes the <a href="http://nationalatlas.gov/mld/timeznp.html";>Time
-Zones of the United States</a> in the public domain.</li>
 <li>The GeoCommunity lists several commercial sources for <a
 href="http://spatialnews.geocomm.com/features/timezones/";>International
 Time Zones and Time Zone Data</a>.</li>
@@ -744,8 +740,8 @@ database contains English abbreviations 
 many cases these are merely inventions of the database
 maintainers.</li>
 <li>Numeric time zone abbreviations typically count hours east of
-<abbr>UTC</abbr>, e.g., <code>+09</code> for Japan and
-<code>-10</code> for Hawaii. However, the <abbr>POSIX</abbr>
+<abbr>UTC</abbr>, e.g., +09 for Japan and
+&minus;10 for Hawaii. However, the <abbr>POSIX</abbr>
 <code><abbr>TZ</abbr></code> environment variable uses the opposite convention.
 For example, one might use <code><abbr>TZ</abbr>="<abbr
 title="Japan Standard Time">JST</abbr>-9"</code> and

Index: src/lib/libc/time/tzset.3
diff -u src/lib/libc/time/tzset.3:1.30 src/lib/libc/time/tzset.3:1.31
--- src/lib/libc/time/tzset.3:1.30	Tue Oct  7 17:51:03 2014
+++ src/lib/libc/time/tzset.3	Thu Oct 23 14:45:58 2014
@@ -1,5 +1,5 @@
-.\"	$NetBSD: tzset.3,v 1.30 2014/10/07 21:51:03 christos Exp $
-.Dd August 15, 2014
+.\"	$NetBSD: tzset.3,v 1.31 2014/10/23 18:45:58 christos Exp $
+.Dd October 23, 2014
 .Dt TZSET 3
 .Os
 .Sh NAME
@@ -315,10 +315,9 @@ extensions to POSIX.
 .It EST5
 stands for US Eastern Standard
 Time (EST), 5 hours behind UTC, without daylight saving.
-.It FJT\-12FJST,M10.3.1/146,M1.3.4/75
+.It FJT\-12FJST,M11.1.0,M1.3.4/75
 stands for Fiji Time (FJT) and Fiji Summer Time (FJST), 12 hours ahead
-of UTC, springing forward on October's third Monday at
-146:00 (i.e., 02:00 on the first Sunday on or after October 21), and
+of UTC, springing forward on November's first Sunday at 02:00, and
 falling back on January's third Thursday at 75:00 (i.e., 03:00 on the
 first Sunday on or after January 18).
 .It IST\-2IDT,M3.4.4/26,M10.5.0

Index: src/lib/libc/time/zdump.8
diff -u src/lib/libc/time/zdump.8:1.13 src/lib/libc/time/zdump.8:1.14
--- src/lib/libc/time/zdump.8:1.13	Tue Oct  7 17:51:03 2014
+++ src/lib/libc/time/zdump.8	Thu Oct 23 14:45:58 2014
@@ -1,5 +1,5 @@
-.\"	$NetBSD: zdump.8,v 1.13 2014/10/07 21:51:03 christos Exp $
-.Dd October 6, 2014
+.\"	$NetBSD: zdump.8,v 1.14 2014/10/23 18:45:58 christos Exp $
+.Dd October 23, 2014
 .Dt ZDUMP 8
 .Os
 .Sh NAME
@@ -54,7 +54,7 @@ Cutoff times are computed using the prol
 and with Universal Time (UT) ignoring leap seconds.
 The lower bound is exclusive and the upper is inclusive; for example, a
 .Dl loyear
-of 1970 excludes a transition occurring at the very start of 1970 but a
+of 1970 excludes a transition occurring at 1970-01-01 00:00:00 UTC but a
 .Dl hiyear
 of 1970 includes the transition.
 The default cutoff is

Index: src/lib/libc/time/zdump.c
diff -u src/lib/libc/time/zdump.c:1.38 src/lib/libc/time/zdump.c:1.39
--- src/lib/libc/time/zdump.c:1.38	Wed Oct  8 09:13:34 2014
+++ src/lib/libc/time/zdump.c	Thu Oct 23 14:45:58 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: zdump.c,v 1.38 2014/10/08 13:13:34 martin Exp $	*/
+/*	$NetBSD: zdump.c,v 1.39 2014/10/23 18:45:58 christos Exp $	*/
 /*
 ** This file is in the public domain, so clarified as of
 ** 2009-05-17 by Arthur David Olson.
@@ -6,7 +6,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: zdump.c,v 1.38 2014/10/08 13:13:34 martin Exp $");
+__RCSID("$NetBSD: zdump.c,v 1.39 2014/10/23 18:45:58 christos Exp $");
 #endif /* !defined lint */
 
 /*
@@ -860,10 +860,11 @@ delta(struct tm *newp, struct tm *oldp)
 	result += newp->tm_sec - oldp->tm_sec;
 	return result;
 }
+#endif
 
 #ifndef TM_GMTOFF
 /* Return A->tm_yday, adjusted to compare it fairly to B->tm_yday.
-  Assume A and B differ by at most one year.  */
+   Assume A and B differ by at most one year.  */
 static int
 adjusted_yday(struct tm const *a, struct tm const *b)
 {

Reply via email to