diff options
Diffstat (limited to 'time')
-rw-r--r-- | time/Makefile | 5 | ||||
-rw-r--r-- | time/strptime_l.c | 11 | ||||
-rw-r--r-- | time/tst-strptime3.c | 55 | ||||
-rw-r--r-- | time/tzfile.c | 114 |
4 files changed, 88 insertions, 97 deletions
diff --git a/time/Makefile b/time/Makefile index 8ce34e4565..d93b84bb2f 100644 --- a/time/Makefile +++ b/time/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991-2003, 2004, 2005, 2007 Free Software Foundation, Inc. +# Copyright (C) 1991-2003, 2004, 2005 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 @@ -35,8 +35,7 @@ distribute := datemsk tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \ tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \ - tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1 \ - tst-strptime3 + tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1 include ../Rules diff --git a/time/strptime_l.c b/time/strptime_l.c index 443a6fa88e..dc0cc686fd 100644 --- a/time/strptime_l.c +++ b/time/strptime_l.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2004, 2005, 2007 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2004, 2005 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 @@ -400,7 +400,6 @@ __strptime_internal (rp, fmt, tm, decided, era_cnt LOCALE_PARAM) /* Does not match a month name. */ return NULL; tm->tm_mon = cnt; - have_mon = 1; want_xday = 1; break; case 'c': @@ -1086,15 +1085,11 @@ __strptime_internal (rp, fmt, tm, decided, era_cnt LOCALE_PARAM) tm->tm_mday = (tm->tm_yday - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1); - have_mon = 1; - have_mday = 1; } - /* Don't crash in day_of_the_week if tm_mon is uninitialized. */ - if (have_mon || (unsigned) tm->tm_mon <= 11) - day_of_the_week (tm); + day_of_the_week (tm); } - if (want_xday && !have_yday && (have_mon || (unsigned) tm->tm_mon <= 11)) + if (want_xday && !have_yday) day_of_the_year (tm); if ((have_uweek || have_wweek) && have_wday) diff --git a/time/tst-strptime3.c b/time/tst-strptime3.c deleted file mode 100644 index 9a8c6485e7..0000000000 --- a/time/tst-strptime3.c +++ /dev/null @@ -1,55 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - - -int -main (void) -{ - int result = 0; - struct tm tm; - - memset (&tm, 0xaa, sizeof (tm)); - - /* Test we don't crash on uninitialized struct tm. - Some fields might contain bogus values until everything - needed is initialized, but we shouldn't crash. */ - if (strptime ("2007", "%Y", &tm) == NULL - || strptime ("12", "%d", &tm) == NULL - || strptime ("Feb", "%b", &tm) == NULL - || strptime ("13", "%M", &tm) == NULL - || strptime ("21", "%S", &tm) == NULL - || strptime ("16", "%H", &tm) == NULL) - { - puts ("strptimes failed"); - result = 1; - } - - if (tm.tm_sec != 21 || tm.tm_min != 13 || tm.tm_hour != 16 - || tm.tm_mday != 12 || tm.tm_mon != 1 || tm.tm_year != 107 - || tm.tm_wday != 1 || tm.tm_yday != 42) - { - puts ("unexpected tm content"); - result = 1; - } - - if (strptime ("8", "%d", &tm) == NULL) - { - puts ("strptime failed"); - result = 1; - } - - if (tm.tm_sec != 21 || tm.tm_min != 13 || tm.tm_hour != 16 - || tm.tm_mday != 8 || tm.tm_mon != 1 || tm.tm_year != 107 - || tm.tm_wday != 4 || tm.tm_yday != 38) - { - puts ("unexpected tm content"); - result = 1; - } - - if (result == 0) - puts ("all OK"); - - return 0; -} diff --git a/time/tzfile.c b/time/tzfile.c index e95fd55f36..ea2d7cae4c 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,9 @@ __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) == 4 || trans_width == 4)) + || (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 +291,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 +323,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 +357,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. */ |