diff options
| author | Ulrich Drepper <drepper@redhat.com> | 2006-11-11 02:05:42 +0000 |
|---|---|---|
| committer | Ulrich Drepper <drepper@redhat.com> | 2006-11-11 02:05:42 +0000 |
| commit | 064737fb74ac2a47916b9be162a6a098cde99816 (patch) | |
| tree | b1b2838f61216fc8378445bfc8fa291d32ae7b0f | |
| parent | 6decd24cc22116dea9da17c548d0ea0e9b6d5bfc (diff) | |
| download | glibc-064737fb74ac2a47916b9be162a6a098cde99816.tar.xz glibc-064737fb74ac2a47916b9be162a6a098cde99816.zip | |
* time/tzfile.c (__tzfile_read): Extend to handle new file format
on machines with 64-bit time_t.
* timezone/checktab.awk: Update from tzcode2006o.
* timezone/ialloc.c: Likewise.
* timezone/private.h: Likewise.
* timezone/scheck.: Likewise.
* timezone/tzfile.h: Likewise.
* timezone/tzselect.ksh: Likewise.
* timezone/zdump.c: Likewise.
* timezone/zic.c: Likewise.
| -rw-r--r-- | ChangeLog | 12 | ||||
| -rw-r--r-- | time/tzfile.c | 112 | ||||
| -rw-r--r-- | timezone/checktab.awk | 2 | ||||
| -rw-r--r-- | timezone/ialloc.c | 7 | ||||
| -rw-r--r-- | timezone/private.h | 83 | ||||
| -rw-r--r-- | timezone/scheck.c | 7 | ||||
| -rw-r--r-- | timezone/tzfile.h | 23 | ||||
| -rw-r--r-- | timezone/tzselect.ksh | 2 | ||||
| -rw-r--r-- | timezone/zdump.c | 39 | ||||
| -rw-r--r-- | timezone/zic.c | 709 |
10 files changed, 756 insertions, 240 deletions
@@ -1,5 +1,17 @@ 2006-11-10 Ulrich Drepper <drepper@redhat.com> + * time/tzfile.c (__tzfile_read): Extend to handle new file format + on machines with 64-bit time_t. + + * timezone/checktab.awk: Update from tzcode2006o. + * timezone/ialloc.c: Likewise. + * timezone/private.h: Likewise. + * timezone/scheck.: Likewise. + * timezone/tzfile.h: Likewise. + * timezone/tzselect.ksh: Likewise. + * timezone/zdump.c: Likewise. + * timezone/zic.c: Likewise. + [BZ #3483] * elf/ldconfig.c (main): Call setlocale and textdomain. Patch mostly by Benno Schulenberg <bensberg@justemail.net>. diff --git a/time/tzfile.c b/time/tzfile.c index e95fd55f36..295f0aa3cb 100644 --- a/time/tzfile.c +++ b/time/tzfile.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1991-1993,1995-2001,2003,2004 Free Software Foundation, Inc. +/* Copyright (C) 1991-1993,1995-2001,2003,2004,2006 + Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -71,24 +72,34 @@ static inline int __attribute ((always_inline)) decode (const void *ptr) { - if ((BYTE_ORDER == BIG_ENDIAN) && sizeof (int) == 4) + if (BYTE_ORDER == BIG_ENDIAN && sizeof (int) == 4) return *(const int *) ptr; - else if (BYTE_ORDER == LITTLE_ENDIAN && sizeof (int) == 4) + if (sizeof (int) == 4) return bswap_32 (*(const int *) ptr); - else - { - const unsigned char *p = ptr; - int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0; - result = (result << 8) | *p++; - result = (result << 8) | *p++; - result = (result << 8) | *p++; - result = (result << 8) | *p++; + const unsigned char *p = ptr; + int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0; - return result; - } + result = (result << 8) | *p++; + result = (result << 8) | *p++; + result = (result << 8) | *p++; + result = (result << 8) | *p++; + + return result; } + +static inline int64_t +__attribute ((always_inline)) +decode64 (const void *ptr) +{ + if ((BYTE_ORDER == BIG_ENDIAN)) + return *(const int64_t *) ptr; + + return bswap_64 (*(const int64_t *) ptr); +} + + void __tzfile_read (const char *file, size_t extra, char **extrap) { @@ -102,6 +113,10 @@ __tzfile_read (const char *file, size_t extra, char **extrap) size_t types_idx; size_t leaps_idx; int was_using_tzfile = __use_tzfile; + int trans_width = 4; + + if (sizeof (time_t) != 4 && sizeof (time_t) != 8) + abort (); __use_tzfile = 0; @@ -185,8 +200,10 @@ __tzfile_read (const char *file, size_t extra, char **extrap) /* No threads reading this stream. */ __fsetlocking (f, FSETLOCKING_BYCALLER); + read_again: if (__builtin_expect (fread_unlocked ((void *) &tzhead, sizeof (tzhead), - 1, f) != 1, 0)) + 1, f) != 1, 0) + || memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic)) != 0) goto lose; num_transitions = (size_t) decode (tzhead.tzh_timecnt); @@ -196,6 +213,26 @@ __tzfile_read (const char *file, size_t extra, char **extrap) num_isstd = (size_t) decode (tzhead.tzh_ttisstdcnt); num_isgmt = (size_t) decode (tzhead.tzh_ttisgmtcnt); + /* For platforms with 64-bit time_t we use the new format if available. */ + if (sizeof (time_t) == 8 && trans_width == 4 + && tzhead.tzh_version[0] != '\0') + { + /* We use the 8-byte format. */ + trans_width = 8; + + /* Position the stream before the second header. */ + size_t to_skip = (num_transitions * (4 + 1) + + num_types * 6 + + chars + + num_leaps * 8 + + num_isstd + + num_isgmt); + if (fseek (f, to_skip, SEEK_CUR) != 0) + goto lose; + + goto read_again; + } + total_size = num_transitions * (sizeof (time_t) + 1); total_size = ((total_size + __alignof__ (struct ttinfo) - 1) & ~(__alignof__ (struct ttinfo) - 1)); @@ -205,10 +242,10 @@ __tzfile_read (const char *file, size_t extra, char **extrap) & ~(__alignof__ (struct leap) - 1)); leaps_idx = total_size; total_size += num_leaps * sizeof (struct leap); - /* This is for the extra memory required by the caller. */ - total_size += extra; - transitions = (time_t *) malloc (total_size); + /* Allocate enough memory including the extra block requested by the + caller. */ + transitions = (time_t *) malloc (total_size + extra); if (transitions == NULL) goto lose; @@ -220,14 +257,11 @@ __tzfile_read (const char *file, size_t extra, char **extrap) if (extra > 0) *extrap = (char *) &leaps[num_leaps]; - if (sizeof (time_t) < 4) - abort (); - - if (sizeof (time_t) == 4) + if (sizeof (time_t) == 4 || trans_width == 8) { - if (__builtin_expect (fread_unlocked (transitions, 1, - (4 + 1) * num_transitions, f) - != (4 + 1) * num_transitions, 0)) + if (__builtin_expect (fread_unlocked (transitions, trans_width + 1, + num_transitions, f) + != num_transitions, 0)) goto lose; } else @@ -245,7 +279,7 @@ __tzfile_read (const char *file, size_t extra, char **extrap) if (__builtin_expect (type_idxs[i] >= num_types, 0)) goto lose; - if (BYTE_ORDER != BIG_ENDIAN || sizeof (time_t) != 4) + if (BYTE_ORDER != BIG_ENDIAN || (sizeof (time_t) == 8 && trans_width == 4)) { /* Decode the transition times, stored as 4-byte integers in network (big-endian) byte order. We work from the end of @@ -255,6 +289,13 @@ __tzfile_read (const char *file, size_t extra, char **extrap) while (i-- > 0) transitions[i] = decode ((char *) transitions + i * 4); } + else if (BYTE_ORDER != BIG_ENDIAN && sizeof (time_t) == 8) + { + /* Decode the transition times, stored as 8-byte integers in + network (big-endian) byte order. */ + for (i = 0; i < num_transitions; ++i) + transitions[i] = decode64 ((char *) transitions + i * 8); + } for (i = 0; i < num_types; ++i) { @@ -280,13 +321,16 @@ __tzfile_read (const char *file, size_t extra, char **extrap) for (i = 0; i < num_leaps; ++i) { - unsigned char x[4]; - if (__builtin_expect (fread_unlocked (x, 1, sizeof (x), f) != sizeof (x), - 0)) + unsigned char x[8]; + if (__builtin_expect (fread_unlocked (x, 1, trans_width, f) + != trans_width, 0)) goto lose; - leaps[i].transition = (time_t) decode (x); - if (__builtin_expect (fread_unlocked (x, 1, sizeof (x), f) != sizeof (x), - 0)) + if (sizeof (time_t) == 4 || trans_width == 4) + leaps[i].transition = (time_t) decode (x); + else + leaps[i].transition = (time_t) decode64 (x); + + if (__builtin_expect (fread_unlocked (x, 1, 4, f) != 4, 0)) goto lose; leaps[i].change = (long int) decode (x); } @@ -311,6 +355,12 @@ __tzfile_read (const char *file, size_t extra, char **extrap) while (i < num_types) types[i++].isgmt = 0; + /* XXX When a version 2 file is available it can contain a POSIX TZ-style + formatted string which specifies how times past the last one specified + are supposed to be handled. We might want to handle this at some + point. But it might be overhead since most/all? files have an + open-ended last entry. */ + fclose (f); /* First "register" all timezone names. */ diff --git a/timezone/checktab.awk b/timezone/checktab.awk index 6d532141e6..80ad7d5701 100644 --- a/timezone/checktab.awk +++ b/timezone/checktab.awk @@ -1,6 +1,6 @@ # Check tz tables for consistency. -# @(#)checktab.awk 1.7 +# @(#)checktab.awk 8.1 # Contributed by Paul Eggert. diff --git a/timezone/ialloc.c b/timezone/ialloc.c index 8a0c701578..1fc2035f45 100644 --- a/timezone/ialloc.c +++ b/timezone/ialloc.c @@ -1,6 +1,11 @@ +/* +** This file is in the public domain, so clarified as of +** 2006-07-17 by Arthur David Olson. +*/ + #ifndef lint #ifndef NOID -static char elsieid[] = "@(#)ialloc.c 8.29"; +static char elsieid[] = "@(#)ialloc.c 8.30"; #endif /* !defined NOID */ #endif /* !defined lint */ diff --git a/timezone/private.h b/timezone/private.h index d9f232c8e3..2837b70c10 100644 --- a/timezone/private.h +++ b/timezone/private.h @@ -21,7 +21,7 @@ #ifndef lint #ifndef NOID -static char privatehid[] = "@(#)private.h 7.55"; +static char privatehid[] = "@(#)private.h 8.2"; #endif /* !defined NOID */ #endif /* !defined lint */ @@ -89,7 +89,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" @@ -125,20 +125,51 @@ static char privatehid[] = "@(#)private.h 7.55"; #define is_digit(c) ((unsigned)(c) - '0' <= 9) /* +** Define HAVE_STDINT_H's default value here, rather than at the +** start, since __GLIBC__'s value depends on previously-included +** files. +** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.) +*/ +#ifndef HAVE_STDINT_H +#define HAVE_STDINT_H \ + (199901 <= __STDC_VERSION__ || \ + 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__))) +#endif /* !defined HAVE_STDINT_H */ + +#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 */ /* @@ -211,14 +242,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. @@ -310,6 +341,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/timezone/scheck.c b/timezone/scheck.c index bc156379a0..74d9b07c14 100644 --- a/timezone/scheck.c +++ b/timezone/scheck.c @@ -1,6 +1,11 @@ +/* +** This file is in the public domain, so clarified as of +** 2006-07-17 by Arthur David Olson. +*/ + #ifndef lint #ifndef NOID -static char elsieid[] = "@(#)scheck.c 8.17"; +static char elsieid[] = "@(#)scheck.c 8.19"; #endif /* !defined lint */ #endif /* !defined NOID */ diff --git a/timezone/tzfile.h b/timezone/tzfile.h index fb6ca9880f..3a9eee305a 100644 --- a/timezone/tzfile.h +++ b/timezone/tzfile.h @@ -21,7 +21,7 @@ #ifndef lint #ifndef NOID -static char tzfilehid[] = "@(#)tzfile.h 7.18"; +static char tzfilehid[] = "@(#)tzfile.h 8.1"; #endif /* !defined NOID */ #endif /* !defined lint */ @@ -49,7 +49,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 */ @@ -84,18 +85,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/timezone/tzselect.ksh b/timezone/tzselect.ksh index f6e28bfdab..b99af8273b 100644 --- a/timezone/tzselect.ksh +++ b/timezone/tzselect.ksh @@ -1,6 +1,6 @@ #! @KSH@ -# '@(#)tzselect.ksh 1.8' +# '@(#)tzselect.ksh 8.1' # Ask the user about the time zone, and output the resulting TZ value to stdout. # Interact with the user via stderr and stdin. diff --git a/timezone/zdump.c b/timezone/zdump.c index d525da1bae..b5dd09b861 100644 --- a/timezone/zdump.c +++ b/timezone/zdump.c @@ -1,4 +1,4 @@ -static char elsieid[] = "@(#)zdump.c 7.74"; +static char elsieid[] = "@(#)zdump.c 8.2"; /* ** This code has been made independent of the rest of the time @@ -15,7 +15,7 @@ static char elsieid[] = "@(#)zdump.c 7.74"; #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) @@ -130,11 +130,7 @@ static char elsieid[] = "@(#)zdump.c 7.74"; #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; @@ -389,7 +385,7 @@ _("%s: usage is %s [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"), } if (fflush(stdout) || ferror(stdout)) { (void) fprintf(stderr, "%s: ", progname); - (void) perror(_("Error writing to standard output")); + (void) perror(_("Error writing standard output")); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); @@ -418,14 +414,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. @@ -468,10 +471,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; @@ -541,10 +541,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/timezone/zic.c b/timezone/zic.c index acb76fb3ba..f7393ea7ba 100644 --- a/timezone/zic.c +++ b/timezone/zic.c @@ -1,15 +1,18 @@ -static char elsieid[] = "@(#)zic.c 7.128"; - /* -** Regardless of the type of time_t, we do our work using this type. +** This file is in the public domain, so clarified as of +** 2006-07-17 by Arthur David Olson. */ -typedef int zic_t; +static char elsieid[] = "@(#)zic.c 8.7"; #include "private.h" #include "locale.h" #include "tzfile.h" +#define ZIC_VERSION '2' + +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 */ @@ -36,6 +39,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) (strchr((cp), '\0')) + struct rule { const char * r_filename; int r_linenum; @@ -44,6 +52,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 */ @@ -103,9 +113,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, 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)); @@ -121,6 +132,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)); @@ -130,16 +142,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, long offset)); +static int stringrule P((char * result, const struct rule * rp, + long dstoff, long gmtoff)); +static void stringzone P((char * result, + 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 writezo |
