From 948ea7a98bccf1ca837e75b5ea71b67365367ec4 Mon Sep 17 00:00:00 2001 From: "Michael G. Schwern" Date: Mon, 29 Sep 2008 11:05:17 -0400 Subject: Update from y2038 Work around a system that doesn't have gm/localtime_r(). This replaces Perl's own gm/localtime() wrapper which couldn't be called outside a PP anyway because it needs my_perl. --- localtime64.c | 44 +++++++++++++++++++++++++++++++++++++++++--- localtime64.h | 19 +++++++++++++++++++ reentr.c | 12 ------------ reentr.h | 43 ++++++------------------------------------- reentr.pl | 7 +------ 5 files changed, 67 insertions(+), 58 deletions(-) diff --git a/localtime64.c b/localtime64.c index 72bd68f0f2..176cc407d2 100644 --- a/localtime64.c +++ b/localtime64.c @@ -258,6 +258,40 @@ int _safe_year(Year year) } +/* Simulate localtime_r() to the best of our ability */ +struct tm * fake_localtime_r(const time_t *clock, struct tm *result) { + const struct tm *static_result = localtime(clock); + + assert(result != NULL); + + if( static_result == NULL ) { + memset(result, 0, sizeof(*result)); + return NULL; + } + else { + memcpy(result, static_result, sizeof(*result)); + return result; + } +} + + +/* Simulate gmtime_r() to the best of our ability */ +struct tm * fake_gmtime_r(const time_t *clock, struct tm *result) { + const struct tm *static_result = gmtime(clock); + + assert(result != NULL); + + if( static_result == NULL ) { + memset(result, 0, sizeof(*result)); + return NULL; + } + else { + memcpy(result, static_result, sizeof(*result)); + return result; + } +} + + struct tm *gmtime64_r (const Time64_T *in_time, struct tm *p) { int v_tm_sec, v_tm_min, v_tm_hour, v_tm_mon, v_tm_wday; @@ -267,10 +301,12 @@ struct tm *gmtime64_r (const Time64_T *in_time, struct tm *p) Time64_T time = *in_time; Year year = 70; + assert(p != NULL); + /* Use the system gmtime() if time_t is small enough */ if( SHOULD_USE_SYSTEM_GMTIME(*in_time) ) { time_t safe_time = *in_time; - gmtime_r(&safe_time, p); + GMTIME_R(&safe_time, p); assert(_check_tm(p)); return p; } @@ -379,10 +415,12 @@ struct tm *localtime64_r (const Time64_T *time, struct tm *local_tm) Year orig_year; int month_diff; + assert(local_tm != NULL); + /* Use the system localtime() if time_t is small enough */ if( SHOULD_USE_SYSTEM_LOCALTIME(*time) ) { safe_time = *time; - localtime_r(&safe_time, local_tm); + LOCALTIME_R(&safe_time, local_tm); assert(_check_tm(local_tm)); return local_tm; } @@ -400,7 +438,7 @@ struct tm *localtime64_r (const Time64_T *time, struct tm *local_tm) } safe_time = TIMEGM(&gm_tm); - if( localtime_r(&safe_time, local_tm) == NULL ) + if( LOCALTIME_R(&safe_time, local_tm) == NULL ) return NULL; local_tm->tm_year = orig_year; diff --git a/localtime64.h b/localtime64.h index 37719775ac..db8ddbf1ea 100644 --- a/localtime64.h +++ b/localtime64.h @@ -4,6 +4,12 @@ /* Configuration. */ /* Define as appropriate for your system */ /* + HAS_GMTIME_R + Defined if your system has gmtime_r() + + HAS_LOCALTIME_R + Defined if your system has localtime_r() + HAS_TIMEGM Defined if your system has timegm() @@ -43,4 +49,17 @@ struct tm *gmtime64_r (const Time64_T *, struct tm *); struct tm *localtime64_r (const Time64_T *, struct tm *); Time64_T timegm64 (struct tm *); + +/* Not everyone has gm/localtime_r() */ +#ifdef HAS_LOCALTIME_R +# define LOCALTIME_R(clock, result) localtime_r(clock, result) +#else +# define LOCALTIME_R(clock, result) fake_localtime_r(clock, result) +#endif +#ifdef HAS_GMTIME_R +# define GMTIME_R(clock, result) gmtime_r(clock, result) +#else +# define GMTIME_R(clock, result) fake_gmtime_r(clock, result) +#endif + #endif diff --git a/reentr.c b/reentr.c index 25fccf858b..8d9ab2a2c1 100644 --- a/reentr.c +++ b/reentr.c @@ -115,10 +115,6 @@ Perl_reentrant_size(pTHX) { # endif # endif #endif /* HAS_GETSPNAM_R */ -#ifdef HAS_GMTIME_R -#endif /* HAS_GMTIME_R */ -#ifdef HAS_LOCALTIME_R -#endif /* HAS_LOCALTIME_R */ #ifdef HAS_RANDOM_R #endif /* HAS_RANDOM_R */ #ifdef HAS_READDIR_R @@ -205,10 +201,6 @@ Perl_reentrant_init(pTHX) { # endif Newx(PL_reentrant_buffer->_spent_buffer, PL_reentrant_buffer->_spent_size, char); #endif /* HAS_GETSPNAM_R */ -#ifdef HAS_GMTIME_R -#endif /* HAS_GMTIME_R */ -#ifdef HAS_LOCALTIME_R -#endif /* HAS_LOCALTIME_R */ #ifdef HAS_RANDOM_R #endif /* HAS_RANDOM_R */ #ifdef HAS_READDIR_R @@ -280,10 +272,6 @@ Perl_reentrant_free(pTHX) { #ifdef HAS_GETSPNAM_R Safefree(PL_reentrant_buffer->_spent_buffer); #endif /* HAS_GETSPNAM_R */ -#ifdef HAS_GMTIME_R -#endif /* HAS_GMTIME_R */ -#ifdef HAS_LOCALTIME_R -#endif /* HAS_LOCALTIME_R */ #ifdef HAS_RANDOM_R #endif /* HAS_RANDOM_R */ #ifdef HAS_READDIR_R diff --git a/reentr.h b/reentr.h index 05b06f8d5c..e66abd907f 100644 --- a/reentr.h +++ b/reentr.h @@ -185,13 +185,12 @@ #define REENTRANT_PROTO_S_SBIE 69 #define REENTRANT_PROTO_S_SBW 70 #define REENTRANT_PROTO_S_TISBI 71 -#define REENTRANT_PROTO_S_TS 72 -#define REENTRANT_PROTO_S_TSBI 73 -#define REENTRANT_PROTO_S_TSBIE 74 -#define REENTRANT_PROTO_S_TWISBIE 75 -#define REENTRANT_PROTO_V_D 76 -#define REENTRANT_PROTO_V_H 77 -#define REENTRANT_PROTO_V_ID 78 +#define REENTRANT_PROTO_S_TSBI 72 +#define REENTRANT_PROTO_S_TSBIE 73 +#define REENTRANT_PROTO_S_TWISBIE 74 +#define REENTRANT_PROTO_V_D 75 +#define REENTRANT_PROTO_V_H 76 +#define REENTRANT_PROTO_V_ID 77 /* Defines for indicating which special features are supported. */ @@ -740,12 +739,6 @@ typedef struct { FILE* _spent_fptr; # endif #endif /* HAS_GETSPNAM_R */ -#ifdef HAS_GMTIME_R - struct tm _gmtime_struct; -#endif /* HAS_GMTIME_R */ -#ifdef HAS_LOCALTIME_R - struct tm _localtime_struct; -#endif /* HAS_LOCALTIME_R */ #ifdef HAS_RANDOM_R struct random_data _random_struct; # if RANDOM_R_PROTO == REENTRANT_PROTO_I_iS @@ -1330,30 +1323,6 @@ typedef struct { # endif /* HAS_GETSPNAM */ #endif /* HAS_GETSPNAM_R */ -#ifdef HAS_GMTIME_R -# if defined(PERL_REENTR_API) && (PERL_REENTR_API+0 == 1) -# undef gmtime -# if !defined(gmtime) && GMTIME_R_PROTO == REENTRANT_PROTO_S_TS -# define gmtime(a) (gmtime_r(a, &PL_reentrant_buffer->_gmtime_struct) ? &PL_reentrant_buffer->_gmtime_struct : 0) -# endif /* if defined(PERL_REENTR_API) && (PERL_REENTR_API+0 == 1) */ -# if !defined(gmtime) && GMTIME_R_PROTO == REENTRANT_PROTO_I_TS -# define gmtime(a) (gmtime_r(a, &PL_reentrant_buffer->_gmtime_struct) == 0 ? &PL_reentrant_buffer->_gmtime_struct : 0) -# endif /* if defined(PERL_REENTR_API) && (PERL_REENTR_API+0 == 1) */ -# endif /* HAS_GMTIME */ -#endif /* HAS_GMTIME_R */ - -#ifdef HAS_LOCALTIME_R -# if defined(PERL_REENTR_API) && (PERL_REENTR_API+0 == 1) -# undef localtime -# if !defined(localtime) && LOCALTIME_R_PROTO == REENTRANT_PROTO_S_TS -# define localtime(a) (L_R_TZSET localtime_r(a, &PL_reentrant_buffer->_localtime_struct) ? &PL_reentrant_buffer->_localtime_struct : 0) -# endif /* if defined(PERL_REENTR_API) && (PERL_REENTR_API+0 == 1) */ -# if !defined(localtime) && LOCALTIME_R_PROTO == REENTRANT_PROTO_I_TS -# define localtime(a) (L_R_TZSET localtime_r(a, &PL_reentrant_buffer->_localtime_struct) == 0 ? &PL_reentrant_buffer->_localtime_struct : 0) -# endif /* if defined(PERL_REENTR_API) && (PERL_REENTR_API+0 == 1) */ -# endif /* HAS_LOCALTIME */ -#endif /* HAS_LOCALTIME_R */ - #ifdef HAS_RANDOM_R # if defined(PERL_REENTR_API) && (PERL_REENTR_API+0 == 1) # undef random diff --git a/reentr.pl b/reentr.pl index ea327a09fe..89795cd2e1 100644 --- a/reentr.pl +++ b/reentr.pl @@ -504,7 +504,7 @@ EOF EOF pushssif $endif; } - elsif ($func =~ /^(drand48|gmtime|localtime|random|srandom)$/) { + elsif ($func =~ /^(drand48|random|srandom)$/) { pushssif $ifdef; push @struct, <