diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2007-02-06 19:35:17 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2007-02-06 19:35:17 +0000 |
commit | 0044c236c2a42c54691edb8497bce0fa8ce0a49e (patch) | |
tree | 529743eb863865002b02f7c0b657263cdb15a399 /lib/libc/time | |
parent | 48331a8159d590ec9e5ea4cd976e1947249f0515 (diff) |
Update to tzcode2007a. This adds support for 64bit time_t in case
we need it in the future. All of our platforms currently have 32bit
time_t types. This also extends the timezone data file format to
support both 32bit and 64bit data. The 64bit data is located after
the 32bit data so binaries linked with the older tzcode simply won't
look at it. A version field in the file header is used to determine
whether the data file is the old or extended format. OK miod@
Diffstat (limited to 'lib/libc/time')
-rw-r--r-- | lib/libc/time/README | 4 | ||||
-rw-r--r-- | lib/libc/time/Theory | 4 | ||||
-rw-r--r-- | lib/libc/time/asctime.c | 13 | ||||
-rw-r--r-- | lib/libc/time/ctime.3 | 4 | ||||
-rw-r--r-- | lib/libc/time/localtime.c | 231 | ||||
-rw-r--r-- | lib/libc/time/private.h | 74 | ||||
-rw-r--r-- | lib/libc/time/scheck.c | 4 | ||||
-rw-r--r-- | lib/libc/time/strftime.3 | 4 | ||||
-rw-r--r-- | lib/libc/time/time2posix.3 | 4 | ||||
-rw-r--r-- | lib/libc/time/tz-art.htm | 65 | ||||
-rw-r--r-- | lib/libc/time/tz-link.htm | 181 | ||||
-rw-r--r-- | lib/libc/time/tzfile.5 | 18 | ||||
-rw-r--r-- | lib/libc/time/tzfile.h | 25 | ||||
-rw-r--r-- | lib/libc/time/tzset.3 | 4 | ||||
-rw-r--r-- | lib/libc/time/zdump.8 | 4 | ||||
-rw-r--r-- | lib/libc/time/zdump.c | 41 | ||||
-rw-r--r-- | lib/libc/time/zic.8 | 28 | ||||
-rw-r--r-- | lib/libc/time/zic.c | 782 |
18 files changed, 1090 insertions, 400 deletions
diff --git a/lib/libc/time/README b/lib/libc/time/README index 180384cb1c5..90156361cbe 100644 --- a/lib/libc/time/README +++ b/lib/libc/time/README @@ -1,5 +1,5 @@ -$OpenBSD: README,v 1.5 2005/07/05 13:40:51 millert Exp $ -@(#)README 7.12 +$OpenBSD: README,v 1.6 2007/02/06 19:35:16 millert Exp $ +@(#)README 8.1 "What time is it?" -- Richard Deacon as The King "Any time you want it to be." -- Frank Baxter as The Scientist diff --git a/lib/libc/time/Theory b/lib/libc/time/Theory index b6205371947..0ba9235f5f6 100644 --- a/lib/libc/time/Theory +++ b/lib/libc/time/Theory @@ -1,5 +1,5 @@ -$OpenBSD: Theory,v 1.11 2006/02/18 21:54:17 millert Exp $ -@(#)Theory 7.19 +$OpenBSD: Theory,v 1.12 2007/02/06 19:35:16 millert Exp $ +@(#)Theory 8.1 ----- Outline ----- diff --git a/lib/libc/time/asctime.c b/lib/libc/time/asctime.c index a70ae4b6d3d..f05a428aef7 100644 --- a/lib/libc/time/asctime.c +++ b/lib/libc/time/asctime.c @@ -1,4 +1,4 @@ -/* $OpenBSD: asctime.c,v 1.14 2006/02/18 21:54:17 millert Exp $ */ +/* $OpenBSD: asctime.c,v 1.15 2007/02/06 19:35:16 millert Exp $ */ /* ** This file is in the public domain, so clarified as of ** 1996-06-05 by Arthur David Olson. @@ -19,7 +19,8 @@ /* ** Some systems only handle "%.2d"; others only handle "%02d"; ** "%02.2d" makes (most) everybody happy. -** At least some versions of gcc warn about the %02.2d; ignore the warning. +** At least some versions of gcc warn about the %02.2d; +** we conditionalize below to avoid the warning. */ /* ** All years associated with 32-bit time_t values are exactly four digits long; @@ -33,14 +34,22 @@ ** The ISO C 1999 and POSIX 1003.1-2004 standards prohibit padding the year, ** but many implementations pad anyway; most likely the standards are buggy. */ +#ifdef __GNUC__ +#define ASCTIME_FMT "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %-4s\n" +#else /* !defined __GNUC__ */ #define ASCTIME_FMT "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4s\n" +#endif /* !defined __GNUC__ */ /* ** For years that are more than four digits we put extra spaces before the year ** so that code trying to overwrite the newline won't end up overwriting ** a digit within a year and truncating the year (operating on the assumption ** that no output is better than wrong output). */ +#ifdef __GNUC__ +#define ASCTIME_FMT_B "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %s\n" +#else /* !defined __GNUC__ */ #define ASCTIME_FMT_B "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %s\n" +#endif /* !defined __GNUC__ */ #define STD_ASCTIME_BUF_SIZE 26 /* diff --git a/lib/libc/time/ctime.3 b/lib/libc/time/ctime.3 index 4c5f30f9bdc..51c184c6170 100644 --- a/lib/libc/time/ctime.3 +++ b/lib/libc/time/ctime.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ctime.3,v 1.32 2006/07/23 09:11:04 jmc Exp $ +.\" $OpenBSD: ctime.3,v 1.33 2007/02/06 19:35:16 millert Exp $ .\" .\" .Dd February 16, 1999 @@ -310,6 +310,6 @@ as the superuser. Avoid using out-of-range values with .Fn mktime when setting up lunch with promptness sticklers in Riyadh. -.\" based on @(#)newctime.3 7.16 +.\" based on @(#)newctime.3 8.1 .\" This file is in the public domain, so clarified as of .\" 2003-02-14 by Arthur David Olson (arthur_david_olson@nih.gov). diff --git a/lib/libc/time/localtime.c b/lib/libc/time/localtime.c index 8fd6ef1523f..a22fc0bcf7b 100644 --- a/lib/libc/time/localtime.c +++ b/lib/libc/time/localtime.c @@ -1,4 +1,4 @@ -/* $OpenBSD: localtime.c,v 1.31 2006/02/18 21:54:17 millert Exp $ */ +/* $OpenBSD: localtime.c,v 1.32 2007/02/06 19:35:16 millert Exp $ */ /* ** This file is in the public domain, so clarified as of ** 1996-06-05 by Arthur David Olson. @@ -106,6 +106,8 @@ struct state { int timecnt; int typecnt; int charcnt; + int goback; + int goahead; time_t ats[TZ_MAX_TIMES]; unsigned char types[TZ_MAX_TIMES]; struct ttinfo ttis[TZ_MAX_TYPES]; @@ -131,8 +133,10 @@ struct rule { */ static long detzcode P((const char * codep)); +static time_t detzcode64 P((const char * codep)); +static int differ_by_repeat P((time_t t1, time_t t0)); static const char * getzname P((const char * strp)); -static const char * getqzname P((const char * strp, const char delim)); +static const char * getqzname P((const char * strp, const int delim)); static const char * getnum P((const char * strp, int * nump, int min, int max)); static const char * getsecs P((const char * strp, long * secsp)); @@ -169,7 +173,8 @@ static int tmcomp P((const struct tm * atmp, const struct tm * btmp)); static time_t transtime P((time_t janfirst, int year, const struct rule * rulep, long offset)); -static int tzload P((const char * name, struct state * sp)); +static int tzload P((const char * name, struct state * sp, + int doextend)); static int tzparse P((const char * name, struct state * sp, int lastditch)); @@ -226,12 +231,25 @@ const char * const codep; register long result; register int i; - result = (codep[0] & 0x80) ? ~0L : 0L; + result = (codep[0] & 0x80) ? ~0L : 0; for (i = 0; i < 4; ++i) result = (result << 8) | (codep[i] & 0xff); return result; } +static time_t +detzcode64(codep) +const char * const codep; +{ + register time_t result; + register int i; + + result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0; + for (i = 0; i < 8; ++i) + result = result * 256 + (codep[i] & 0xff); + return result; +} + static void settzname P((void)) { @@ -301,13 +319,33 @@ settzname P((void)) } static int -tzload(name, sp) +differ_by_repeat(t1, t0) +const time_t t1; +const time_t t0; +{ + if (TYPE_INTEGRAL(time_t) && + TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) + return 0; + return t1 - t0 == SECSPERREPEAT; +} + +static int +tzload(name, sp, doextend) register const char * name; register struct state * const sp; +register const int doextend; { - register const char * p; - register int i; - register int fid; + register const char * p; + register int i; + register int fid; + register int stored; + register int nread; + union { + struct tzhead tzhead; + char buf[2 * sizeof(struct tzhead) + + 2 * sizeof *sp + + 4 * TZ_MAX_TIMES]; + } u; if (name != NULL && issetugid() != 0) if ((name[0] == ':' && (strchr(name, '/') || strstr(name, ".."))) || @@ -349,18 +387,13 @@ register struct state * const sp; if ((fid = open(name, OPEN_MODE)) == -1) return -1; } - { - struct tzhead * tzhp; - union { - struct tzhead tzhead; - char buf[sizeof *sp + sizeof *tzhp]; - } u; + nread = read(fid, u.buf, sizeof u.buf); + if (close(fid) < 0 || nread <= 0) + return -1; + for (stored = 4; stored <= 8; stored *= 2) { int ttisstdcnt; int ttisgmtcnt; - i = read(fid, u.buf, sizeof u.buf); - if (close(fid) != 0) - return -1; ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); @@ -375,17 +408,19 @@ register struct state * const sp; (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) return -1; - if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */ + if (nread - (p - u.buf) < + sp->timecnt * stored + /* ats */ sp->timecnt + /* types */ - sp->typecnt * (4 + 2) + /* ttinfos */ + sp->typecnt * 6 + /* ttinfos */ sp->charcnt + /* chars */ - sp->leapcnt * (4 + 4) + /* lsinfos */ + sp->leapcnt * (stored + 4) + /* lsinfos */ ttisstdcnt + /* ttisstds */ ttisgmtcnt) /* ttisgmts */ return -1; for (i = 0; i < sp->timecnt; ++i) { - sp->ats[i] = detzcode(p); - p += 4; + sp->ats[i] = (stored == 4) ? + detzcode(p) : detzcode64(p); + p += stored; } for (i = 0; i < sp->timecnt; ++i) { sp->types[i] = (unsigned char) *p++; @@ -413,8 +448,9 @@ register struct state * const sp; register struct lsinfo * lsisp; lsisp = &sp->lsis[i]; - lsisp->ls_trans = detzcode(p); - p += 4; + lsisp->ls_trans = (stored == 4) ? + detzcode(p) : detzcode64(p); + p += stored; lsisp->ls_corr = detzcode(p); p += 4; } @@ -471,7 +507,63 @@ register struct state * const sp; } break; } + /* + ** If this is an old file, we're done. + */ + if (u.tzhead.tzh_version[0] == '\0') + break; + nread -= p - u.buf; + for (i = 0; i < nread; ++i) + u.buf[i] = p[i]; + /* + ** If this is a narrow integer time_t system, we're done. + */ + if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t)) + break; + } + if (doextend && nread > 2 && + u.buf[0] == '\n' && u.buf[nread - 1] == '\n' && + sp->typecnt + 2 <= TZ_MAX_TYPES) { + struct state ts; + register int result; + + u.buf[nread - 1] = '\0'; + result = tzparse(&u.buf[1], &ts, FALSE); + if (result == 0 && ts.typecnt == 2 && + sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { + for (i = 0; i < 2; ++i) + ts.ttis[i].tt_abbrind += + sp->charcnt; + for (i = 0; i < ts.charcnt; ++i) + sp->chars[sp->charcnt++] = + ts.chars[i]; + i = 0; + while (i < ts.timecnt && + ts.ats[i] <= + sp->ats[sp->timecnt - 1]) + ++i; + while (i < ts.timecnt && + sp->timecnt < TZ_MAX_TIMES) { + sp->ats[sp->timecnt] = + ts.ats[i]; + sp->types[sp->timecnt] = + sp->typecnt + + ts.types[i]; + ++sp->timecnt; + ++i; + } + sp->ttis[sp->typecnt++] = ts.ttis[0]; + sp->ttis[sp->typecnt++] = ts.ttis[1]; + } } + i = 2 * YEARSPERREPEAT; + sp->goback = sp->goahead = sp->timecnt > i; + sp->goback = sp->goback && sp->types[i] == sp->types[0] && + differ_by_repeat(sp->ats[i], sp->ats[0]); + sp->goahead = sp->goahead && + sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] && + differ_by_repeat(sp->ats[sp->timecnt - 1], + sp->ats[sp->timecnt - 1 - i]); return 0; } @@ -504,19 +596,17 @@ register const char * strp; /* ** Given a pointer into an extended time zone string, scan until the ending -** delimiter of the zone name is located. Return a pointer to the delimiter. +** delimiter of the zone name is located. Return a pointer to the delimiter. ** ** As with getzname above, the legal character set is actually quite ** restricted, with other characters producing undefined results. -** We choose not to care - allowing almost anything to be in the zone abbrev. +** We don't do any checking here; checking is done later in common-case code. */ static const char * -getqzname(strp, delim) -register const char * strp; -const char delim; +getqzname(register const char *strp, const int delim) { - register char c; + register int c; while ((c = *strp) != '\0' && c != delim) ++strp; @@ -825,7 +915,7 @@ const int lastditch; if (name == NULL) return -1; } - load_result = tzload(TZDEFRULES, sp); + load_result = tzload(TZDEFRULES, sp, FALSE); if (load_result != 0) sp->leapcnt = 0; /* so, we're off a little */ if (*name != '\0') { @@ -867,11 +957,8 @@ const int lastditch; return -1; sp->typecnt = 2; /* standard time and DST */ /* - ** Two transitions per year, from EPOCH_YEAR to 2037. + ** Two transitions per year, from EPOCH_YEAR forward. */ - sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1); - if (sp->timecnt > TZ_MAX_TIMES) - return -1; sp->ttis[0].tt_gmtoff = -dstoffset; sp->ttis[0].tt_isdst = 1; sp->ttis[0].tt_abbrind = stdlen + 1; @@ -881,7 +968,12 @@ const int lastditch; atp = sp->ats; typep = sp->types; janfirst = 0; - for (year = EPOCH_YEAR; year <= 2037; ++year) { + sp->timecnt = 0; + for (year = EPOCH_YEAR; + sp->timecnt + 2 <= TZ_MAX_TIMES; + ++year) { + time_t newfirst; + starttime = transtime(janfirst, year, &start, stdoffset); endtime = transtime(janfirst, year, &end, @@ -897,8 +989,13 @@ const int lastditch; *atp++ = endtime; *typep++ = 1; /* DST ends */ } - janfirst += year_lengths[isleap(year)] * + sp->timecnt += 2; + newfirst = janfirst; + newfirst += year_lengths[isleap(year)] * SECSPERDAY; + if (newfirst <= janfirst) + break; + janfirst = newfirst; } } else { register long theirstdoffset; @@ -1011,7 +1108,7 @@ static void gmtload(sp) struct state * const sp; { - if (tzload(gmt, sp) != 0) + if (tzload(gmt, sp, TRUE) != 0) (void) tzparse(gmt, sp, TRUE); } static @@ -1031,7 +1128,7 @@ tzsetwall_basic P((void)) } } #endif /* defined ALL_STATE */ - if (tzload((char *) NULL, lclptr) != 0) + if (tzload((char *) NULL, lclptr, TRUE) != 0) gmtload(lclptr); settzname(); } @@ -1089,7 +1186,7 @@ tzset_basic P((void)) lclptr->ttis[0].tt_gmtoff = 0; lclptr->ttis[0].tt_abbrind = 0; (void) strlcpy(lclptr->chars, gmt, sizeof lclptr->chars); - } else if (tzload(name, lclptr) != 0) + } else if (tzload(name, lclptr, TRUE) != 0) if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0) (void) gmtload(lclptr); settzname(); @@ -1130,6 +1227,45 @@ struct tm * const tmp; if (sp == NULL) return gmtsub(timep, offset, tmp); #endif /* defined ALL_STATE */ + if ((sp->goback && t < sp->ats[0]) || + (sp->goahead && t > sp->ats[sp->timecnt - 1])) { + time_t newt = t; + register time_t seconds; + register time_t tcycles; + register int_fast64_t icycles; + + if (t < sp->ats[0]) + seconds = sp->ats[0] - t; + else seconds = t - sp->ats[sp->timecnt - 1]; + --seconds; + tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; + ++tcycles; + icycles = tcycles; + if (tcycles - icycles >= 1 || icycles - tcycles >= 1) + return NULL; + seconds = icycles; + seconds *= YEARSPERREPEAT; + seconds *= AVGSECSPERYEAR; + if (t < sp->ats[0]) + newt += seconds; + else newt -= seconds; + if (newt < sp->ats[0] || + newt > sp->ats[sp->timecnt - 1]) + return NULL; /* "cannot happen" */ + result = localsub(&newt, offset, tmp); + if (result == tmp) { + register time_t newy; + + newy = tmp->tm_year; + if (t < sp->ats[0]) + newy -= icycles * YEARSPERREPEAT; + else newy += icycles * YEARSPERREPEAT; + tmp->tm_year = newy; + if (tmp->tm_year != newy) + return NULL; + } + return result; + } if (sp->timecnt == 0 || t < sp->ats[0]) { i = 0; while (sp->ttis[i].tt_isdst) @@ -1138,10 +1274,17 @@ struct tm * const tmp; break; } } else { - for (i = 1; i < sp->timecnt; ++i) - if (t < sp->ats[i]) - break; - i = (int) sp->types[i - 1]; + register int lo = 1; + register int hi = sp->timecnt; + + while (lo < hi) { + register int mid = (lo + hi) >> 1; + + if (t < sp->ats[mid]) + hi = mid; + else lo = mid + 1; + } + i = (int) sp->types[lo - 1]; } ttisp = &sp->ttis[i]; /* diff --git a/lib/libc/time/private.h b/lib/libc/time/private.h index 8acebd17725..933029fb6cb 100644 --- a/lib/libc/time/private.h +++ b/lib/libc/time/private.h @@ -1,4 +1,4 @@ -/* $OpenBSD: private.h,v 1.18 2006/02/18 21:54:17 millert Exp $ */ +/* $OpenBSD: private.h,v 1.19 2007/02/06 19:35:16 millert Exp $ */ #ifndef PRIVATE_H #define PRIVATE_H @@ -15,6 +15,7 @@ #define XPG4_1994_04_09 1 #define STD_INSPIRED 1 #define HAVE_STRERROR 1 +#define HAVE_STDINT_H 1 #define NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU 1 /* @@ -32,7 +33,7 @@ #if 0 #ifndef lint #ifndef NOID -static char privatehid[] = "@(#)private.h 7.55"; +static char privatehid[] = "@(#)private.h 8.2"; #endif /* !defined NOID */ #endif /* !defined lint */ #endif @@ -103,7 +104,7 @@ static char privatehid[] = "@(#)private.h 7.55"; #include "stdio.h" #include "errno.h" #include "string.h" -#include "limits.h" /* for CHAR_BIT */ +#include "limits.h" /* for CHAR_BIT et al. */ #include "time.h" #include "stdlib.h" @@ -138,21 +139,40 @@ static char privatehid[] = "@(#)private.h 7.55"; /* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */ #define is_digit(c) ((unsigned)(c) - '0' <= 9) +#if HAVE_STDINT_H +#include "stdint.h" +#endif /* !HAVE_STDINT_H */ + +#ifndef INT_FAST64_MAX +/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */ +#if defined LLONG_MAX || defined __LONG_LONG_MAX__ +typedef long long int_fast64_t; +#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */ +#if (LONG_MAX >> 31) < 0xffffffff +Please use a compiler that supports a 64-bit integer type (or wider); +you may need to compile with "-DHAVE_STDINT_H". +#endif /* (LONG_MAX >> 31) < 0xffffffff */ +typedef long int_fast64_t; +#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */ +#endif /* !defined INT_FAST64_MAX */ + +#ifndef INT32_MAX +#define INT32_MAX 0x7fffffff +#endif /* !defined INT32_MAX */ +#ifndef INT32_MIN +#define INT32_MIN (-1 - INT32_MAX) +#endif /* !defined INT32_MIN */ + /* ** Workarounds for compilers/systems. */ /* -** SunOS 4.1.1 cc lacks prototypes. +** If your compiler lacks prototypes, "#define P(x) ()". */ #ifndef P -#ifdef __STDC__ #define P(x) x -#endif /* defined __STDC__ */ -#ifndef __STDC__ -#define P(x) () -#endif /* !defined __STDC__ */ #endif /* !defined P */ /* @@ -226,14 +246,14 @@ extern char * asctime_r(); ** Private function declarations. */ -char * icalloc P((int nelem, int elsize)); -char * icatalloc P((char * old, const char * new)); -char * icpyalloc P((const char * string)); -char * imalloc P((int n)); -void * irealloc P((void * pointer, int size)); -void icfree P((char * pointer)); -void ifree P((char * pointer)); -const char *scheck P((const char *string, const char *format)); +char * icalloc P((int nelem, int elsize)); +char * icatalloc P((char * old, const char * new)); +char * icpyalloc P((const char * string)); +char * imalloc P((int n)); +void * irealloc P((void * pointer, int size)); +void icfree P((char * pointer)); +void ifree P((char * pointer)); +const char * scheck P((const char * string, const char * format)); /* ** Finally, some convenience items. @@ -325,6 +345,26 @@ char *asctime_r P((struct tm const *, char *)); char *ctime_r P((time_t const *, char *)); #endif /* HAVE_INCOMPATIBLE_CTIME_R */ +#ifndef YEARSPERREPEAT +#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */ +#endif /* !defined YEARSPERREPEAT */ + +/* +** The Gregorian year averages 365.2425 days, which is 31556952 seconds. +*/ + +#ifndef AVGSECSPERYEAR +#define AVGSECSPERYEAR 31556952L +#endif /* !defined AVGSECSPERYEAR */ + +#ifndef SECSPERREPEAT +#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR) +#endif /* !defined SECSPERREPEAT */ + +#ifndef SECSPERREPEAT_BITS +#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */ +#endif /* !defined SECSPERREPEAT_BITS */ + /* ** UNIX was a registered trademark of The Open Group in 2003. */ diff --git a/lib/libc/time/scheck.c b/lib/libc/time/scheck.c index c5e00e38f51..ca2cbbf0830 100644 --- a/lib/libc/time/scheck.c +++ b/lib/libc/time/scheck.c @@ -1,7 +1,7 @@ -/* $OpenBSD: scheck.c,v 1.9 2006/02/18 21:54:17 millert Exp $ */ +/* $OpenBSD: scheck.c,v 1.10 2007/02/06 19:35:16 millert Exp $ */ /* ** This file is in the public domain, so clarified as of -** Feb 14, 2003 by Arthur David Olson. +** 2006-07-17 by Arthur David Olson. */ /*LINTLIBRARY*/ diff --git a/lib/libc/time/strftime.3 b/lib/libc/time/strftime.3 index f85a02be7cd..d383cc6578c 100644 --- a/lib/libc/time/strftime.3 +++ b/lib/libc/time/strftime.3 @@ -30,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" from: @(#)strftime.3 5.12 (Berkeley) 6/29/91 -.\" $OpenBSD: strftime.3,v 1.20 2005/07/22 03:23:37 jaredy Exp $ +.\" $OpenBSD: strftime.3,v 1.21 2007/02/06 19:35:16 millert Exp $ .\" .Dd January 18, 1998 .Dt STRFTIME 3 @@ -245,4 +245,4 @@ is not large enough to store the entire time string. The contents of .Fa buf are implementation specific in this case. -.\" @(#)newstrftime.3 7.14 +.\" @(#)newstrftime.3 8.1 diff --git a/lib/libc/time/time2posix.3 b/lib/libc/time/time2posix.3 index 107d39ddfd2..3ef435f56c8 100644 --- a/lib/libc/time/time2posix.3 +++ b/lib/libc/time/time2posix.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: time2posix.3,v 1.13 2005/07/22 03:23:37 jaredy Exp $ +.\" $OpenBSD: time2posix.3,v 1.14 2007/02/06 19:35:16 millert Exp $ .Dd May 24, 1999 .Dt TIME2POSIX 3 .Os @@ -138,6 +138,6 @@ degenerate to the identity function. .Xr localtime 3 , .Xr mktime 3 , .Xr time 3 -.\" @(#)time2posix.3 7.8 +.\" @(#)time2posix.3 8.1 .\" This file is in the public domain, so clarified as of .\" 1996-06-05 by Arthur David Olson. diff --git a/lib/libc/time/tz-art.htm b/lib/libc/time/tz-art.htm index 4abbd519b36..c23c5176ff7 100644 --- a/lib/libc/time/tz-art.htm +++ b/lib/libc/time/tz-art.htm @@ -1,23 +1,22 @@ -<?xml version="1.0" encoding="US-ASCII"?> <!DOCTYPE html -PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" -"DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +PUBLIC "-//W3C//DTD HTML 4.01//EN" +"http://www.w3.org/TR/html4/strict.dtd"> +<html> <head> -<meta http-equiv="Content-type" content='text/html; charset="US-ASCII"' /> +<meta http-equiv="Content-type" content='text/html; charset="US-ASCII"'> <title>Time and the Arts</title> </head> <body> <h1>Time and the Arts</h1> <address> -@(#)tz-art.htm 7.59 +@(#)tz-art.htm 8.5 </address> <p> Please send corrections to this web page to the <a href="mailto:tz@elsie.nci.nih.gov">time zone mailing list</a>.</p> <p> See also <a href="tz-link.htm">Sources for Time Zone and Daylight Saving Time Data</a>.</p> -<hr /> +<hr> <p> Data on recordings of "Save That Time," Russ Long, Serrob Publishing, BMI:</p> <table> @@ -83,7 +82,7 @@ Marion Simon, percussion</td></tr> <tr><td><a href="http://www.allmusic.com/cg/amg.dll?p=amg&sql=A5rkcikcjbb89">AMG Rating</a></td><td>unrated</td></tr> <tr><td>Penguin Rating</td><td>3 stars</td></tr> </table> -<hr /> +<hr> <p>Also of note:</p> <table> <tr><td>Artist</td><td>Holly Cole Trio</td></tr> @@ -160,6 +159,25 @@ Richard Teitelbaum, modular moog and micromoog synthesizer</td></tr> <tr><td>ADO Rating</td><td>black dot</td></tr> <tr><td><a href="http://www.allmusic.com/cg/amg.dll?p=amg&sql=A5bkvu3xjan1k">AMG Rating</a></td><td>unrated</td></tr> <tr><td> </td></tr> +<tr><td>Artist</td><td>Charles Gayle</td></tr> +<tr><td>CD</td><td>Time Zones</td></tr> +<tr><td>Copyright Date</td><td>2006</td></tr> +<tr><td>Label</td><td>Tompkins Square</td></tr> +<tr><td>ID</td><td>TSQ2839</td></tr> +<tr><td>Total Time</td><td>49:06</td></tr> +<tr><td>Personnel</td><td>Charles Gayle, piano</td></tr> +<tr><td>ADO Rating</td><td>1 star</td></tr> +<tr><td><a href="http://www.allmusic.com/cg/amg.dll?p=amg&sql=10:13rc28vw054a">AMG Rating</a></td><td>4.5 stars</td></tr> +<tr><td> </td></tr> +<tr><td>Artist</td><td>The Get Up Kids</td></tr> +<tr><td>CD</td><td>Eudora</td></tr> +<tr><td>Copyright Date</td><td>2001</td></tr> +<tr><td>Label</td><td>Vagrant</td></tr> +<tr><td>ID</td><td>357</td></tr> +<tr><td>Total Time</td><td>65:12</td></tr> +<tr><td>Notes</td><td>Includes the song "Central Standard Time." Thanks to Colin Bowern for this information.</td></tr> +<tr><td><a href="http://www.allmusic.com/cg/amg.dll?p=amg&sql=10:7ddovwvla9xk">AMG Rating</a></td><td>2.5 stars</td></tr> +<tr><td> </td></tr> <tr><td>Artist</td><td>Jules Verne</td></tr> <tr><td>Book</td><td>Le Tour du Monde en Quatre-Vingts Jours (Around the World in Eighty Days)</td></tr> @@ -173,13 +191,40 @@ is available at <a href="http://fourmilab.ch/etexts/www/tdm80j">http://fourmilab.ch/etexts/www/tdm80j</a> An on-line English-language translation of the book is available at <a href="http://www.literature.org/Works/Jules-Verne/eighty">http://www.literature.org/Works/Jules-Verne/eighty</a></td></tr> + +<tr><td> </td></tr> +<tr><td>Artist</td><td>Umberto Eco</td></tr> +<tr><td>Book</td><td>The Island of the Day Before +(L'isola del giorno prima)</td></tr> +<tr><td>Copyright Date</td><td>1994</td></tr> +<tr><td>Notes</td><td> +"...the story of a 17th century Italian nobleman trapped near an island +on the International Date Line. Time and time zones play an integral +part in the novel." (Paul Eggert, 2006-04-22) +</td></tr> +<tr><td> </td></tr> +<tr><td>Artist</td><td>David Jebb</td></tr> +<tr><td>Book</td><td><a href="http://www.thethirteenthtimezone.com"> +The Thirteenth Time Zone</a></td></tr> +<tr><td>Notes</td><td> +"It's fiction, but it's based on his experiences and travels." (Paul Eggert, 2006-04-22) +</td></tr> +<tr><td> </td></tr> +<tr><td>Artist</td><td>John Dunning</td></tr> +<tr><td>Book</td><td><a +href="http://www.simonsays.com/content/book.cfm?sid=33&pid=479719">Two +O'Clock, Eastern Wartime</a></td></tr> +<tr><td>Copyright Date</td><td>2001</td></tr> +<tr><td>Notes</td><td> +Mystery, history, daylight saving time, and old-time radio. +</td></tr> <tr><td> </td></tr> <tr><td>Film</td><td>Bell Science - About Time</td></tr> <tr><td>Notes</td><td>The Frank Baxter/Richard Deacon extravaganza. Information is available at <a href="http://www.videoflicks.com/titles/1035/1035893.htm">http://www.videoflicks.com/titles/1035/1035893.htm</a></td></tr> </table> -<hr /> +<hr> <ul> <li> An episode of "The Adventures of Superman" entitled "The Mysterious @@ -226,7 +271,7 @@ zones?" was a $32,000 question on the 2001-05-23 United States airing of question should have been asked 2002-06-04. </li> </ul> -<hr /> +<hr> <ul> <li> "We're been using the five-cent nickle in this country since 1492. diff --git a/lib/libc/time/tz-link.htm b/lib/libc/time/tz-link.htm index 17b8d7fbfd6..40867322ac2 100644 --- a/lib/libc/time/tz-link.htm +++ b/lib/libc/time/tz-link.htm @@ -1,25 +1,24 @@ -<?xml version="1.0" encoding="US-ASCII"?> <!DOCTYPE html - PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> + PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> +<html> <head> <title>Sources for Time Zone and Daylight Saving Time Data</title> -<link rel="schema.DC" href="http://purl.org/DC/elements/1.1/" /> -<meta http-equiv="Content-type" content='text/html; charset="US-ASCII"' /> -<meta name="DC.Creator" content="Eggert, Paul" /> -<meta name="DC.Contributor" content="Olson, Arthur David" /> -<meta name="DC.Date" content="2006-01-20" /> +<link rel="schema.DC" href="http://purl.org/DC/elements/1.1/"> +<meta http-equiv="Content-type" content='text/html; charset="US-ASCII"'> +<meta name="DC.Creator" content="Eggert, Paul"> +<meta name="DC.Contributor" content="Olson, Arthur David"> +<meta name="DC.Date" content="2007-01-02"> <meta name="DC.Description" - content="Sources of information about time zones and daylight saving time" /> -<meta name="DC.Identifier" content="http://www.twinsun.com/tz/tz-link.htm" /> + content="Sources of information about time zones and daylight saving time"> +<meta name="DC.Identifier" content="http://www.twinsun.com/tz/tz-link.htm"> <meta name="Keywords" - content="database,daylight saving,DST,time zone,timezone,tz,zoneinfo" /> + content="database,daylight saving,DST,time zone,timezone,tz,zoneinfo"> </head> <body> <h1>Sources for Time Zone and Daylight Saving Time Data</h1> <address> -@(#)tz-link.htm 7.54 +@(#)tz-link.htm 8.9 </address> <p> Please send corrections to this web page to the @@ -36,7 +35,8 @@ href="http://en.wikipedia.org/wiki/Coordinated_Universal_Time"><abbr title="Coordinated Universal Time">UTC</abbr></a> offsets, and <a href="http://en.wikipedia.org/wiki/Daylight_saving">daylight-saving</a> rules. -This database (often called <code>tz</code> or <code>zoneinfo</code>) +This database (often called <code>tz</code> or <a +href="http://en.wikipedia.org/wiki/Zoneinfo"><code>zoneinfo</code></a>) is used by several implementations, including <a href="http://www.gnu.org/software/libc/">the @@ -53,6 +53,7 @@ title="DJ's GNU Programming Platform">DJGPP</abbr></a>, <a href="http://www.sgi.com/developers/technology/irix/">IRIX</a>, <a href="http://www.apple.com/macosx/">Mac OS X</a>, <a href="http://h71000.www7.hp.com/">OpenVMS</a>, +<a href="http://www.oracle.com/database/index.html">Oracle Database</a>, <a href="http://www.sun.com/software/solaris/">Solaris</a>, <a href="http://h30097.www3.hp.com/">Tru64</a>, and <a href="http://www.sco.com/products/unixware/">UnixWare</a>.</p> @@ -101,9 +102,11 @@ location.</p> The data are by no means authoritative. If you find errors, please send changes to the <a href="mailto:tz@elsie.nci.nih.gov">time zone mailing list</a>. You can also <a -href="mailto:tz-request@elsie.nci.nih.gov">subscribe</a> to the -mailing list, retrieve the <a -href="ftp://elsie.nci.nih.gov/pub/tzarchive.gz">archive of old +href="http://news.gmane.org/gmane.comp.time.tz/">browse recent +messages</a> sent to the mailing list, <a +href="mailto:tz-request@elsie.nci.nih.gov">subscribe</a> to it, +retrieve the <a +href="ftp://elsie.nci.nih.gov/pub/tzarchive.gz">full archive of old messages</a> (in gzip compressed format), or retrieve <a href="ftp://munnari.oz.au/pub/oldtz/">archived older versions of code and data</a>; there is also a smaller <a @@ -125,6 +128,8 @@ throughout the world.</li> href="http://www.convertit.com/Go/ConvertIt/World_Time/Current_Time.ASP">Current Time in 1000 Places</a></li> <li><a href="http://timezoneconverter.com/">Time Zone Converter</a></li> +<li><a href="http://home.tiscali.nl/~t876506/TZworld.html">Complete +timezone information for all countries</a></li> </ul></li> <li><a href="http://www.timeanddate.com/worldclock/">The World Clock - Time Zones</a> @@ -144,14 +149,13 @@ covers time zone data; see its VTIMEZONE calendar component. The <a href="http://www.calconnect.org/">Calendaring and Scheduling Consortium</a> is promoting further work in this area. <a -href="ftp://ftp.rfc-editor.org/internet-drafts/draft-royer-ical-basic-04.txt">iCalendar -Basic</a> is a draft simplified definition that omits VTIMEZONE due to -its complexity, but this removal is expected to appear as an -independent specification later.</li> +href="http://www.calconnect.org/publications/icalendartimezoneproblemsandrecommendationsv1.0.pdf">iCalendar +TIMEZONE Problems and Recommendations</a> offers guidelines and +recommendations for the use of VTIMEZONE and <code>tz</code>.</li> <li><a -href="ftp://ftp.rfc-editor.org/internet-drafts/draft-royer-timezone-registry-03.txt">Time -Zone Registry</a> proposes an <a href="http://www.iana.org/"><abbr -title="Internet Assigned Numbers Authority">IANA</abbr></a> time zone +href="http://www.calconnect.org/publications/timezoneregistryandservicerecommendationsv1.0.pdf">Timezone +Registry and Service Recommendations</a> discusses a +strategy for defining and deploying a time zone registration process that would establish unique names for each version of each <code>tz</code> zone, along with a polygonal representation of the geographical area corresponding to the @@ -165,13 +169,6 @@ and group scheduling systems, and has a <a href="http://www.w3.org/2002/12/cal/#tzd">workspace on time zone data</a> converted from <code>tz</code>. An earlier <a href="http://www.w3.org/2000/01/foo">schema</a> was sketched out.</li> -<li><a -href="ftp://ftp.rfc-editor.org/internet-drafts/draft-royer-calsch-xcal-03.txt"><abbr -title="iCalendar in XML Format">xCal-Basic</abbr></a> -is a draft <a -href="http://www.w3.org/XML/"><abbr -title="Extensible Markup Language">XML</abbr></a> document type -definition that corresponds to iCalendar.</li> </ul> <h2>Other <code>tz</code> compilers</h2> <ul> @@ -206,6 +203,10 @@ contains a class <code>org.joda.time.tz.ZoneInfoCompiler</code> that compiles <code>tz</code> source into a Joda-specific binary format. Joda Time is freely available under a <abbr>BSD</abbr>-style license.</li> +<li><a href="http://mozware.free.fr/devtools/xmlDate/">xmlDate</a> +contains <a href="http://www.mozilla.org/js/">JavaScript</a> code that +parses <samp>tz</samp> source into an internal object that represents +a time zone. It is freely available under the GPL.</li> <li><a href="http://sourceforge.net/projects/pytz/">PyTZ - Python Time Zone Library</a> compiles <code>tz</code> source into <a href="http://www.python.org/">Python</a>. @@ -215,6 +216,11 @@ compiles <code>tz</code> source into <a href="http://www.ruby-lang.org/">Ruby</a>. It is freely available under the <abbr title="Massachusetts Institute of Technology">MIT</abbr> license.</li> +<li>Starting with version 8.5, <a href="http://www.tcl.tk/">Tcl</a> +contains a developer-oriented parser that compiles <samp>tz</samp> +source into text files, along with a runtime that can read those +files. Tcl is freely available under a <abbr>BSD</abbr>-style +license.</li> </ul> <h2>Other <code>tz</code> binary file readers</h2> <ul> @@ -231,12 +237,22 @@ and is widely used in <abbr>GNU</abbr>/Linux systems.</li> <li><a href="http://www.bmsi.com/java/#TZ">ZoneInfo.java</a> is a <code>tz</code> binary file reader written in Java. It is freely available under the <abbr>LGPL</abbr>.</li> -<li><a href="http://s.keim.free.fr/tz/doc.html">Python time zones</a> -is a <code>tz</code> binary file reader written in Python. -It is freely available under a <abbr>BSD</abbr>-style license.</li> +<li>Tcl, mentioned above, also contains a +<code>tz</code> binary file reader.</li> </ul> <h2>Other <code>tz</code>-based time zone software</h2> <ul> +<li><a href="http://www.stemhaus.com/firefox/foxclocks/">FoxClocks</a> +is an extension for <a +href="http://developer.mozilla.org/en/docs/Toolkit_API">Mozilla +Toolkit</a> applications like <a +href="http://www.mozilla.com/firefox/">Firefox</a>, <a +href="http://www.mozilla.com/en-US/thunderbird/">Thunderbird</a>, and +<a +href="http://www.mozilla.org/projects/calendar/sunbird/">Sunbird</a>. +It displays multiple clocks in the application window, and has a mapping +interface to <a href="http://earth.google.com/">Google Earth</a>. +It is freely available under the <abbr>GPL</abbr>.</li> <li><a href="http://users.skynet.be/Peter.Verthez/projects/intclock/">International clock (intclock)</a> is a multi-timezone clock for @@ -245,21 +261,21 @@ under the <abbr>GPL</abbr>.</li> <li><a href="http://java.sun.com/">Sun Java</a> releases since 1.4 contain a copy of a subset of a recent <code>tz</code> database in a Java-specific format.</li> -<li><a -href="http://www1.tip.nl/~t876506/AboutTimeZonesHC.html">HyperCard -time zones calculator</a> was a HyperCard stack.</li> +<li><a href="http://kimmo.suominen.com/sw/timezone/">Time Zone</a> is +a <a href="http://wordpress.org/">WordPress</a> plugin. It is freely +available under a <abbr>BSD</abbr>-style license.</li> <li><a href="http://www.veladg.com/velaterra.html">VelaTerra</a> is a Mac OS X program. Its developers <a href="http://www.veladg.com/tzoffer.html">offer free licenses</a> to <code>tz</code> contributors.</li> <li><a -href="http://www.cimmyt.org/timezone/">World Time Explorer</a> is a +href="http://www.worldtimeexplorer.com/index.html">World Time Explorer</a> is a Microsoft Windows program.</li> </ul> <h2>Other time zone databases</h2> <ul> -<li><a href="http://www.astro.com/cgi/aq.cgi?lang=e">Atlas Query</a> +<li><a href="http://www.astro.com/cgi/aq.cgi">Atlas Query</a> is Astrodienst's Web version of Shanks's excellent time zone history atlases published in both <a href="http://astrocom.com/products/software.php?software_id=ibmwboth">computer</a> @@ -284,13 +300,20 @@ Schedules Information Manual</a> of the <a href="http://www.iata.org/index.htm">International Air Transport Association</a> gives current time zone rules for airports served by commercial aviation.</li> +<li>Some Microsoft Windows versions contain time zone information in +an undocumented format, with IDs that can be mapped to <code>TZ</code> +values using the <a +href="http://unicode.org/cldr/data/diff/supplemental/windows_tzid.html">Windows +→ Tzid table</a> maintained by the <abbr +title="Common Locale Data Repository">CLDR</abbr> data mentioned +below.</li> </ul> <h2>Maps</h2> <ul> -<li>The <a href="http://www.odci.gov/">United States Central +<li>The <a href="https://www.cia.gov/">United States Central Intelligence Agency (<abbr title="Central Intelligence Agency">CIA</abbr>)</a> publishes a <a -href="http://www.odci.gov/cia/publications/factbook/reference_maps/pdf/time_zones.pdf">time +href="https://www.cia.gov/cia/publications/factbook/reference_maps/pdf/time_zones.pdf">time zone map</a>; the <a href="http://www.lib.utexas.edu/maps/world.html">Perry-Castañeda @@ -312,7 +335,7 @@ but the maps are more up to date.</li> <li><a href="http://www.statoids.com/statoids.html">Administrative Divisions of Countries ("Statoids")</a> contains detailed lists of <code>tz</code>-related zone subdivision data.</li> -<li><a href="http://home-4.tiscali.nl/~t876506/Multizones.html">Time +<li><a href="http://home.tiscali.nl/~t876506/Multizones.html">Time zone boundaries for multizone countries</a> summarizes legal boundaries between time zones within countries.</li> <li>Manifold.net's <a @@ -356,7 +379,10 @@ Zone Concepts</a> discusses terminological issues behind time zones.</li> <h2>National histories of legal time</h2> <dl> <dt>Australia</dt> -<dd>The Bureau of Metrology publishes a list of +<dd>The Parliamentary Library has commissioned <a +href="http://www.aph.gov.au/LIBRARY/Pubs/rn/2006-07/07rn13.pdf">research +note on daylight saving time in Australia</a>. +The Bureau of Metrology publishes a list of <a href="http://www.bom.gov.au/climate/averages/tables/dst_times.shtml">Implementation Dates of Daylight Savings Time within Australia</a>.</dd> <dt>Austria</dt> <dd>The Federal Office of Metrology and Surveying publishes a @@ -374,13 +400,14 @@ Portuguese)</a>.</dd> <dt>Canada</dt> <dd>The Institute for National Measurement Standards publishes current and some older information about <a -href="http://inms-ienm.nrc-cnrc.gc.ca/en/time_services/daylight_saving_e.php">Time -Zones & Daylight Saving Time</a>.</dd> +href="http://inms-ienm.nrc-cnrc.gc.ca/time_services/daylight_saving_e.html">Time +Zones & Daylight Saving Time</a>. +<a href="http://www3.sympatico.ca/c.walton/canada_dst.html">Canadian +Daylight Saving Regulations</a> summarizes changes for 2007.</dd> <dt>Chile</dt> -<dd>WebExhibits publishes a <a -href="http://webexhibits.org/daylightsaving/chile.html" -hreflang="es">history of official time (in Spanish)</a> originally -written by the Chilean Hydrographic and Oceanographic Service.</dd> +<dd>The Chilean Hydrographic and Oceanographic Service publishes a <a +href="http://www.horaoficial.cl/horaof.htm" hreflang="es"> history of +official time (in Spanish)</a>.</dd> <dt>Germany</dt> <dd>The National Institute for Science and Technology maintains the <a href="http://www.ptb.de/en/org/4/44/441/dars_e.htm">Realisation of @@ -422,7 +449,7 @@ href="http://www.srcf.ucam.org/~jsm28/british-time/">History of legal time in Britain</a> discusses in detail the country with perhaps the best-documented history of clock adjustments. The National Physical Laboratory also maintains an <a -href="http://www.npl.co.uk/time/summer_time_archive.html">Archive +href="http://www.npl.co.uk/time/measurement_time/summer_time_archive.html">Archive of Summer time dates</a>.</dd> </dl> <h2>Precision timekeeping</h2> @@ -436,6 +463,12 @@ title="Network Time Protocol">NTP</abbr>: The Network Time Protocol</a> discusses how to synchronize clocks of Internet hosts.</li> +<li><a +href="ftp://ftp.rfc-editor.org/internet-drafts/draft-ietf-dhc-timezone-option-04.txt">A +Timezone Option for <abbr title="Dynamic Host Configuration Protocol">DHCP</abbr></a> +proposes a <a +href="http://www.dhcp.org/">DHCP</a> option for a server to configure +a client's time zone and daylight saving settings automatically.</li> <li><a href="http://gauss.gge.unb.ca/GMT.UT.and.the.RGO.html">A Few Facts Concerning <abbr title="Greenwich Mean Time">GMT</abbr>, <abbr title="Universal Time">UT</abbr>, and @@ -487,15 +520,13 @@ href="http://www.mail-archive.com/leapsecs@rom.usno.navy.mil/">Leap Second Discussion List</a> and <a href="http://rom.usno.navy.mil/archives/leapsecs.html">archive</a> covers <a href="http://gauss.gge.unb.ca/papers.pdf/gpsworld.november99.pdf">McCarthy -and Klepczynski's proposal to discontinue leap seconds</a>, published in <a -href="http://www.gpsworld.com/gpsworld/"><abbr -title="Global Positioning System">GPS</abbr> World</a> -<strong>10</strong>, 11 -(1999-11), 50–57 and discussed further in R. A. Nelson et al., +and Klepczynski's proposal to discontinue leap seconds</a>, +discussed further in <a href="http://www.cl.cam.ac.uk/~mgk25/time/metrologia-leapsecond.pdf">The -leap second: its history and possible future</a>, -<a href="http://www.bipm.fr/metrologia/index.html">Metrologia</a> -<strong>38</strong> (2001), 509–529. +leap second: its history and possible future</a>. +The <a href="http://www.aas.org/policy/LeapSecondCommittee.html"><abbr +title="American Astronomical Society">AAS</abbr> Leap Second +Committee</a> has solicited input on this proposal. <a href="http://www.ucolick.org/~sla/leapsecs/">The Future of Leap Seconds</a> covers this contentious issue.</li> @@ -512,13 +543,14 @@ title="International Organization for Standardization">ISO</abbr> 8601:2004 -- Data elements and interchange formats -- Information interchange -- Representation of dates and times</a>.</li> <li> -<a href="http://www.w3.org/TR/xmlschema-2/#dateTime"><abbr>XML</abbr> +<a href="http://www.w3.org/TR/xmlschema-2/#dateTime"><abbr +title="Extensible Markup Language">XML</abbr> Schema: Datatypes - dateTime</a> specifies a format inspired by -<abbr>ISO</abbr> 8601 that is in common use in <abbr>XML</abbr> data.</li> +<abbr>ISO</abbr> 8601 that is in common use in <a +href="http://www.w3.org/XML/"><abbr>XML</abbr></a> data.</li> <li> -Section 3.3 of <a -href="ftp://ftp.rfc-editor.org/in-notes/rfc2822.txt">Internet -<abbr title="Request For Comments">RFC</abbr> 2822</a> +<a href="ftp://ftp.rfc-editor.org/in-notes/rfc2822.txt">Internet <abbr +title="Request For Comments">RFC</abbr> 2822</a> §3.3 specifies the time notation used in email and <a href="ftp://ftp.rfc-editor.org/in-notes/rfc2616.txt"><abbr>HTTP</abbr></a> headers.</li> @@ -535,19 +567,16 @@ formats.</li> <a href="http://www.exit109.com/~ghealton/y2k/yrexamples.html">The Best of Dates, the Worst of Dates</a> covers many problems encountered by software developers when handling dates and time stamps.</li> -<li><a -href="http://www-306.ibm.com/software/globalization/icu/"><abbr>ICU</abbr></a> -contains a mechanism for localizing time zone -labels and abbreviations; for example, one can use it to specify -Russian translations for "Eastern European Summer Time", -"<abbr title="Eastern European Summer Time">EEST</abbr>", -and <code>Europe/Bucharest</code>. -This mechanism is part of the -<a href="http://unicode.org/cldr/">Unicode -<abbr title="Common Locale Data Repository">CLDR</abbr> Project</a>; -for example, the <a -href="http://unicode.org/cldr/data/diff/by_type/dates_timeZoneNames.html"><abbr>CLDR</abbr> Sideways Data for dates_timeZoneNames</a> -shows values for time zone names in many locales.</li> +<li>The <a +href="http://unicode.org/cldr/">Unicode Common Locale Data Repository +(<abbr>CLDR</abbr>) Project</a> has localizations for time zone names, +abbreviations, identifiers, and formats. For example, it contains +French translations for "Eastern European Summer Time", "<abbr +title="Eastern European Summer Time">EEST</abbr>", and +"Bucharest". <a +href="http://unicode.org/cldr/data/charts/by_type/names.zone.html">By-Type +Chart: names.zone</a> shows these values for many locales. +<abbr>ICU</abbr> contains a mechanism for using this data.</li> <li>Alphabetic time zone abbreviations should not be used as unique identifiers for <abbr>UTC</abbr> offsets as they are ambiguous in practice. For example, "<abbr>EST</abbr>" denotes 5 hours behind diff --git a/lib/libc/time/tzfile.5 b/lib/libc/time/tzfile.5 index ffe37006b03..806b4276ecc 100644 --- a/lib/libc/time/tzfile.5 +++ b/lib/libc/time/tzfile.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tzfile.5,v 1.9 2006/02/18 21:54:17 millert Exp $ +.\" $OpenBSD: tzfile.5,v 1.10 2007/02/06 19:35:16 millert Exp $ .Dd May 24, 1999 .Dt TZFILE 5 .Os @@ -12,7 +12,9 @@ The time zone information files used by .Xr tzset 3 begin with the magic characters "TZif" to identify themselves as time zone information files, -followed by sixteen bytes reserved for future use, +followed by a character identifying the version of the file's format +(as of 2005, either an ASCII NUL or a '2') +followed by fifteen bytes containing zeroes reserved for future use, followed by six four-byte values of type .Fa long written in a @@ -134,8 +136,18 @@ if either .Fa tzh_timecnt is zero or the time argument is less than the first transition time recorded in the file. +.Pp +For version-2-format time zone files, +the above header and data is followed by a second header and data, +identical in format except that +eight bytes are used for each transition time or leap second time. +After the second header and data comes a newline-encloded, +POSIX-TZ-environment-variable-style string for use in handling instants +after the last transition time stored in the file +(with nothing between the newlines if there is no POSIX representation for +such instants). .Sh SEE ALSO .Xr ctime 3 -.\" @(#)tzfile.5 7.11 +.\" @(#)tzfile.5 8.1 .\" This file is in the public domain, so clarified as of .\" 1996-06-05 by Arthur David Olson. diff --git a/lib/libc/time/tzfile.h b/lib/libc/time/tzfile.h index 2a31ed526a8..c2153817393 100644 --- a/lib/libc/time/tzfile.h +++ b/lib/libc/time/tzfile.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tzfile.h,v 1.7 2006/02/18 21:54:17 millert Exp $ */ +/* $OpenBSD: tzfile.h,v 1.8 2007/02/06 19:35:16 millert Exp $ */ #ifndef TZFILE_H @@ -24,7 +24,7 @@ #if 0 #ifndef lint #ifndef NOID -static char tzfilehid[] = "@(#)tzfile.h 7.18"; +static char tzfilehid[] = "@(#)tzfile.h 8.1"; #endif /* !defined NOID */ #endif /* !defined lint */ #endif @@ -53,7 +53,8 @@ static char tzfilehid[] = "@(#)tzfile.h 7.18"; struct tzhead { char tzh_magic[4]; /* TZ_MAGIC */ - char tzh_reserved[16]; /* reserved for future use */ + char tzh_version[1]; /* '\0' or '2' as of 2005 */ + char tzh_reserved[15]; /* reserved--must be zero */ char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ char tzh_leapcnt[4]; /* coded number of leap seconds */ @@ -88,18 +89,22 @@ struct tzhead { */ /* +** If tzh_version is '2' or greater, the above is followed by a second instance +** of tzhead and a second instance of the data in which each coded transition +** time uses 8 rather than 4 chars, +** then a POSIX-TZ-environment-variable-style string for use in handling +** instants after the last transition time stored in the file +** (with nothing between the newlines if there is no POSIX representation for +** such instants). +*/ + +/* ** In the current implementation, "tzset()" refuses to deal with files that ** exceed any of the limits below. */ #ifndef TZ_MAX_TIMES -/* -** The TZ_MAX_TIMES value below is enough to handle a bit more than a -** year's worth of solar time (corrected daily to the nearest second) or -** 138 years of Pacific Presidential Election time -** (where there are three time zone transitions every fourth year). -*/ -#define TZ_MAX_TIMES 370 +#define TZ_MAX_TIMES 1200 #endif /* !defined TZ_MAX_TIMES */ #ifndef TZ_MAX_TYPES diff --git a/lib/libc/time/tzset.3 b/lib/libc/time/tzset.3 index 1f0c18399e7..579f0389477 100644 --- a/lib/libc/time/tzset.3 +++ b/lib/libc/time/tzset.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tzset.3,v 1.15 2006/02/18 21:54:17 millert Exp $ +.\" $OpenBSD: tzset.3,v 1.16 2007/02/06 19:35:16 millert Exp $ .Dd May 24, 1999 .Dt TZSET 3 .Os @@ -286,6 +286,6 @@ UTC leap seconds are loaded from .Xr strftime 3 , .Xr time 3 , .Xr tzfile 5 -.\" @(#)newtzset.3 7.5 +.\" @(#)newtzset.3 8.1 .\" This file is in the public domain, so clarified as of .\" 2003-02-14 by Arthur David Olson. diff --git a/lib/libc/time/zdump.8 b/lib/libc/time/zdump.8 index 76465be6cd7..ebb6ff3fedb 100644 --- a/lib/libc/time/zdump.8 +++ b/lib/libc/time/zdump.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: zdump.8,v 1.12 2006/02/18 21:54:17 millert Exp $ +.\" $OpenBSD: zdump.8,v 1.13 2007/02/06 19:35:16 millert Exp $ .Dd May 23, 1999 .Dt ZDUMP 8 .Os @@ -54,7 +54,7 @@ values that are neither float nor double. Time discontinuities are found by sampling the results returned by localtime at twelve-hour intervals. This works in all real-world cases; -one can construct artificial time zones for which this fails. +.\" @(#)zdump.8 8.1 .Sh SEE ALSO .Xr ctime 3 , .Xr tzfile 5 , diff --git a/lib/libc/time/zdump.c b/lib/libc/time/zdump.c index 614398641d7..30a8893dfc1 100644 --- a/lib/libc/time/zdump.c +++ b/lib/libc/time/zdump.c @@ -1,8 +1,8 @@ -/* $OpenBSD: zdump.c,v 1.18 2006/02/18 21:54:17 millert Exp $ */ +/* $OpenBSD: zdump.c,v 1.19 2007/02/06 19:35:16 millert Exp $ */ /* ** This file is in the public domain, so clarified as of ** Feb 14, 2003 by Arthur David Olson. -*/ +static char elsieid[] = "@(#)zdump.c 8.3"; /* ** This code has been made independent of the rest of the time @@ -20,7 +20,7 @@ #include "ctype.h" /* for isalpha et al. */ #ifndef isascii #define isascii(x) 1 -#endif +#endif /* !defined isascii */ #ifndef ZDUMP_LO_YEAR #define ZDUMP_LO_YEAR (-500) @@ -135,11 +135,7 @@ #endif /* !defined TZ_DOMAIN */ #ifndef P -#ifdef __STDC__ #define P(x) x -#else /* !defined __STDC__ */ -#define P(x) () -#endif /* !defined __STDC__ */ #endif /* !defined P */ extern char ** environ; @@ -388,7 +384,7 @@ _("usage: %s [-v] [-c [loyear,]hiyear] zonename ...\n"), } if (fflush(stdout) || ferror(stdout)) { (void) fprintf(stderr, "%s: ", progname); - (void) perror(_("Error writing standard output")); + (void) perror(_("Error writing to standard output")); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); @@ -417,14 +413,21 @@ _("%s: use of -v on system with floating time_t other than float or double\n"), } } else if (0 > (time_t) -1) { /* - ** time_t is signed. + ** time_t is signed. Assume overflow wraps around. */ - register time_t hibit; + time_t t = 0; + time_t t1 = 1; - for (hibit = 1; (hibit * 2) != 0; hibit *= 2) - continue; - absolute_min_time = hibit; - absolute_max_time = -(hibit + 1); + while (t < t1) { + t = t1; + t1 = 2 * t1 + 1; + } + + absolute_max_time = t; + t = -t; + absolute_min_time = t - 1; + if (t < absolute_min_time) + absolute_min_time = t; } else { /* ** time_t is unsigned. @@ -467,10 +470,7 @@ const long y; } static time_t -hunt(name, lot, hit) -char * name; -time_t lot; -time_t hit; +hunt(char *name, time_t lot, time_t hit) { time_t t; long diff; @@ -540,10 +540,7 @@ struct tm * oldp; } static void -show(zone, t, v) -char * zone; -time_t t; -int v; +show(char *zone, time_t t, int v) { register struct tm * tmp; diff --git a/lib/libc/time/zic.8 b/lib/libc/time/zic.8 index 8ca931f3d27..895c4208662 100644 --- a/lib/libc/time/zic.8 +++ b/lib/libc/time/zic.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: zic.8,v 1.18 2006/02/18 21:54:17 millert Exp $ +.\" $OpenBSD: zic.8,v 1.19 2007/02/06 19:35:16 millert Exp $ .Dd May 23, 1999 .Dt ZIC 8 .Os @@ -8,7 +8,7 @@ .Sh SYNOPSIS .Nm zic .Bk -words -.Op Fl sv +.Op Fl v .Op Fl d Ar directory .Op Fl L Ar leapsecondfilename .Op Fl l Ar timezone @@ -48,10 +48,6 @@ time zone environment variables. will act as if the input contained a link line of the form .Pp .Dl Link timezone posixrules -.It Fl s -Limit time values stored in output files to values that are the same -whether they're taken to be signed or unsigned. -You can use this option to generate SVVS-compatible files. .It Fl v Complain if a year that appears in a data file is outside the range of years representable by @@ -237,7 +233,7 @@ A zone line has the form .nf .ti +.5i .ta \w'Zone\0\0'u +\w'Australia/Adelaide\0\0'u +\w'GMTOFF\0\0'u +\w'RULES/SAVE\0\0'u +\w'FORMAT\0\0'u -Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL] +Zone NAME GMTOFF RULES/SAVE FORMAT [UNTILYEAR [MONTH [DAY [TIME]]]] .sp For example: .sp @@ -276,15 +272,15 @@ Alternately, a slash .Pq \&/ separates standard and daylight abbreviations. -.It Cm UNTIL +.It Cm UNTILYEAR [MONTH [DAY [TIME]]] The time at which the UTC offset or the rule(s) change for a location. 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 UTC offset and rule change until the time specified. The month, day, and time of day have the same format as the IN, ON, and AT -columns of a rule; trailing columns can be omitted, and default to the -earliest possible value for the missing columns. +fields of a rule; trailing fields can be omitted, and default to the +earliest possible value for the missing fields. .Pp The next line must be a .Dq continuation @@ -293,11 +289,11 @@ string .Dq Zone and the name are omitted, as the continuation line will place information starting at the time specified as the -.Em UNTIL -field in the previous line in the file used by the previous line. -Continuation lines may contain an -.Em UNTIL -field, just as zone lines do, indicating that the next line is a further +.Dq until +information in the previous line in the file used by the previous line. +tion lines may contain +.Dq until +information, just as zone lines do, indicating that the next line is a further continuation. .El .Pp @@ -401,7 +397,7 @@ link to local time zone standard directory used for created files .El .Sh SEE ALSO -.Xr ctime 3 , +.\" @(#)zic.8 8.2 .Xr tzfile 5 , .Xr zdump 8 .\" @(#)zic.8 7.24 diff --git a/lib/libc/time/zic.c b/lib/libc/time/zic.c index df293bf052b..ec09225454a 100644 --- a/lib/libc/time/zic.c +++ b/lib/libc/time/zic.c @@ -1,19 +1,21 @@ -/* $OpenBSD: zic.c,v 1.26 2006/02/18 21:54:17 millert Exp $ */ +/* $OpenBSD: zic.c,v 1.27 2007/02/06 19:35:16 millert Exp $ */ /* ** This file is in the public domain, so clarified as of -** Feb 14, 2003 by Arthur David Olson. +** 2006-07-17 by Arthur David Olson. */ -/* -** Regardless of the type of time_t, we do our work using this type. -*/ - -typedef int zic_t; - #include "private.h" #include "locale.h" #include "tzfile.h" +#ifdef notyet +#define ZIC_VERSION '2' +#else +#define ZIC_VERSION '\0' +#endif + +typedef int_fast64_t zic_t; + #ifndef ZIC_MAX_ABBR_LEN_WO_WARN #define ZIC_MAX_ABBR_LEN_WO_WARN 6 #endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */ @@ -24,7 +26,7 @@ typedef int zic_t; #ifdef S_IRUSR #define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) #else -#define MKDIR_UMASK 0755 +#define MKDIR_UMASK 0755 #endif /* @@ -40,6 +42,11 @@ typedef int zic_t; #define isascii(x) 1 #endif +#define OFFSET_STRLEN_MAXIMUM (7 + INT_STRLEN_MAXIMUM(long)) +#define RULE_STRLEN_MAXIMUM 8 /* "Mdd.dd.d" */ + +#define end(cp, n) (memchr((cp), '\0', (n))) + struct rule { const char * r_filename; int r_linenum; @@ -48,6 +55,8 @@ struct rule { int r_loyear; /* for example, 1986 */ int r_hiyear; /* for example, 1986 */ const char * r_yrtype; + int r_lowasnum; + int r_hiwasnum; int r_month; /* 0..11 */ @@ -107,9 +116,10 @@ static void adjleap P((void)); static void associate P((void)); static int ciequal P((const char * ap, const char * bp)); static void convert P((long val, char * buf)); +static void convert64 P((zic_t val, char * buf)); static void dolink P((const char * fromfile, const char * tofile)); static void doabbr P((char * abbr, size_t size, const char * format, - const char * letters, int isdst)); + const char * letters, int isdst, int doquotes)); static void eat P((const char * name, int num)); static void eats P((const char * name, int num, const char * rname, int rnum)); @@ -125,6 +135,7 @@ static void inrule P((char ** fields, int nfields)); static int inzcont P((char ** fields, int nfields)); static int inzone P((char ** fields, int nfields)); static int inzsub P((char ** fields, int nfields, int iscont)); +static int is32 P((zic_t x)); static int itsabbr P((const char * abbr, const char * word)); static int itsdir P((const char * name)); static int lowerit P((int c)); @@ -134,16 +145,22 @@ static void newabbr P((const char * abbr)); static long oadd P((long t1, long t2)); static void outzone P((const struct zone * zp, int ntzones)); static void puttzcode P((long code, FILE * fp)); +static void puttzcode64 P((zic_t code, FILE * fp)); static int rcomp P((const void * leftp, const void * rightp)); static zic_t rpytime P((const struct rule * rp, int wantedy)); static void rulesub P((struct rule * rp, const char * loyearp, const char * hiyearp, const char * typep, const char * monthp, const char * dayp, const char * timep)); +static int stringoffset P((char * result, size_t size, long offset)); +static int stringrule P((char * result, size_t size, const struct rule * rp, + long dstoff, long gmtoff)); +static void stringzone P((char * result, size_t size, + const struct zone * zp, int ntzones)); static void setboundaries P((void)); static zic_t tadd P((zic_t t1, long t2)); static void usage P((void)); -static void writezone P((const char * name)); +static void writezone P((const char * name, const char * string)); static int yearistype P((int year, const char * type)); #if !HAVE_STRERROR @@ -154,13 +171,16 @@ static int charcnt; static int errors; static const char * filename; static int leapcnt; +static int leapseen; +static int leapminyear; +static int leapmaxyear; static int linenum; +static int max_abbrvar_len; +static int max_format_len; static zic_t max_time; static int max_year; -static int max_year_representable; static zic_t min_time; static int min_year; -static int min_year_representable; static int noise; static const char * rfilename; static int rlinenum; @@ -456,7 +476,7 @@ const char * const string; static void usage P((void)) { - (void) fprintf(stderr, _("usage: %s [-sv] [-d directory] [-L leapsecondfilename] [-l timezone]\n\t[-p timezone] [-y command] [filename ...]\n"), + (void) fprintf(stderr, _("usage: %s [-v] [-d directory] [-L leapsecondfilename] [-l timezone]\n\t[-p timezone] [-y command] [filename ...]\n"), progname); exit(EXIT_FAILURE); } @@ -466,7 +486,6 @@ static const char * lcltime; static const char * directory; static const char * leapsec; static const char * yitcommand; -static int sflag = FALSE; int main(argc, argv) @@ -488,7 +507,12 @@ char * argv[]; (void) textdomain(TZ_DOMAIN); #endif /* HAVE_GETTEXT */ progname = argv[0]; - while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != -1) + if (TYPE_BIT(zic_t) < 64) { + (void) fprintf(stderr, "%s: %s\n", progname, + _("wild compilation-time specification of zic_t")); + exit(EXIT_FAILURE); + } + while ((c = getopt(argc, argv, "d:l:p:L:vy:")) != -1) switch (c) { default: usage(); @@ -545,9 +569,6 @@ _("%s: More than one -L option specified\n"), case 'v': noise = TRUE; break; - case 's': - sflag = TRUE; - break; } if (optind == argc - 1 && strcmp(argv[optind], "=") == 0) usage(); /* usage message by request */ @@ -637,7 +658,7 @@ const char * const tofile; #if HAVE_SYMLINK if (result != 0 && errno == EXDEV) result = symlink(fromname, toname); -#endif +#endif /* HAVE_SYMLINK */ if (result != 0) { const char *e = strerror(errno); @@ -651,54 +672,17 @@ const char * const tofile; ifree(toname); } -#ifndef INT_MAX -#define INT_MAX ((int) (((unsigned)~0)>>1)) -#endif /* !defined INT_MAX */ - -#ifndef INT_MIN -#define INT_MIN ((int) ~(((unsigned)~0)>>1)) -#endif /* !defined INT_MIN */ - -/* -** The tz file format currently allows at most 32-bit quantities. -** This restriction should be removed before signed 32-bit values -** wrap around in 2038, but unfortunately this will require a -** change to the tz file format. -*/ - -#define MAX_BITS_IN_FILE 32 -#define TIME_T_BITS_IN_FILE ((TYPE_BIT(zic_t) < MAX_BITS_IN_FILE) ? \ - TYPE_BIT(zic_t) : MAX_BITS_IN_FILE) +#define TIME_T_BITS_IN_FILE 64 static void setboundaries P((void)) { register int i; - if (TYPE_SIGNED(zic_t)) { - min_time = -1; - for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i) - min_time *= 2; - max_time = -(min_time + 1); - if (sflag) - min_time = 0; - } else { - min_time = 0; - max_time = 2 - sflag; - for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i) - max_time *= 2; - --max_time; - } - { - time_t t; - - t = (time_t) min_time; - min_year = TM_YEAR_BASE + gmtime(&t)->tm_year; - t = (time_t) max_time; - max_year = TM_YEAR_BASE + gmtime(&t)->tm_year; - } - min_year_representable = min_year; - max_year_representable = max_year; + min_time = -1; + for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i) + min_time *= 2; + max_time = -(min_time + 1); } static int @@ -973,6 +957,8 @@ const int nfields; fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]); r.r_name = ecpyalloc(fields[RF_NAME]); r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]); + if (max_abbrvar_len < strlen(r.r_abbrvar)) + max_abbrvar_len = strlen(r.r_abbrvar); rules = (struct rule *) (void *) erealloc((char *) rules, (int) ((nrules + 1) * sizeof *rules)); rules[nrules++] = r; @@ -1081,6 +1067,8 @@ const int iscont; } z.z_rule = ecpyalloc(fields[i_rule]); z.z_format = ecpyalloc(fields[i_format]); + if (max_format_len < strlen(z.z_format)) + max_format_len = strlen(z.z_format); hasuntil = nfields > i_untilyear; if (hasuntil) { z.z_untilrule.r_filename = filename; @@ -1142,6 +1130,11 @@ const int nfields; error(_("invalid leaping year")); return; } + if (!leapseen || leapmaxyear < year) + leapmaxyear = year; + if (!leapseen || leapminyear > year) + leapminyear = year; + leapseen = TRUE; j = EPOCH_YEAR; while (j != year) { if (year > j) { @@ -1296,7 +1289,8 @@ const char * const timep; */ cp = loyearp; lp = byword(cp, begin_years); - if (lp != NULL) switch ((int) lp->l_value) { + rp->r_lowasnum = lp == NULL; + if (!rp->r_lowasnum) switch ((int) lp->l_value) { case YR_MINIMUM: rp->r_loyear = INT_MIN; break; @@ -1311,14 +1305,11 @@ const char * const timep; } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) { error(_("invalid starting year")); return; - } else if (noise) { - if (rp->r_loyear < min_year_representable) - warning(_("starting year too low to be represented")); - else if (rp->r_loyear > max_year_representable) - warning(_("starting year too high to be represented")); } cp = hiyearp; - if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) { + lp = byword(cp, end_years); + rp->r_hiwasnum = lp == NULL; + if (!rp->r_hiwasnum) switch ((int) lp->l_value) { case YR_MINIMUM: rp->r_hiyear = INT_MIN; break; @@ -1336,11 +1327,6 @@ const char * const timep; } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) { error(_("invalid ending year")); return; - } else if (noise) { - if (rp->r_loyear < min_year_representable) - warning(_("ending year too low to be represented")); - else if (rp->r_loyear > max_year_representable) - warning(_("ending year too high to be represented")); } if (rp->r_loyear > rp->r_hiyear) { error(_("starting year greater than ending year")); @@ -1355,8 +1341,6 @@ const char * const timep; } rp->r_yrtype = ecpyalloc(typep); } - if (rp->r_loyear < min_year && rp->r_loyear > 0) - min_year = rp->r_loyear; /* ** Day work. ** Accept things such as: @@ -1410,13 +1394,25 @@ const long val; char * const buf; { register int i; - register long shift; + register int shift; for (i = 0, shift = 24; i < 4; ++i, shift -= 8) buf[i] = val >> shift; } static void +convert64(val, buf) +const zic_t val; +char * const buf; +{ + register int i; + register int shift; + + for (i = 0, shift = 56; i < 8; ++i, shift -= 8) + buf[i] = val >> shift; +} + +static void puttzcode(val, fp) const long val; FILE * const fp; @@ -1427,29 +1423,51 @@ FILE * const fp; (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp); } +static void +puttzcode64(val, fp) +const zic_t val; +FILE * const fp; +{ + char buf[8]; + + convert64(val, buf); + (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp); +} + static int atcomp(avp, bvp) -void * avp; -void * bvp; +const void * avp; +const void * bvp; { - if (((struct attype *) avp)->at < ((struct attype *) bvp)->at) - return -1; - else if (((struct attype *) avp)->at > ((struct attype *) bvp)->at) - return 1; - else return 0; + const zic_t a = ((const struct attype *) avp)->at; + const zic_t b = ((const struct attype *) bvp)->at; + + return (a < b) ? -1 : (a > b); +} + +static int +is32(x) +const zic_t x; +{ + return INT32_MIN <= x && x <= INT32_MAX; } static void -writezone(name) +writezone(name, string) const char * const name; +const char * const string; { - register FILE * fp; - register int i, j; - static char * fullname; - static struct tzhead tzh; - zic_t ats[TZ_MAX_TIMES]; - unsigned char types[TZ_MAX_TIMES]; - size_t len; + register FILE * fp; + register int i, j; + register int leapcnt32, leapi32; + register int timecnt32, timei32; + register int pass; + static char * fullname; + static const struct tzhead tzh0; + static struct tzhead tzh; + zic_t ats[TZ_MAX_TIMES]; + unsigned char types[TZ_MAX_TIMES]; + size_t len; /* ** Sort. @@ -1493,9 +1511,38 @@ const char * const name; ats[i] = attypes[i].at; types[i] = attypes[i].type; } + /* + ** Correct for leap seconds. + */ + for (i = 0; i < timecnt; ++i) { + j = leapcnt; + while (--j >= 0) + if (ats[i] > trans[j] - corr[j]) { + ats[i] = tadd(ats[i], corr[j]); + break; + } + } + /* + ** Figure out 32-bit-limited starts and counts. + */ + timecnt32 = timecnt; + timei32 = 0; + leapcnt32 = leapcnt; + leapi32 = 0; + while (timecnt32 > 0 && !is32(ats[timecnt32 - 1])) + --timecnt32; + while (timecnt32 > 0 && !is32(ats[timei32])) { + --timecnt32; + ++timei32; + } + while (leapcnt32 > 0 && !is32(trans[leapcnt32 - 1])) + --leapcnt32; + while (leapcnt32 > 0 && !is32(trans[leapi32])) { + --leapcnt32; + ++leapi32; + } len = strlen(directory) + 1 + strlen(name) + 1; fullname = erealloc(fullname, len); - (void) snprintf(fullname, len, "%s/%s", directory, name); /* ** Remove old file, if any, to snap links. @@ -1518,67 +1565,156 @@ const char * const name; exit(EXIT_FAILURE); } } - convert(eitol(typecnt), tzh.tzh_ttisgmtcnt); - convert(eitol(typecnt), tzh.tzh_ttisstdcnt); - convert(eitol(leapcnt), tzh.tzh_leapcnt); - convert(eitol(timecnt), tzh.tzh_timecnt); - convert(eitol(typecnt), tzh.tzh_typecnt); - convert(eitol(charcnt), tzh.tzh_charcnt); - (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); +#ifdef notyet + for (pass = 1; pass <= 2; ++pass) { +#else + pass = 1; { +#endif + register int thistimei, thistimecnt; + register int thisleapi, thisleapcnt; + register int thistimelim, thisleaplim; + int writetype[TZ_MAX_TIMES]; + int typemap[TZ_MAX_TYPES]; + register int thistypecnt; + char thischars[TZ_MAX_CHARS]; + char thischarcnt; + int indmap[TZ_MAX_CHARS]; + + if (pass == 1) { + thistimei = timei32; + thistimecnt = timecnt32; + thisleapi = leapi32; + thisleapcnt = leapcnt32; + } else { + thistimei = 0; + thistimecnt = timecnt; + thisleapi = 0; + thisleapcnt = leapcnt; + } + thistimelim = thistimei + thistimecnt; + thisleaplim = thisleapi + thisleapcnt; + for (i = 0; i < typecnt; ++i) + writetype[i] = thistimecnt == timecnt; + if (thistimecnt == 0) { + /* + ** No transition times fall in the current + ** (32- or 64-bit) window. + */ + if (typecnt != 0) + writetype[typecnt - 1] = TRUE; + } else { + for (i = thistimei - 1; i < thistimelim; ++i) + if (i >= 0) + writetype[types[i]] = TRUE; + /* + ** For America/Godthab and Antarctica/Palmer + */ + if (thistimei == 0) + writetype[0] = TRUE; + } + thistypecnt = 0; + for (i = 0; i < typecnt; ++i) + typemap[i] = writetype[i] ? thistypecnt++ : -1; + for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i) + indmap[i] = -1; + thischarcnt = 0; + for (i = 0; i < typecnt; ++i) { + register char * thisabbr; + + if (!writetype[i]) + continue; + if (indmap[abbrinds[i]] >= 0) + continue; + thisabbr = &chars[abbrinds[i]]; + for (j = 0; j < thischarcnt; ++j) + if (strcmp(&thischars[j], thisabbr) == 0) + break; + if (j == thischarcnt) { + (void) strlcpy(&thischars[(int) thischarcnt], + thisabbr, sizeof(thischars) - thischarcnt); + thischarcnt += strlen(thisabbr) + 1; + } + indmap[abbrinds[i]] = j; + } #define DO(field) (void) fwrite((void *) tzh.field, \ (size_t) sizeof tzh.field, (size_t) 1, fp) - DO(tzh_magic); - DO(tzh_reserved); - DO(tzh_ttisgmtcnt); - DO(tzh_ttisstdcnt); - DO(tzh_leapcnt); - DO(tzh_timecnt); - DO(tzh_typecnt); - DO(tzh_charcnt); + tzh = tzh0; + (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); + tzh.tzh_version[0] = ZIC_VERSION; + convert(eitol(thistypecnt), tzh.tzh_ttisgmtcnt); + convert(eitol(thistypecnt), tzh.tzh_ttisstdcnt); + convert(eitol(thisleapcnt), tzh.tzh_leapcnt); + convert(eitol(thistimecnt), tzh.tzh_timecnt); + convert(eitol(thistypecnt), tzh.tzh_typecnt); + convert(eitol(thischarcnt), tzh.tzh_charcnt); + DO(tzh_magic); + DO(tzh_version); + DO(tzh_reserved); + DO(tzh_ttisgmtcnt); + DO(tzh_ttisstdcnt); + DO(tzh_leapcnt); + DO(tzh_timecnt); + DO(tzh_typecnt); + DO(tzh_charcnt); #undef DO - for (i = 0; i < timecnt; ++i) { - j = leapcnt; - while (--j >= 0) - if (ats[i] >= trans[j]) { - ats[i] = tadd(ats[i], corr[j]); - break; - } - puttzcode((long) ats[i], fp); - } - if (timecnt > 0) - (void) fwrite((void *) types, (size_t) sizeof types[0], - (size_t) timecnt, fp); - for (i = 0; i < typecnt; ++i) { - puttzcode((long) gmtoffs[i], fp); - (void) putc(isdsts[i], fp); - (void) putc(abbrinds[i], fp); - } - if (charcnt != 0) - (void) fwrite((void *) chars, (size_t) sizeof chars[0], - (size_t) charcnt, fp); - for (i = 0; i < leapcnt; ++i) { - if (roll[i]) { - if (timecnt == 0 || trans[i] < ats[0]) { - j = 0; - while (isdsts[j]) - if (++j >= typecnt) { - j = 0; - break; - } - } else { - j = 1; - while (j < timecnt && trans[i] >= ats[j]) - ++j; - j = types[j - 1]; + for (i = thistimei; i < thistimelim; ++i) + if (pass == 1) + puttzcode((long) ats[i], fp); + else puttzcode64(ats[i], fp); + for (i = thistimei; i < thistimelim; ++i) { + unsigned char uc; + + uc = typemap[types[i]]; + (void) fwrite((void *) &uc, + (size_t) sizeof uc, + (size_t) 1, + fp); + } + for (i = 0; i < typecnt; ++i) + if (writetype[i]) { + puttzcode(gmtoffs[i], fp); + (void) putc(isdsts[i], fp); + (void) putc((unsigned char) indmap[abbrinds[i]], fp); } - puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp); - } else puttzcode((long) trans[i], fp); - puttzcode((long) corr[i], fp); - } - for (i = 0; i < typecnt; ++i) - (void) putc(ttisstds[i], fp); - for (i = 0; i < typecnt; ++i) - (void) putc(ttisgmts[i], fp); + if (thischarcnt != 0) + (void) fwrite((void *) thischars, + (size_t) sizeof thischars[0], + (size_t) thischarcnt, fp); + for (i = thisleapi; i < thisleaplim; ++i) { + register zic_t todo; + + if (roll[i]) { + if (timecnt == 0 || trans[i] < ats[0]) { + j = 0; + while (isdsts[j]) + if (++j >= typecnt) { + j = 0; + break; + } + } else { + j = 1; + while (j < timecnt && + trans[i] >= ats[j]) + ++j; + j = types[j - 1]; + } + todo = tadd(trans[i], -gmtoffs[j]); + } else todo = trans[i]; + if (pass == 1) + puttzcode((long) todo, fp); + else puttzcode64(todo, fp); + puttzcode(corr[i], fp); + } + for (i = 0; i < typecnt; ++i) + if (writetype[i]) + (void) putc(ttisstds[i], fp); + for (i = 0; i < typecnt; ++i) + if (writetype[i]) + (void) putc(ttisgmts[i], fp); + } +#ifdef notyet + (void) fprintf(fp, "\n%s\n", string); +#endif if (ferror(fp) || fclose(fp)) { (void) fprintf(stderr, _("%s: Error writing %s\n"), progname, fullname); @@ -1587,22 +1723,240 @@ const char * const name; } static void -doabbr(abbr, size, format, letters, isdst) +doabbr(abbr, size, format, letters, isdst, doquotes) char * const abbr; size_t size; const char * const format; const char * const letters; const int isdst; +const int doquotes; { - if (strchr(format, '/') == NULL) { + register char * cp; + register char * slashp; + register int len; + + slashp = strchr(format, '/'); + if (slashp == NULL) { if (letters == NULL) - strlcpy(abbr, format, size); - else snprintf(abbr, size, format, letters); - } else if (isdst) - strlcpy(abbr, strchr(format, '/') + 1, size); - else { - strlcpy(abbr, format, size); - *strchr(abbr, '/') = '\0'; + (void) strlcpy(abbr, format, size); + else (void) snprintf(abbr, size, format, letters); + } else if (isdst) { + (void) strlcpy(abbr, slashp + 1, size); + } else { + if (slashp - format + 1 < size) + size = slashp - format + 1; + (void) strlcpy(abbr, format, size); + } + if (!doquotes) + return; + for (cp = abbr; *cp != '\0'; ++cp) + if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", *cp) == NULL && + strchr("abcdefghijklmnopqrstuvwxyz", *cp) == NULL) + break; + len = strlen(abbr); + if (len > 0 && *cp == '\0') + return; + abbr[len + 2] = '\0'; + abbr[len + 1] = '>'; + for ( ; len > 0; --len) + abbr[len] = abbr[len - 1]; + abbr[0] = '<'; +} + +static void +updateminmax(x) +const int x; +{ + if (min_year > x) + min_year = x; + if (max_year < x) + max_year = x; +} + +static int +stringoffset(result, size, offset) +char * result; +size_t size; +long offset; +{ + register int hours; + register int minutes; + register int seconds; + register char * ep; + + result[0] = '\0'; + if (offset < 0) { + (void) strlcpy(result, "-", size); + offset = -offset; + } + seconds = offset % SECSPERMIN; + offset /= SECSPERMIN; + minutes = offset % MINSPERHOUR; + offset /= MINSPERHOUR; + hours = offset; + if (hours >= HOURSPERDAY) { + result[0] = '\0'; + return -1; + } + ep = end(result, size); + (void) snprintf(ep, size - (ep - result), "%d", hours); + if (minutes != 0 || seconds != 0) { + ep = end(result, size); + (void) snprintf(ep, size - (ep - result), ":%02d", minutes); + if (seconds != 0) { + ep = end(result, size); + (void) snprintf(ep, size - (ep - result), ":%02d", seconds); + } + } + return 0; +} + +static int +stringrule(result, size, rp, dstoff, gmtoff) +char * result; +size_t size; +const struct rule * const rp; +const long dstoff; +const long gmtoff; +{ + register long tod; + register char * ep; + + ep = end(result, size); + size -= ep - result; + result = ep; + if (rp->r_dycode == DC_DOM) { + register int month, total; + + if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY) + return -1; + total = 0; + for (month = 0; month < rp->r_month; ++month) + total += len_months[0][month]; + (void) snprintf(result, size, "J%d", total + rp->r_dayofmonth); + } else { + register int week; + + if (rp->r_dycode == DC_DOWGEQ) { + week = 1 + rp->r_dayofmonth / DAYSPERWEEK; + if ((week - 1) * DAYSPERWEEK + 1 != rp->r_dayofmonth) + return -1; + } else if (rp->r_dycode == DC_DOWLEQ) { + if (rp->r_dayofmonth == len_months[1][rp->r_month]) + week = 5; + else { + week = 1 + rp->r_dayofmonth / DAYSPERWEEK; + if (week * DAYSPERWEEK - 1 != rp->r_dayofmonth) + return -1; + } + } else return -1; /* "cannot happen" */ + (void) snprintf(result, size, "M%d.%d.%d", + rp->r_month + 1, week, rp->r_wday); + } + tod = rp->r_tod; + if (rp->r_todisgmt) + tod += gmtoff; + if (rp->r_todisstd && rp->r_stdoff == 0) + tod += dstoff; + if (tod < 0) { + result[0] = '\0'; + return -1; + } + if (tod != 2 * SECSPERMIN * MINSPERHOUR) { + (void) strlcat(result, "/", size); + ep = end(result, size); + if (stringoffset(ep, size - (ep - result), tod) != 0) + return -1; + } + return 0; +} + +static void +stringzone(result, size, zpfirst, zonecount) +char * result; +size_t size; +const struct zone * const zpfirst; +const int zonecount; +{ + register const struct zone * zp; + register struct rule * rp; + register struct rule * stdrp; + register struct rule * dstrp; + register int i; + register const char * abbrvar; + register char * ep; + + result[0] = '\0'; + zp = zpfirst + zonecount - 1; + stdrp = dstrp = NULL; + for (i = 0; i < zp->z_nrules; ++i) { + rp = &zp->z_rules[i]; + if (rp->r_hiwasnum || rp->r_hiyear != INT_MAX) + continue; + if (rp->r_yrtype != NULL) + continue; + if (rp->r_stdoff == 0) { + if (stdrp == NULL) + stdrp = rp; + else return; + } else { + if (dstrp == NULL) + dstrp = rp; + else return; + } + } + if (stdrp == NULL && dstrp == NULL) { + /* + ** There are no rules running through "max". + ** Let's find the latest rule. + */ + for (i = 0; i < zp->z_nrules; ++i) { + rp = &zp->z_rules[i]; + if (stdrp == NULL || rp->r_hiyear > stdrp->r_hiyear || + (rp->r_hiyear == stdrp->r_hiyear && + rp->r_month > stdrp->r_month)) + stdrp = rp; + } + if (stdrp != NULL && stdrp->r_stdoff != 0) + return; /* We end up in DST (a POSIX no-no). */ + /* + ** Horrid special case: if year is 2037, + ** presume this is a zone handled on a year-by-year basis; + ** do not try to apply a rule to the zone. + */ + if (stdrp != NULL && stdrp->r_hiyear == 2037) + return; + } + if (stdrp == NULL && zp->z_nrules != 0) + return; + abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar; + doabbr(result, size, zp->z_format, abbrvar, FALSE, TRUE); + ep = end(result, size); + if (stringoffset(ep, size - (ep - result), -zp->z_gmtoff) != 0) { + result[0] = '\0'; + return; + } + if (dstrp == NULL) + return; + ep = end(result, size); + doabbr(ep, size - (ep - result), zp->z_format, dstrp->r_abbrvar, TRUE, TRUE); + if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR) { + ep = end(result, size); + if (stringoffset(ep, size - (ep - result), + -(zp->z_gmtoff + dstrp->r_stdoff)) != 0) { + result[0] = '\0'; + return; + } + } + (void) strlcat(result, ",", size); + if (stringrule(result, size, dstrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) { + result[0] = '\0'; + return; + } + (void) strlcat(result, ",", size); + if (stringrule(result, size, stdrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) { + result[0] = '\0'; + return; } } @@ -1623,8 +1977,17 @@ const int zonecount; register int startttisstd; register int startttisgmt; register int type; - char startbuf[BUFSIZ]; - + register char * startbuf; + register char * ab; + register char * envvar; + register int max_abbr_len; + register int max_envvar_len; + + max_abbr_len = 2 + max_format_len + max_abbrvar_len; + max_envvar_len = 2 * max_abbr_len + 5 * 9; + startbuf = emalloc(max_abbr_len + 1); + ab = emalloc(max_abbr_len + 1); + envvar = emalloc(max_envvar_len + 1); INITIALIZE(untiltime); INITIALIZE(starttime); /* @@ -1639,6 +2002,48 @@ const int zonecount; */ startttisstd = FALSE; startttisgmt = FALSE; + min_year = max_year = EPOCH_YEAR; + if (leapseen) { + updateminmax(leapminyear); + updateminmax(leapmaxyear); + } + for (i = 0; i < zonecount; ++i) { + zp = &zpfirst[i]; + updateminmax(zp->z_untilrule.r_loyear); + for (j = 0; j < zp->z_nrules; ++j) { + rp = &zp->z_rules[j]; + if (rp->r_lowasnum) + updateminmax(rp->r_loyear); + if (rp->r_hiwasnum) + updateminmax(rp->r_hiyear); + } + } + /* + ** Generate lots of data if a rule can't cover all future times. + */ + stringzone(envvar, max_envvar_len + 1, zpfirst, zonecount); + if (noise && envvar[0] == '\0') { + register char * wp; + +wp = ecpyalloc(_("no POSIX environment variable for zone")); + wp = ecatalloc(wp, " "); + wp = ecatalloc(wp, zpfirst->z_name); + warning(wp); + ifree(wp); + } + if (envvar[0] == '\0') { + if (min_year >= INT_MIN + YEARSPERREPEAT) + min_year -= YEARSPERREPEAT; + else min_year = INT_MIN; + if (max_year <= INT_MAX - YEARSPERREPEAT) + max_year += YEARSPERREPEAT; + else max_year = INT_MAX; + } + /* + ** For the benefit of older systems, generate data through 2037. + */ + if (max_year < 2037) + max_year = 2037; for (i = 0; i < zonecount; ++i) { /* ** A guess that may well be corrected later. @@ -1655,8 +2060,8 @@ const int zonecount; startoff = zp->z_gmtoff; if (zp->z_nrules == 0) { stdoff = zp->z_stdoff; - doabbr(startbuf, sizeof(startbuf), zp->z_format, - (char *) NULL, stdoff != 0); + doabbr(startbuf, max_abbr_len + 1, zp->z_format, + (char *) NULL, stdoff != 0, FALSE); type = addtype(oadd(zp->z_gmtoff, stdoff), startbuf, stdoff != 0, startttisstd, startttisgmt); @@ -1686,7 +2091,6 @@ const int zonecount; register int k; register zic_t jtime, ktime; register long offset; - char buf[BUFSIZ]; INITIALIZE(ktime); if (useuntil) { @@ -1741,27 +2145,32 @@ const int zonecount; startoff = oadd(zp->z_gmtoff, stdoff); doabbr(startbuf, - sizeof(startbuf), + max_abbr_len + 1, zp->z_format, rp->r_abbrvar, - rp->r_stdoff != 0); + rp->r_stdoff != 0, + FALSE); continue; } if (*startbuf == '\0' && - startoff == oadd(zp->z_gmtoff, - stdoff)) - doabbr(startbuf, - sizeof(startbuf), - zp->z_format, - rp->r_abbrvar, - rp->r_stdoff != 0); + startoff == oadd(zp->z_gmtoff, + stdoff)) { + doabbr(startbuf, + max_abbr_len + 1, + zp->z_format, + rp->r_abbrvar, + rp->r_stdoff != + 0, + FALSE); + } } eats(zp->z_filename, zp->z_linenum, rp->r_filename, rp->r_linenum); - doabbr(buf, sizeof(buf), zp->z_format, - rp->r_abbrvar, rp->r_stdoff != 0); + doabbr(ab, max_abbr_len + 1, zp->z_format, + rp->r_abbrvar, + rp->r_stdoff != 0, FALSE); offset = oadd(zp->z_gmtoff, rp->r_stdoff); - type = addtype(offset, buf, rp->r_stdoff != 0, + type = addtype(offset, ab, rp->r_stdoff != 0, rp->r_todisstd, rp->r_todisgmt); addtt(ktime, type); } @@ -1771,8 +2180,8 @@ const int zonecount; zp->z_format != NULL && strchr(zp->z_format, '%') == NULL && strchr(zp->z_format, '/') == NULL) - strlcpy(startbuf, zp->z_format, - sizeof(startbuf)); + (void) strlcpy(startbuf, zp->z_format, + max_abbr_len + 1); eat(zp->z_filename, zp->z_linenum); if (*startbuf == '\0') error(_("can't determine time zone abbreviation to use just after until time")); @@ -1795,7 +2204,10 @@ error(_("can't determine time zone abbreviation to use just after until time")); starttime = tadd(starttime, -gmtoff); } } - writezone(zpfirst->z_name); + writezone(zpfirst->z_name, envvar); + ifree(startbuf); + ifree(ab); + ifree(envvar); } static void @@ -1803,14 +2215,18 @@ addtt(starttime, type) const zic_t starttime; int type; { + size_t len; + if (starttime <= min_time || (timecnt == 1 && attypes[0].at < min_time)) { gmtoffs[0] = gmtoffs[type]; isdsts[0] = isdsts[type]; ttisstds[0] = ttisstds[type]; ttisgmts[0] = ttisgmts[type]; - if (abbrinds[type] != 0) - strlcpy(chars, &chars[abbrinds[type]], sizeof(chars)); + if (abbrinds[type] != 0) { + len = strlen(&chars[abbrinds[type]]) + 1; + (void) memmove(chars, &chars[abbrinds[type]], len); + } abbrinds[0] = 0; charcnt = strlen(chars) + 1; typecnt = 1; @@ -2176,8 +2592,6 @@ register const int wantedy; will not work with pre-2004 versions of zic")); } } - if (dayoff < 0 && !TYPE_SIGNED(zic_t)) - return min_time; if (dayoff < min_time / SECSPERDAY) return min_time; if (dayoff > max_time / SECSPERDAY) @@ -2235,7 +2649,7 @@ wp = _("time zone abbreviation differs from POSIX standard"); error(_("too many, or too long, time zone abbreviations")); exit(EXIT_FAILURE); } - strlcpy(&chars[charcnt], string, sizeof(chars) - charcnt); + (void) strlcpy(&chars[charcnt], string, sizeof(chars) - charcnt); charcnt += eitol(i); } |