From a76a349e949dfad5716eb3893052070b770e949f Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 4 Jun 2003 20:09:47 +0000 Subject: [PATCH] Ensure we use gnulib mktime rather than glibc's mktime, on hosts where mktime isn't the inverse of localtime (negative time_t). --- config/ChangeLog | 5 ++ config/srclist.txt | 5 +- lib/ChangeLog | 4 ++ lib/mktime.c | 16 +---- m4/ChangeLog | 2 + m4/mktime.m4 | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 197 insertions(+), 19 deletions(-) diff --git a/config/ChangeLog b/config/ChangeLog index 2af1c3691..5aaea7a02 100644 --- a/config/ChangeLog +++ b/config/ChangeLog @@ -1,3 +1,8 @@ +2003-06-04 Paul Eggert + + * srclist.txt ($LIBCSRC/time/mktime.c lib gpl): Comment out for now, + as glibc mktime is buggy on non-glibc systems. + 2003-06-03 * config.sub: update from prep. diff --git a/config/srclist.txt b/config/srclist.txt index a73c57254..ba200c1d9 100644 --- a/config/srclist.txt +++ b/config/srclist.txt @@ -1,4 +1,4 @@ -# $Id: srclist.txt,v 1.13 2003-06-03 12:55:44 karl Exp $ +# $Id: srclist.txt,v 1.14 2003-06-04 20:09:47 eggert Exp $ # Files for which we are not the source. See ./srclistvars.sh for the # variable definitions. @@ -27,7 +27,8 @@ $LIBCSRC/posix/getopt.h lib gpl $LIBCSRC/posix/getopt1.c lib gpl $LIBCSRC/posix/regex.h lib gpl $LIBCSRC/string/strdup.c lib gpl -$LIBCSRC/time/mktime.c lib gpl +# This can be uncommented after libc mktime is fixed. +#$LIBCSRC/time/mktime.c lib gpl # # - libc/sysdeps/generic has memcpy.c, memmove.c, strcasecmp.c, but they # are totally different implementations. diff --git a/lib/ChangeLog b/lib/ChangeLog index 21b402ffa..3a3cc847f 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,5 +1,9 @@ 2003-06-04 Paul Eggert + * mktime.c (__mktime_internal): Do not reject negative timestamps + arbitrarily. This is the same patch as 2003-05-28, but it got lost + in the 2003-05-30 sync from glibc. + .h files should stand alone, but we shouldn't include if we can get away with just . diff --git a/lib/mktime.c b/lib/mktime.c index a4f4e3bfd..107dbbf36 100644 --- a/lib/mktime.c +++ b/lib/mktime.c @@ -1,5 +1,5 @@ /* Convert a `struct tm' to a time_t value. - Copyright (C) 1993-1999, 2002 Free Software Foundation, Inc. + Copyright (C) 1993-1999, 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Paul Eggert (eggert@twinsun.com). @@ -264,12 +264,6 @@ __mktime_internal (struct tm *tp, int sec_requested = sec; - /* Only years after 1970 are defined. - If year is 69, it might still be representable due to - timezone differences. */ - if (year < 69) - return -1; - #if LEAP_SECONDS_POSSIBLE /* Handle out-of-range seconds specially, since ydhms_tm_diff assumes every minute has 60 seconds. */ @@ -377,14 +371,6 @@ __mktime_internal (struct tm *tp, return -1; } - if (year == 69) - { - /* If year was 69, need to check whether the time was representable - or not. */ - if (t < 0 || t > 2 * 24 * 60 * 60) - return -1; - } - *tp = tm; return t; } diff --git a/m4/ChangeLog b/m4/ChangeLog index 6c397347d..a822bada0 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,5 +1,7 @@ 2003-06-04 Paul Eggert + * mktime.m4 (AC_FUNC_MKTIME): New macro, taken from Autoconf CVS. + It can be removed after the next Autoconf is released. * exclude.m4 (gl_EXCLUDE): Don't check for sys/types.h; no loner needed. diff --git a/m4/mktime.m4 b/m4/mktime.m4 index 94468eefa..2131cff4f 100644 --- a/m4/mktime.m4 +++ b/m4/mktime.m4 @@ -1,5 +1,5 @@ -# mktime.m4 serial 1 -dnl Copyright (C) 2002 Free Software Foundation, Inc. +# mktime.m4 serial 2 +dnl Copyright (C) 2002, 2003 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program @@ -8,6 +8,186 @@ dnl the same distribution terms as the rest of that program. dnl From Jim Meyering. +# Redefine AC_FUNC_MKTIME, to fix a bug in Autoconf 2.57 and earlier. +# This redefinition can be removed once a new version of Autoconf comes out. +# The redefinition is taken from +# . +# AC_FUNC_MKTIME +# -------------- +AC_DEFUN([AC_FUNC_MKTIME], +[AC_REQUIRE([AC_HEADER_TIME])dnl +AC_CHECK_HEADERS(stdlib.h sys/time.h unistd.h) +AC_CHECK_FUNCS(alarm) +AC_CACHE_CHECK([for working mktime], ac_cv_func_working_mktime, +[AC_RUN_IFELSE([AC_LANG_SOURCE( +[[/* Test program from Paul Eggert and Tony Leneis. */ +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#if HAVE_STDLIB_H +# include +#endif + +#if HAVE_UNISTD_H +# include +#endif + +#if !HAVE_ALARM +# define alarm(X) /* empty */ +#endif + +/* Work around redefinition to rpl_putenv by other config tests. */ +#undef putenv + +static time_t time_t_max; +static time_t time_t_min; + +/* Values we'll use to set the TZ environment variable. */ +static char *tz_strings[] = { + (char *) 0, "TZ=GMT0", "TZ=JST-9", + "TZ=EST+3EDT+2,M10.1.0/00:00:00,M2.3.0/00:00:00" +}; +#define N_STRINGS (sizeof (tz_strings) / sizeof (tz_strings[0])) + +/* Fail if mktime fails to convert a date in the spring-forward gap. + Based on a problem report from Andreas Jaeger. */ +static void +spring_forward_gap () +{ + /* glibc (up to about 1998-10-07) failed this test. */ + struct tm tm; + + /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0" + instead of "TZ=America/Vancouver" in order to detect the bug even + on systems that don't support the Olson extension, or don't have the + full zoneinfo tables installed. */ + putenv ("TZ=PST8PDT,M4.1.0,M10.5.0"); + + tm.tm_year = 98; + tm.tm_mon = 3; + tm.tm_mday = 5; + tm.tm_hour = 2; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_isdst = -1; + if (mktime (&tm) == (time_t)-1) + exit (1); +} + +static void +mktime_test1 (now) + time_t now; +{ + struct tm *lt; + if ((lt = localtime (&now)) && mktime (lt) != now) + exit (1); +} + +static void +mktime_test (now) + time_t now; +{ + mktime_test1 (now); + mktime_test1 ((time_t) (time_t_max - now)); + mktime_test1 ((time_t) (time_t_min + now)); +} + +static void +irix_6_4_bug () +{ + /* Based on code from Ariel Faigon. */ + struct tm tm; + tm.tm_year = 96; + tm.tm_mon = 3; + tm.tm_mday = 0; + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_isdst = -1; + mktime (&tm); + if (tm.tm_mon != 2 || tm.tm_mday != 31) + exit (1); +} + +static void +bigtime_test (j) + int j; +{ + struct tm tm; + time_t now; + tm.tm_year = tm.tm_mon = tm.tm_mday = tm.tm_hour = tm.tm_min = tm.tm_sec = j; + now = mktime (&tm); + if (now != (time_t) -1) + { + struct tm *lt = localtime (&now); + if (! (lt + && lt->tm_year == tm.tm_year + && lt->tm_mon == tm.tm_mon + && lt->tm_mday == tm.tm_mday + && lt->tm_hour == tm.tm_hour + && lt->tm_min == tm.tm_min + && lt->tm_sec == tm.tm_sec + && lt->tm_yday == tm.tm_yday + && lt->tm_wday == tm.tm_wday + && ((lt->tm_isdst < 0 ? -1 : 0 < lt->tm_isdst) + == (tm.tm_isdst < 0 ? -1 : 0 < tm.tm_isdst)))) + exit (1); + } +} + +int +main () +{ + time_t t, delta; + int i, j; + + /* This test makes some buggy mktime implementations loop. + Give up after 60 seconds; a mktime slower than that + isn't worth using anyway. */ + alarm (60); + + for (time_t_max = 1; 0 < time_t_max; time_t_max *= 2) + continue; + time_t_max--; + if ((time_t) -1 < 0) + for (time_t_min = -1; (time_t) (time_t_min * 2) < 0; time_t_min *= 2) + continue; + delta = time_t_max / 997; /* a suitable prime number */ + for (i = 0; i < N_STRINGS; i++) + { + if (tz_strings[i]) + putenv (tz_strings[i]); + + for (t = 0; t <= time_t_max - delta; t += delta) + mktime_test (t); + mktime_test ((time_t) 1); + mktime_test ((time_t) (60 * 60)); + mktime_test ((time_t) (60 * 60 * 24)); + + for (j = 1; 0 < j; j *= 2) + bigtime_test (j); + bigtime_test (j - 1); + } + irix_6_4_bug (); + spring_forward_gap (); + exit (0); +}]])], + [ac_cv_func_working_mktime=yes], + [ac_cv_func_working_mktime=no], + [ac_cv_func_working_mktime=no])]) +if test $ac_cv_func_working_mktime = no; then + AC_LIBOBJ([mktime]) +fi +])# AC_FUNC_MKTIME + AC_DEFUN([gl_FUNC_MKTIME], [ AC_REQUIRE([AC_FUNC_MKTIME]) -- 2.11.0