Module Name: src Committed By: christos Date: Sun Jun 21 16:06:51 UTC 2015
Modified Files: src/lib/libc/time: Makefile NEWS localtime.c private.h tzselect.ksh zdump.c zic.8 zic.c Log Message: merge tzcode2015e: Changes affecting code When displaying data, tzselect converts it to the current locale's encoding if the iconv command works. (Problem reported by random832.) tzselect no longer mishandles Dominica, fixing a bug introduced in Release 2014f. (Problem reported by Owen Leibman.) zic -l no longer fails when compiled with -DTZDEFAULT=\"/etc/localtime\". This fixes a bug introduced in Release 2014f. (Problem reported by Leonardo Chiquitto.) To generate a diff of this commit: cvs rdiff -u -r1.28 -r1.29 src/lib/libc/time/Makefile cvs rdiff -u -r1.11 -r1.12 src/lib/libc/time/NEWS cvs rdiff -u -r1.94 -r1.95 src/lib/libc/time/localtime.c cvs rdiff -u -r1.40 -r1.41 src/lib/libc/time/private.h \ src/lib/libc/time/zdump.c cvs rdiff -u -r1.13 -r1.14 src/lib/libc/time/tzselect.ksh cvs rdiff -u -r1.24 -r1.25 src/lib/libc/time/zic.8 cvs rdiff -u -r1.53 -r1.54 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/Makefile diff -u src/lib/libc/time/Makefile:1.28 src/lib/libc/time/Makefile:1.29 --- src/lib/libc/time/Makefile:1.28 Tue Apr 28 13:00:24 2015 +++ src/lib/libc/time/Makefile Sun Jun 21 12:06:51 2015 @@ -5,7 +5,7 @@ PACKAGE= tzcode # Version numbers of the code and data distributions. -VERSION= 2015d +VERSION= 2015e # Email address for bug reports. BUGEMAIL= t...@iana.org @@ -293,23 +293,24 @@ TAB_CHAR= ' ' SAFE_CHARSET1= $(TAB_CHAR)' !\"'$$sharp'$$%&'\''()*+,./0123456789:;<=>?@' SAFE_CHARSET2= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\^_`' SAFE_CHARSET3= 'abcdefghijklmnopqrstuvwxyz{|}~' -SAFE_CHARSET= ]$(SAFE_CHARSET1)$(SAFE_CHARSET2)$(SAFE_CHARSET3)- -SAFE_CHAR= '['$(SAFE_CHARSET)']' -# NONSYM_CHAR is a regular expression that matches any character -# except for a small number of symbols, where we prefer to stick with +SAFE_CHARSET= $(SAFE_CHARSET1)$(SAFE_CHARSET2)$(SAFE_CHARSET3) +SAFE_CHAR= '[]'$(SAFE_CHARSET)'-]' + +# OK_CHAR matches any character allowed in the distributed files. +# This is the same as SAFE_CHAR, except that multibyte letters are +# also allowed so that commentary can contain people's names and quote +# non-English sources. For non-letters the sources are limited to # ASCII renderings for the convenience of maintainers whose text editors # mishandle UTF-8 by default (e.g., XEmacs 21.4.22). -NONSYM_CHAR= '[^–—°′″≈≠≤≥±−×÷∞←→↔·•§¶«»‘’‚‛“”„‟‹›「」『』〝〞〟]' +OK_CHAR= '[][:alpha:]'$(SAFE_CHARSET)'-]' # SAFE_LINE matches a line of safe characters. -# SAFE_SHARP_LINE is similar, except any character can follow '#'; +# SAFE_SHARP_LINE is similar, except any OK character can follow '#'; # this is so that comments can contain non-ASCII characters. -# NONSYM_LINE matches a line of non-symbols. -# VALID_LINE matches a line of any validly-encoded characters. +# OK_LINE matches a line of OK characters. SAFE_LINE= '^'$(SAFE_CHAR)'*$$' -SAFE_SHARP_LINE='^'$(SAFE_CHAR)'*('$$sharp$(NONSYM_CHAR)'*)?$$' -NONSYM_LINE= '^'$(NONSYM_CHAR)'*$$' -VALID_LINE= '^.*$$' +SAFE_SHARP_LINE='^'$(SAFE_CHAR)'*('$$sharp$(OK_CHAR)'*)?$$' +OK_LINE= '^'$(OK_CHAR)'*$$' # Flags to give 'tar' when making a distribution. # Try to use flags appropriate for GNU tar. @@ -324,6 +325,8 @@ GZIPFLAGS= -9 ${GZIP_N_FLAG} ############################################################################### +#MAKE= make + cc= cc CC= $(cc) -DTZDIR=\"$(TZDIR)\" @@ -372,7 +375,7 @@ SHELL= /bin/sh all: tzselect zic zdump libtz.a $(TABDATA) -ALL: all date +ALL: all date $(ENCHILADA) install: all $(DATA) $(REDO) $(MANS) mkdir -p $(DESTDIR)$(ETCDIR) $(DESTDIR)$(TZDIR) \ @@ -476,14 +479,11 @@ check: check_character_set check_white_ check_character_set: $(ENCHILADA) LC_ALL=en_US.utf8 && export LC_ALL && \ sharp='#' && \ - ! grep -Env $(SAFE_LINE) $(MANS) date.1 $(MANTXTS) \ + ! grep -Env $(SAFE_LINE) Makefile $(MANS) date.1 $(MANTXTS) \ $(MISC) $(SOURCES) $(WEB_PAGES) && \ ! grep -Env $(SAFE_SHARP_LINE) $(TDATA) backzone \ - iso3166.tab leapseconds yearistype.sh zone.tab && \ - test $$(grep -Ecv $(SAFE_SHARP_LINE) Makefile) -eq 1 && \ - ! grep -Env $(NONSYM_LINE) CONTRIBUTING NEWS README Theory \ - $(MANS) date.1 zone1970.tab && \ - ! grep -Env $(VALID_LINE) $(ENCHILADA) + leapseconds yearistype.sh zone.tab && \ + ! grep -Env $(OK_LINE) $(ENCHILADA) check_white_space: $(ENCHILADA) ! grep -En ' '$(TAB_CHAR)"|$$(printf '[\f\r\v]')" $(ENCHILADA) @@ -574,9 +574,9 @@ set-timestamps.out: $(ENCHILADA) # The zics below ensure that each data file can stand on its own. # We also do an all-files run to catch links to links. -check_public: $(ENCHILADA) - make maintainer-clean - make "CFLAGS=$(GCC_DEBUG_FLAGS)" $(ENCHILADA) all +check_public: + $(MAKE) maintainer-clean + $(MAKE) "CFLAGS=$(GCC_DEBUG_FLAGS)" ALL mkdir tzpublic for i in $(TDATA) ; do \ $(zic) -v -d tzpublic $$i 2>&1 || exit; \ @@ -595,8 +595,8 @@ check_time_t_alternatives: zones=`$(AWK) '/^[^#]/ { print $$3 }' <zone1970.tab` && \ for type in $(TIME_T_ALTERNATIVES); do \ mkdir -p tzpublic/$$type && \ - make clean_misc && \ - make TOPDIR=`pwd`/tzpublic/$$type \ + $(MAKE) clean_misc && \ + $(MAKE) TOPDIR=`pwd`/tzpublic/$$type \ CFLAGS='$(CFLAGS) -Dtime_tz='"'$$type'" \ REDO='$(REDO)' \ install && \ @@ -642,12 +642,12 @@ tzdata$(VERSION).tar.gz.asc: tzdata$(VER gpg --armor --detach-sign $? typecheck: - make clean + $(MAKE) clean for i in "long long" unsigned; \ do \ - make CFLAGS="-DTYPECHECK -D__time_t_defined -D_TIME_T \"-Dtime_t=$$i\"" ; \ + $(MAKE) CFLAGS="-DTYPECHECK -D__time_t_defined -D_TIME_T \"-Dtime_t=$$i\"" ; \ ./zdump -v Europe/Rome ; \ - make clean ; \ + $(MAKE) clean ; \ done zonenames: $(TDATA) Index: src/lib/libc/time/NEWS diff -u src/lib/libc/time/NEWS:1.11 src/lib/libc/time/NEWS:1.12 --- src/lib/libc/time/NEWS:1.11 Tue Apr 28 13:00:24 2015 +++ src/lib/libc/time/NEWS Sun Jun 21 12:06:51 2015 @@ -1,5 +1,34 @@ News for the tz database + +Release 2015e - 2015-06-13 10:56:02 -0700 + + Changes affecting future time stamps + + Morocco will suspend DST from 2015-06-14 03:00 through 2015-07-19 02:00, + not 06-13 and 07-18 as we had guessed. (Thanks to Milamber.) + + Assume Cayman Islands will observe DST starting next year, using US rules. + Although it isn't guaranteed, it is the most likely. + + Changes affecting data format + + The file 'iso3166.tab' now uses UTF-8, so that its entries can better + spell the names of Åland Islands, Côte d'Ivoire, and Réunion. + + Changes affecting code + + When displaying data, tzselect converts it to the current locale's + encoding if the iconv command works. (Problem reported by random832.) + + tzselect no longer mishandles Dominica, fixing a bug introduced + in Release 2014f. (Problem reported by Owen Leibman.) + + zic -l no longer fails when compiled with -DTZDEFAULT=\"/etc/localtime\". + This fixes a bug introduced in Release 2014f. + (Problem reported by Leonardo Chiquitto.) + + Release 2015d - 2015-04-24 08:09:46 -0700 Changes affecting future time stamps Index: src/lib/libc/time/localtime.c diff -u src/lib/libc/time/localtime.c:1.94 src/lib/libc/time/localtime.c:1.95 --- src/lib/libc/time/localtime.c:1.94 Tue Mar 24 16:01:18 2015 +++ src/lib/libc/time/localtime.c Sun Jun 21 12:06:51 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: localtime.c,v 1.94 2015/03/24 20:01:18 christos Exp $ */ +/* $NetBSD: localtime.c,v 1.95 2015/06/21 16:06:51 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.94 2015/03/24 20:01:18 christos Exp $"); +__RCSID("$NetBSD: localtime.c,v 1.95 2015/06/21 16:06:51 christos Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -230,13 +230,24 @@ init_ttinfo(struct ttinfo *s, int_fast32 static int_fast32_t detzcode(const char *const codep) { - int_fast32_t result; - int i; + int_fast32_t result; + int i; + int_fast32_t one = 1; + int_fast32_t halfmaxval = one << (32 - 2); + int_fast32_t maxval = halfmaxval - 1 + halfmaxval; + int_fast32_t minval = -1 - maxval; - result = (codep[0] & 0x80) ? -1 : 0; - for (i = 0; i < 4; ++i) + result = codep[0] & 0x7f; + for (i = 1; i < 4; ++i) result = (result << 8) | (codep[i] & 0xff); - return result; + + if (codep[0] & 0x80) { + /* Do two's-complement negation even on non-two's-complement machines. + If the result would be minval - 1, return minval. */ + result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0; + result += minval; + } + return result; } static int_fast64_t @@ -244,11 +255,22 @@ detzcode64(const char *const codep) { int_fast64_t result; int i; + int_fast64_t one = 1; + int_fast64_t halfmaxval = one << (64 - 2); + int_fast64_t maxval = halfmaxval - 1 + halfmaxval; + int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval; - result = (codep[0] & 0x80) ? -1 : 0; - for (i = 0; i < 8; ++i) + result = codep[0] & 0x7f; + for (i = 1; i < 8; ++i) result = (result << 8) | (codep[i] & 0xff); - return result; + + if (codep[0] & 0x80) { + /* Do two's-complement negation even on non-two's-complement machines. + If the result would be minval - 1, return minval. */ + result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0; + result += minval; + } + return result; } const char * Index: src/lib/libc/time/private.h diff -u src/lib/libc/time/private.h:1.40 src/lib/libc/time/private.h:1.41 --- src/lib/libc/time/private.h:1.40 Tue Apr 28 13:00:24 2015 +++ src/lib/libc/time/private.h Sun Jun 21 12:06:51 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: private.h,v 1.40 2015/04/28 17:00:24 christos Exp $ */ +/* $NetBSD: private.h,v 1.41 2015/06/21 16:06:51 christos Exp $ */ #ifndef PRIVATE_H #define PRIVATE_H @@ -490,17 +490,20 @@ time_t time2posix_z(timezone_t __restric #define TYPE_SIGNED(type) (/*CONSTCOND*/((type) -1) < 0) #endif /* !defined TYPE_SIGNED */ -#ifdef LOCALTIME_IMPLEMENTATION -/* The minimum and maximum finite time values. */ -static time_t const time_t_min = - (TYPE_SIGNED(time_t) - ? (time_t) -1 << (int)(CHAR_BIT * sizeof (time_t) - 1) - : 0); -static time_t const time_t_max = - (TYPE_SIGNED(time_t) - ? - (~ 0 < 0) - ((time_t) -1 << (int)(CHAR_BIT * sizeof (time_t) - 1)) - : -1); -#endif +#define TWOS_COMPLEMENT(t) (/*CONSTCOND*/(t) ~ (t) 0 < 0) + +/* Max and min values of the integer type T, of which only the bottom + B bits are used, and where the highest-order used bit is considered + to be a sign bit if T is signed. */ +#define MAXVAL(t, b) /*LINTED*/ \ + ((t) (((t) 1 << ((b) - 1 - TYPE_SIGNED(t))) \ + - 1 + ((t) 1 << ((b) - 1 - TYPE_SIGNED(t))))) +#define MINVAL(t, b) \ + ((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0)) + +/* The minimum and maximum finite time values. This assumes no padding. */ +static time_t const time_t_min = MINVAL(time_t, TYPE_BIT(time_t)); +static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t)); #ifndef INT_STRLEN_MAXIMUM /* Index: src/lib/libc/time/zdump.c diff -u src/lib/libc/time/zdump.c:1.40 src/lib/libc/time/zdump.c:1.41 --- src/lib/libc/time/zdump.c:1.40 Thu Oct 23 17:19:53 2014 +++ src/lib/libc/time/zdump.c Sun Jun 21 12:06:51 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: zdump.c,v 1.40 2014/10/23 21:19:53 christos Exp $ */ +/* $NetBSD: zdump.c,v 1.41 2015/06/21 16:06:51 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.40 2014/10/23 21:19:53 christos Exp $"); +__RCSID("$NetBSD: zdump.c,v 1.41 2015/06/21 16:06:51 christos Exp $"); #endif /* !defined lint */ /* @@ -261,13 +261,15 @@ extern char * optarg; extern int optind; /* The minimum and maximum finite time values. */ +enum { atime_shift = CHAR_BIT * sizeof (time_t) - 2 }; static time_t absolute_min_time = ((time_t) -1 < 0 - ? (time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1) + ? (- ((time_t) ~ (time_t) 0 < 0) + - (((time_t) 1 << atime_shift) - 1 + ((time_t) 1 << atime_shift))) : 0); static time_t absolute_max_time = ((time_t) -1 < 0 - ? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1)) + ? (((time_t) 1 << atime_shift) - 1 + ((time_t) 1 << atime_shift)) : -1); static size_t longest; static char * progname; Index: src/lib/libc/time/tzselect.ksh diff -u src/lib/libc/time/tzselect.ksh:1.13 src/lib/libc/time/tzselect.ksh:1.14 --- src/lib/libc/time/tzselect.ksh:1.13 Sat Jan 31 13:55:17 2015 +++ src/lib/libc/time/tzselect.ksh Sun Jun 21 12:06:51 2015 @@ -1,6 +1,6 @@ #! /bin/bash # -# $NetBSD: tzselect.ksh,v 1.13 2015/01/31 18:55:17 christos Exp $ +# $NetBSD: tzselect.ksh,v 1.14 2015/06/21 16:06:51 christos Exp $ # PKGVERSION='(tzcode) ' TZVERSION=see_Makefile @@ -39,10 +39,16 @@ REPORT_BUGS_TO=t...@iana.org : ${AWK=awk} : ${TZDIR=`pwd`} +# Output one argument as-is to standard output. +# Safer than 'echo', which can mishandle '\' or leading '-'. +say() { + printf '%s\n' "$1" +} + # Check for awk Posix compliance. ($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1 [ $? = 123 ] || { - echo >&2 "$0: Sorry, your '$AWK' program is not Posix compatible." + say >&2 "$0: Sorry, your '$AWK' program is not Posix compatible." exit 1 } @@ -156,16 +162,16 @@ do -version) exec echo "tzselect $PKGVERSION$TZVERSION" ;; -*) - echo >&2 "$0: -$opt$OPTARG: unknown option; try '$0 --help'"; exit 1 ;; + say >&2 "$0: -$opt$OPTARG: unknown option; try '$0 --help'"; exit 1 ;; *) - echo >&2 "$0: try '$0 --help'"; exit 1 ;; + say >&2 "$0: try '$0 --help'"; exit 1 ;; esac done shift `expr $OPTIND - 1` case $# in 0) ;; -*) echo >&2 "$0: $1: unknown argument"; exit 1 ;; +*) say >&2 "$0: $1: unknown argument"; exit 1 ;; esac # Make sure the tables are readable. @@ -174,11 +180,26 @@ TZ_ZONE_TABLE=$TZDIR/$zonetabtype.tab for f in $TZ_COUNTRY_TABLE $TZ_ZONE_TABLE do <"$f" || { - echo >&2 "$0: time zone files are not set up correctly" + say >&2 "$0: time zone files are not set up correctly" exit 1 } 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 }' && + { tmp=`(mktemp -d) 2>/dev/null` || { + tmp=${TMPDIR-/tmp}/tzselect.$$ && + (umask 77 && mkdir -- "$tmp") + };} && + trap 'status=$?; rm -fr -- "$tmp"; exit $status' 0 HUP INT PIPE TERM && + (iconv -f UTF-8 -t //TRANSLIT <"$TZ_COUNTRY_TABLE" >$tmp/iso3166.tab) \ + 2>/dev/null && + 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=' ' IFS=$newline @@ -338,8 +359,7 @@ while exit 0 }' do - echo >&2 "'$TZ' is not a conforming" \ - 'Posix time zone string.' + say >&2 "'$TZ' is not a conforming Posix time zone string." done TZ_for_date=$TZ;; *) @@ -361,7 +381,7 @@ while sort -n | sed "${location_limit}q" ` - regions=`echo "$distance_table" | $AWK ' + regions=`say "$distance_table" | $AWK ' BEGIN { FS = "\t" } { print $NF } '` @@ -371,7 +391,7 @@ while "of distance from $coord". doselect $regions region=$select_result - TZ=`echo "$distance_table" | $AWK -v region="$region" ' + TZ=`say "$distance_table" | $AWK -v region="$region" ' BEGIN { FS="\t" } $NF == region { print $4 } '` @@ -431,6 +451,7 @@ while } } } + /^#/ { next } $1 ~ cc { print $4 } ' <"$TZ_ZONE_TABLE"` @@ -462,6 +483,7 @@ while } } } + /^#/ { next } $1 ~ cc && $4 == region { print $3 } ' <"$TZ_ZONE_TABLE"` esac @@ -469,7 +491,7 @@ while # Make sure the corresponding zoneinfo file exists. TZ_for_date=$TZDIR/$TZ <"$TZ_for_date" || { - echo >&2 "$0: time zone files are not set up correctly" + say >&2 "$0: time zone files are not set up correctly" exit 1 } esac @@ -502,15 +524,15 @@ Universal Time is now: $UTdate." echo >&2 "The following information has been given:" echo >&2 "" case $country%$region%$coord in - ?*%?*%) echo >&2 " $country$newline $region";; - ?*%%) echo >&2 " $country";; - %?*%?*) echo >&2 " coord $coord$newline $region";; - %%?*) echo >&2 " coord $coord";; - *) echo >&2 " TZ='$TZ'" + ?*%?*%) say >&2 " $country$newline $region";; + ?*%%) say >&2 " $country";; + %?*%?*) say >&2 " coord $coord$newline $region";; + %%?*) say >&2 " coord $coord";; + *) say >&2 " TZ='$TZ'" esac - echo >&2 "" - echo >&2 "Therefore TZ='$TZ' will be used.$extra_info" - echo >&2 "Is the above information OK?" + say >&2 "" + say >&2 "Therefore TZ='$TZ' will be used.$extra_info" + say >&2 "Is the above information OK?" doselect Yes No ok=$select_result @@ -525,7 +547,7 @@ case $SHELL in *) file=.profile line="TZ='$TZ'; export TZ" esac -echo >&2 " +say >&2 " You can make this change permanent for yourself by appending the line $line to the file '$file' in your home directory; then log out and log in again. @@ -533,4 +555,4 @@ to the file '$file' in your home directo Here is that TZ value again, this time on standard output so that you can use the $0 command in shell scripts:" -echo "$TZ" +say "$TZ" Index: src/lib/libc/time/zic.8 diff -u src/lib/libc/time/zic.8:1.24 src/lib/libc/time/zic.8:1.25 --- src/lib/libc/time/zic.8:1.24 Tue Oct 7 17:51:03 2014 +++ src/lib/libc/time/zic.8 Sun Jun 21 12:06:51 2015 @@ -1,4 +1,4 @@ -.\" $NetBSD: zic.8,v 1.24 2014/10/07 21:51:03 christos Exp $ +.\" $NetBSD: zic.8,v 1.25 2015/06/21 16:06:51 christos Exp $ .Dd October 6, 2014 .Dt ZIC 8 .Os @@ -324,7 +324,8 @@ The time at which the UT offset or the r It is specified as a year, a month, a day, and a time of day. If this is specified, the time zone information is generated from the given UT offset -and rule change until the time specified. +and rule change until the time specified, which is interpreted using +the rules in effect just before the transition. The month, day, and time of day have the same format as the IN, ON, and AT fields of a rule; trailing fields can be omitted, and default to the earliest possible value for the missing fields. Index: src/lib/libc/time/zic.c diff -u src/lib/libc/time/zic.c:1.53 src/lib/libc/time/zic.c:1.54 --- src/lib/libc/time/zic.c:1.53 Tue Apr 28 13:00:24 2015 +++ src/lib/libc/time/zic.c Sun Jun 21 12:06:51 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: zic.c,v 1.53 2015/04/28 17:00:24 christos Exp $ */ +/* $NetBSD: zic.c,v 1.54 2015/06/21 16:06:51 christos Exp $ */ /* ** This file is in the public domain, so clarified as of ** 2006-07-17 by Arthur David Olson. @@ -10,7 +10,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: zic.c,v 1.53 2015/04/28 17:00:24 christos Exp $"); +__RCSID("$NetBSD: zic.c,v 1.54 2015/06/21 16:06:51 christos Exp $"); #endif /* !defined lint */ #include "private.h" @@ -456,7 +456,8 @@ verror(const char *const string, va_list ** zic ... 2>&1 | error -t "*" -v ** on BSD systems. */ - fprintf(stderr, _("\"%s\", line %d: "), filename, linenum); + if (filename) + fprintf(stderr, _("\"%s\", line %d: "), filename, linenum); vfprintf(stderr, string, args); if (rfilename != NULL) fprintf(stderr, _(" (rule from \"%s\", line %d)"), @@ -608,7 +609,7 @@ _("%s: More than one -L option specified noise = true; break; case 's': - warning(_("-s ignored\n")); + warning(_("-s ignored")); break; } if (optind == argc - 1 && strcmp(argv[optind], "=") == 0) @@ -661,36 +662,43 @@ _("%s: More than one -L option specified return errors ? EXIT_FAILURE : EXIT_SUCCESS; } -static void +static bool componentcheck(char const *name, char const *component, char const *component_end) { enum { component_len_max = 14 }; size_t component_len = component_end - component; if (component_len == 0) { - fprintf(stderr, _("%s: file name '%s' contains empty component"), - progname, name); - exit(EXIT_FAILURE); + if (!*name) + error (_("empty file name")); + else + error (_(component == name + ? "file name '%s' begins with '/'" + : *component_end + ? "file name '%s' contains '//'" + : "file name '%s' ends with '/'"), + name); + return false; } if (0 < component_len && component_len <= 2 && component[0] == '.' && component_end[-1] == '.') { - fprintf(stderr, _("%s: file name '%s' contains" - " '%.*s' component"), - progname, name, (int) component_len, component); - exit(EXIT_FAILURE); + error(_("file name '%s' contains '%.*s' component"), + name, (int) component_len, component); + return false; } - if (!noise) - return; - if (0 < component_len && component[0] == '-') - warning(_("file name '%s' component contains leading '-'"), - name); - if (component_len_max < component_len) - warning(_("file name '%s' contains overlength component" - " '%.*s...'"), - name, component_len_max, component); + if (noise) { + if (0 < component_len && component[0] == '-') + warning(_("file name '%s' component contains leading '-'"), + name); + if (component_len_max < component_len) + warning(_("file name '%s' contains overlength component" + " '%.*s...'"), + name, component_len_max, component); + } + return true; } -static void +static bool namecheck(const char *name) { char const *cp; @@ -714,14 +722,14 @@ namecheck(const char *name) ? _("file name '%s' contains byte '%c'") : _("file name '%s' contains byte '\\%o'")), name, c); - return; } if (c == '/') { - componentcheck(name, component, cp); + if (!componentcheck(name, component, cp)) + return false; component = cp + 1; } } - componentcheck(name, component, cp); + return componentcheck(name, component, cp); } static char * @@ -746,7 +754,6 @@ dolink(const char *const fromfield, cons char * toname; int fromisdir; - namecheck(tofield); fromname = relname(directory, fromfield); toname = relname(directory, tofield); /* @@ -826,8 +833,8 @@ dolink(const char *const fromfield, cons #define TIME_T_BITS_IN_FILE 64 -static const zic_t min_time = (zic_t) -1 << (TIME_T_BITS_IN_FILE - 1); -static const zic_t max_time = -1 - ((zic_t) -1 << (TIME_T_BITS_IN_FILE - 1)); +static zic_t const min_time = MINVAL (zic_t, TIME_T_BITS_IN_FILE); +static zic_t const max_time = MAXVAL (zic_t, TIME_T_BITS_IN_FILE); /* Estimated time of the Big Bang, in seconds since the POSIX epoch. rounded downward to the negation of a power of two that is @@ -1033,9 +1040,9 @@ infile(const char *name) break; case LC_LEAP: if (name != leapsec) - warning( -_("%s: Leap line in non leap seconds file %s\n"), - progname, name); + warning(_("%s: Leap line in non leap" + " seconds file %s"), + progname, name); else inleap(fields, nfields); wantcont = false; break; @@ -1191,7 +1198,9 @@ inzsub(char **const fields, const int nf i_untilday = ZFC_TILDAY; i_untiltime = ZFC_TILTIME; z.z_name = NULL; - } else { + } else if (!namecheck(fields[ZF_NAME])) + return false; + else { i_gmtoff = ZF_GMTOFF; i_rule = ZF_RULE; i_format = ZF_FORMAT; @@ -1367,10 +1376,8 @@ inlink(char **const fields, const int nf error(_("blank FROM field on Link line")); return; } - if (*fields[LF_TO] == '\0') { - error(_("blank TO field on Link line")); - return; - } + if (! namecheck(fields[LF_TO])) + return; l.l_filename = filename; l.l_linenum = linenum; l.l_from = ecpyalloc(fields[LF_FROM]); @@ -1596,7 +1603,6 @@ writezone(const char *const name, const void *typesptr = ats + timecnt; unsigned char *types = typesptr; - namecheck(name); /* ** Sort. */ @@ -2971,7 +2977,7 @@ mkdirs(char *argname) if (itsdir(name) <= 0) { char const *e = strerror(err); warning(_("%s: Can't create directory" - " %s: %s\n"), + " %s: %s"), progname, name, e); free(name); return false;