From patchwork Wed Nov 21 17:49:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Eggert X-Patchwork-Id: 30245 Received: (qmail 105099 invoked by alias); 21 Nov 2018 17:49:27 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 105088 invoked by uid 89); 21 Nov 2018 17:49:26 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.2 spammy=H*Ad:D*ucla.edu X-HELO: zimbra.cs.ucla.edu Subject: Re: [PATCH 1/1] Y2038: make __mktime_internal compatible with __time64_t To: "Albert ARIBAUD (3ADEV)" , libc-alpha@sourceware.org References: <20181121002844.14530-9-albert.aribaud@3adev.fr> <20181121070245.14169-1-albert.aribaud@3adev.fr> From: Paul Eggert Message-ID: Date: Wed, 21 Nov 2018 09:49:16 -0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 In-Reply-To: <20181121070245.14169-1-albert.aribaud@3adev.fr> Albert ARIBAUD (3ADEV) wrote: > +#if __TIMESIZE != 64 > + > +/* The 32-bit-time wrapper. */ > +time_t > +mktime (struct tm *tp) When this code is used in Gnulib in the obvious way, it defines another instance of 'mktime' which won't work. Also, this new instance of mktime uses a function fits_in_time_t, which isn't defined outside glibc. There is a similar problem with timegm. A quick fix would be to change '#if __TIMESIZE != 64' to '#if defined _LIBC && __TIMESIZE != 64'. But we can take this opportunity to simplify mktime.c as per the attached patches. The first is for glibc and assumes the patches you already sent, and the second (for the record) is the resulting combined patch to Gnulib. From c0b58031ef8b98741f67d74662ba9128d43c5d03 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 21 Nov 2018 09:18:10 -0800 Subject: [PATCH] mktime: adjust to glibc 64-bit changes * lib/mktime-internal.h (__gmtime64_r): Rename from __gmtime_r. (__localtime64_r): Rename from __localtime_r. (__mktime64, __time64_t, __timegm64): New macros. * lib/mktime.c, lib/timegm.c: Sync from glibc, with changes needed for Gnulib. --- ChangeLog | 7 +++++ lib/mktime-internal.h | 14 ++++++--- lib/mktime.c | 68 ++++++++++++++++++++++++++----------------- lib/timegm.c | 21 +++++++++++-- 4 files changed, 77 insertions(+), 33 deletions(-) diff --git a/ChangeLog b/ChangeLog index 15630fe23..457b21d6f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2018-11-21 Paul Eggert + mktime: adjust to glibc 64-bit changes + * lib/mktime-internal.h (__gmtime64_r): Rename from __gmtime_r. + (__localtime64_r): Rename from __localtime_r. + (__mktime64, __time64_t, __timegm64): New macros. + * lib/mktime.c, lib/timegm.c: Sync from glibc, with changes + needed for Gnulib. + mktime: add libc-config dependency I missed this when we synced from glibc. * modules/mktime (Depends-on): Add libc-config. diff --git a/lib/mktime-internal.h b/lib/mktime-internal.h index 3e64156e8..fde7bfa4c 100644 --- a/lib/mktime-internal.h +++ b/lib/mktime-internal.h @@ -45,9 +45,15 @@ time_t mktime_internal (struct tm *, Similarly for gmtime_r. See the gnulib time_r module for one way to implement this. */ -#undef __gmtime_r -#undef __localtime_r -#define __gmtime_r gmtime_r -#define __localtime_r localtime_r +#undef __gmtime64_r +#undef __localtime64_r +#undef __mktime64 +#undef __time64_t +#undef __timegm64 +#define __gmtime64_r gmtime_r +#define __localtime64_r localtime_r +#define __mktime64 mktime +#define __time64_t time_t +#define __timegm64 timegm #define __mktime_internal mktime_internal diff --git a/lib/mktime.c b/lib/mktime.c index 8faa9bc93..f6d911da4 100644 --- a/lib/mktime.c +++ b/lib/mktime.c @@ -112,11 +112,11 @@ my_tzset (void) added to them, and then with another timestamp added, without worrying about overflow. - Much of the code uses long_int to represent time_t values, to - lessen the hassle of dealing with platforms where time_t is + Much of the code uses long_int to represent __time64_t values, to + lessen the hassle of dealing with platforms where __time64_t is unsigned, and because long_int should suffice to represent all - time_t values that mktime can generate even on platforms where - time_t is excessively wide. */ + __time64_t values that mktime can generate even on platforms where + __time64_t is excessively wide. */ #if INT_MAX <= LONG_MAX / 4 / 366 / 24 / 60 / 60 typedef long int long_int; @@ -144,16 +144,17 @@ shr (long_int a, int b) : a / (one << b) - (a % (one << b) < 0)); } -/* Bounds for the intersection of time_t and long_int. */ +/* Bounds for the intersection of __time64_t and long_int. */ static long_int const mktime_min - = ((TYPE_SIGNED (time_t) && TYPE_MINIMUM (time_t) < TYPE_MINIMUM (long_int)) - ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (time_t)); + = ((TYPE_SIGNED (__time64_t) + && TYPE_MINIMUM (__time64_t) < TYPE_MINIMUM (long_int)) + ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (__time64_t)); static long_int const mktime_max - = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (time_t) - ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (time_t)); + = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (__time64_t) + ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (__time64_t)); -verify (TYPE_IS_INTEGER (time_t)); +verify (TYPE_IS_INTEGER (__time64_t)); #define EPOCH_YEAR 1970 #define TM_YEAR_BASE 1900 @@ -252,23 +253,23 @@ tm_diff (long_int year, long_int yday, int hour, int min, int sec, } /* Use CONVERT to convert T to a struct tm value in *TM. T must be in - range for time_t. Return TM if successful, NULL (setting errno) on + range for __time64_t. Return TM if successful, NULL (setting errno) on failure. */ static struct tm * -convert_time (struct tm *(*convert) (const time_t *, struct tm *), +convert_time (struct tm *(*convert) (const __time64_t *, struct tm *), long_int t, struct tm *tm) { - time_t x = t; + __time64_t x = t; return convert (&x, tm); } /* Use CONVERT to convert *T to a broken down time in *TP. If *T is out of range for conversion, adjust it so that it is the nearest in-range value and then convert that. - A value is in range if it fits in both time_t and long_int. + A value is in range if it fits in both __time64_t and long_int. Return TP on success, NULL (setting errno) on failure. */ static struct tm * -ranged_convert (struct tm *(*convert) (const time_t *, struct tm *), +ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *), long_int *t, struct tm *tp) { long_int t1 = (*t < mktime_min ? mktime_min @@ -310,7 +311,7 @@ ranged_convert (struct tm *(*convert) (const time_t *, struct tm *), } -/* Convert *TP to a time_t value, inverting +/* Convert *TP to a __time64_t value, inverting the monotonic and mostly-unit-linear conversion function CONVERT. Use *OFFSET to keep track of a guess at the offset of the result, compared to what the result would be for UTC without leap seconds. @@ -318,9 +319,9 @@ ranged_convert (struct tm *(*convert) (const time_t *, struct tm *), If successful, set *TP to the canonicalized struct tm; otherwise leave *TP alone, return ((time_t) -1) and set errno. This function is external because it is used also by timegm.c. */ -time_t +__time64_t __mktime_internal (struct tm *tp, - struct tm *(*convert) (const time_t *, struct tm *), + struct tm *(*convert) (const __time64_t *, struct tm *), mktime_offset_t *offset) { struct tm tm; @@ -520,9 +521,9 @@ __mktime_internal (struct tm *tp, #if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS -/* Convert *TP to a time_t value. */ -time_t -mktime (struct tm *tp) +/* Convert *TP to a __time64_t value. */ +__time64_t +__mktime64 (struct tm *tp) { /* POSIX.1 8.1.1 requires that whenever mktime() is called, the time zone names contained in the external variable 'tzname' shall @@ -531,19 +532,34 @@ mktime (struct tm *tp) # if defined _LIBC || NEED_MKTIME_WORKING static mktime_offset_t localtime_offset; - return __mktime_internal (tp, __localtime_r, &localtime_offset); + return __mktime_internal (tp, __localtime64_r, &localtime_offset); # else # undef mktime return mktime (tp); # endif } + +weak_alias (__mktime64, __timelocal64) +libc_hidden_def (__mktime64) +libc_hidden_weak (__timelocal64) + #endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */ -#ifdef weak_alias -weak_alias (mktime, timelocal) -#endif +#if defined _LIBC && __TIMESIZE != 64 -#ifdef _LIBC +/* The 32-bit-time wrapper. */ +time_t +mktime (struct tm *tp) +{ + __time64_t t64 = __mktime64 (tp); + if (fits_in_time_t (t64)) + return t64; + __set_errno (EOVERFLOW); + return -1; +} + +weak_alias (mktime, timelocal) libc_hidden_def (mktime) libc_hidden_weak (timelocal) + #endif diff --git a/lib/timegm.c b/lib/timegm.c index 229fff23c..ec7f8eb16 100644 --- a/lib/timegm.c +++ b/lib/timegm.c @@ -24,11 +24,26 @@ #include #include "mktime-internal.h" +#include + +__time64_t +__timegm64 (struct tm *tmp) +{ + static long int gmtime_offset; + tmp->tm_isdst = 0; + return __mktime_internal (tmp, __gmtime64_r, &gmtime_offset); +} + +#if defined _LIBC && __TIMESIZE != 64 time_t timegm (struct tm *tmp) { - static mktime_offset_t gmtime_offset; - tmp->tm_isdst = 0; - return __mktime_internal (tmp, __gmtime_r, &gmtime_offset); + __time64_t t64 = __timegm64 (tmp); + if (fits_in_time_t (t64)) + return t64; + __set_errno (EOVERFLOW); + return -1; } + +#endif -- 2.17.1