From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS31976 209.132.180.0/23 X-Spam-Status: No, score=-4.2 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,SPF_HELO_PASS,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id 0AB1D20248 for ; Wed, 6 Mar 2019 11:32:07 +0000 (UTC) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:from:to:cc:subject:message-id:in-reply-to :references:mime-version:content-type; q=dns; s=default; b=Gfm7L /mgKjdWX42Lp2TXGDCOBbEGtuh3XMnOwRd0yrXFNDgVUf06Kf+lLcZKKmFEjdQht nksnnponbs4CHZQAP9yy+RiXisNUR8HcBL92N6mKI4mmj1w41B/JEhcRkwlzRSWO 6sryy65EMWNhA0M5OrTSXu8sxQ9Y8dcZyKrKy4= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:from:to:cc:subject:message-id:in-reply-to :references:mime-version:content-type; s=default; bh=YBgyFeiRKic 5zxu7VT1mQX2U2+A=; b=amUM3F8ClhnWEBK4h7wtMghMxxHNPX5YpSuiVcD9Yn/ jD7xHS+J+rnG5QfWNdA/kxN8Ce6T/+4YmYn0ovtPqxO1+loeyW9dyy2ZiZl+Mv5W a7uj2p9d5pXpdMi4CPnAcONUb7r0GWoSYQlpRpbEBFU+L1NP/4E04YceGwFKeBJc = Received: (qmail 39647 invoked by alias); 6 Mar 2019 11:32:04 -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 Received: (qmail 39639 invoked by uid 89); 6 Mar 2019 11:32:03 -0000 Authentication-Results: sourceware.org; auth=none X-HELO: mail-out.m-online.net Date: Wed, 6 Mar 2019 12:31:47 +0100 From: Lukasz Majewski To: libc-alpha@sourceware.org Cc: Paul Eggert , Joseph Myers Subject: Re: [PATCH v2 1/2] Y2038: make __mktime_internal compatible with __time64_t Message-ID: <20190306123147.0eb78b5b@jawa> In-Reply-To: <20190227112042.1794-1-lukma@denx.de> References: <20190227112042.1794-1-lukma@denx.de> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; boundary="Sig_/CpjiEQg2=pKY24_GPJAjn+n"; protocol="application/pgp-signature" --Sig_/CpjiEQg2=pKY24_GPJAjn+n Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Dear Joseph, Paul, > From: Paul Eggert >=20 > This implies also making its callers 64-bit-time compatible > (these are mktime/localtime and timegm) and providing wrappers > for 32-bit-time userland to call. >=20 > Tested with 'make check' on x86_64-linux-gnu and i686-linux.gnu. >=20 > * include/time.h (__mktime64): Add prototype. > * include/time.h (__localtime64): Likewise. > * include/time.h (fits_in_time_t): New static function. > * time/mktime.c (__mktime64): New function. > * time/timegm.c (__timegm64): Likewise. > * time/mktime.c (mktime) [__TIMESIZE]: New wrapper function. > * time/timegm.c (timegm) [__TIMESIZE]: Likewise. >=20 > --- > Applicable on top of the newest glibc's master branch > SH1: aa0e46636a5b71b609a41e9ab97134cd76ac1522 >=20 > Tested with make check for x86_64, i585 and ARM setups. >=20 > Changes for v2: > Add missing space (__set_errno (EOVERFLOW)) in src/time/timegm.c > Add missing space (__set_errno (EOVERFLOW)) in src/time/mktime.c Gentle ping on this series. > --- > include/time.h | 36 +++++++++++++++++++++----- > time/mktime.c | 80 > ++++++++++++++++++++++++++++++++++++++++++---------------- > time/timegm.c | 27 +++++++++++++++++++- 3 files changed, 114 > insertions(+), 29 deletions(-) >=20 > diff --git a/include/time.h b/include/time.h > index 61dd9e180b..34e5e04820 100644 > --- a/include/time.h > +++ b/include/time.h > @@ -3,6 +3,7 @@ > =20 > #ifndef _ISOMAC > # include > +# include > =20 > extern __typeof (strftime_l) __strftime_l; > libc_hidden_proto (__strftime_l) > @@ -16,6 +17,21 @@ libc_hidden_proto (localtime) > libc_hidden_proto (strftime) > libc_hidden_proto (strptime) > =20 > +#if __TIMESIZE =3D=3D 64 > +# define __timegm64 timegm > +# define __mktime64 mktime > +# define __timelocal64 timelocal > +#else > +extern __time64_t __timegm64 (struct tm *__tp) __THROW; > +extern __time64_t __mktime64 (struct tm *__tp) __THROW; > +/* Another name for `__mktime64'. */ > +extern __time64_t __timelocal64 (struct tm *__tp) __THROW; > + > +libc_hidden_proto (__mktime64) > +libc_hidden_proto (__timelocal64) > +#endif > + > + > extern __typeof (clock_getres) __clock_getres; > extern __typeof (clock_gettime) __clock_gettime; > libc_hidden_proto (__clock_gettime) > @@ -49,13 +65,13 @@ extern void __tzset_parse_tz (const char *tz) > attribute_hidden; extern void __tz_compute (__time64_t timer, struct > tm *tm, int use_localtime) __THROW attribute_hidden; > =20 > -/* Subroutine of `mktime'. Return the `time_t' representation of TP > and > - normalize TP, given that a `struct tm *' maps to a `time_t' as > performed +/* Subroutine of mktime. Return the __time64_t > representation of TP and > + normalize TP, given that a struct tm * maps to a __time64_t as > performed by FUNC. Record next guess for localtime-gmtime offset in > *OFFSET. */ -extern time_t __mktime_internal (struct tm *__tp, > - struct tm *(*__func) (const time_t > *, > - struct tm *), > - long int *__offset) > attribute_hidden; +extern __time64_t __mktime_internal (struct tm > *__tp, > + struct tm *(*__func) (const > __time64_t *, > + struct tm > *), > + long int *__offset) > attribute_hidden;=20 > #if __TIMESIZE =3D=3D 64 > # define __ctime64 ctime > @@ -155,5 +171,13 @@ extern double __difftime (time_t time1, time_t > time0); actual clock ID. */ > #define CLOCK_IDFIELD_SIZE 3 > =20 > +/* Check whether a time64_t value fits in a time_t. */ > +static inline bool > +fits_in_time_t (__time64_t t64) > +{ > + time_t t =3D t64; > + return t =3D=3D t64; > +} > + > #endif > #endif > diff --git a/time/mktime.c b/time/mktime.c > index af43a6950d..5d3644e213 100644 > --- a/time/mktime.c > +++ b/time/mktime.c > @@ -112,11 +112,11 @@ my_tzset (void) > added to them, and then with another timestamp added, without > worrying about overflow. > =20 > - 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. */ > =20 > #if INT_MAX <=3D 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)); > } > =20 > -/* Bounds for the intersection of time_t and long_int. */ > +/* Bounds for the intersection of __time64_t and long_int. */ > =20 > static long_int const mktime_min > - =3D ((TYPE_SIGNED (time_t) && TYPE_MINIMUM (time_t) < TYPE_MINIMUM > (long_int)) > - ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (time_t)); > + =3D ((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 > - =3D (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (time_t) > - ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (time_t)); > + =3D (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (__time64_t) > + ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (__time64_t)); > =20 > -verify (TYPE_IS_INTEGER (time_t)); > +verify (TYPE_IS_INTEGER (__time64_t)); > =20 > #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, } > =20 > /* 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 =3D t; > + __time64_t x =3D t; > return convert (&x, tm); > } > =20 > /* 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 =3D (*t < mktime_min ? mktime_min > @@ -310,7 +311,7 @@ ranged_convert (struct tm *(*convert) (const > time_t *, struct tm *), } > =20 > =20 > -/* 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,10 +521,13 @@ __mktime_internal (struct tm *tp, > =20 > #if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS > =20 > -/* 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) > { > + __time64_t t64; > + time_t t; > + struct tm tp0 =3D *tp; > /* POSIX.1 8.1.1 requires that whenever mktime() is called, the > time zone names contained in the external variable 'tzname' > shall be set as if the tzset() function had been called. */ > @@ -531,7 +535,15 @@ mktime (struct tm *tp) > =20 > # if defined _LIBC || NEED_MKTIME_WORKING > static mktime_offset_t localtime_offset; > - return __mktime_internal (tp, __localtime_r, &localtime_offset); > + t64 =3D __mktime_internal (&tp0, __localtime64_r, &localtime_offset); > + t =3D t64; > + if (t !=3D t64) > + { > + __set_errno (EOVERFLOW); > + return -1; > + } > + *tp =3D tp0; > + return t; > # else > # undef mktime > return mktime (tp); > @@ -540,6 +552,28 @@ mktime (struct tm *tp) > #endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */ > =20 > #ifdef weak_alias > +weak_alias (__mktime64, __timelocal64) > +#endif > + > +#ifdef _LIBC > +libc_hidden_def (__mktime64) > +libc_hidden_weak (__timelocal64) > +#endif > + > +#if __TIMESIZE !=3D 64 > + > +/* The 32-bit-time wrapper. */ > +time_t > +mktime (struct tm *tp) > +{ > + __time64_t t64 =3D __mktime64 (tp); > + if (fits_in_time_t (t64)) > + return t64; > + __set_errno (EOVERFLOW); > + return -1; > +} > + > +#ifdef weak_alias > weak_alias (mktime, timelocal) > #endif > =20 > @@ -547,3 +581,5 @@ weak_alias (mktime, timelocal) > libc_hidden_def (mktime) > libc_hidden_weak (timelocal) > #endif > + > +#endif > diff --git a/time/timegm.c b/time/timegm.c > index bfd36d0255..0cbe60a7fe 100644 > --- a/time/timegm.c > +++ b/time/timegm.c > @@ -22,13 +22,38 @@ > #endif > =20 > #include > +#include > =20 > #include "mktime-internal.h" > +#include > + > +__time64_t > +__timegm64 (struct tm *tmp) > +{ > + static long int gmtime_offset; > + tmp->tm_isdst =3D 0; > + return __mktime_internal (tmp, __gmtime64_r, &gmtime_offset); > +} > + > +#if __TIMESIZE !=3D 64 > =20 > time_t > timegm (struct tm *tmp) > { > + time_t t; > + __time64_t t64; > + struct tm tmp0 =3D *tmp; > static mktime_offset_t gmtime_offset; > tmp->tm_isdst =3D 0; > - return __mktime_internal (tmp, __gmtime_r, &gmtime_offset); > + t64 =3D __mktime_internal (&tmp0, __gmtime64_r, &gmtime_offset); > + t =3D t64; > + if (t !=3D t64) > + { > + __set_errno (EOVERFLOW); > + return -1; > + } > + *tmp =3D tmp0; > + return t; > } > + > +#endif Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de --Sig_/CpjiEQg2=pKY24_GPJAjn+n Content-Type: application/pgp-signature Content-Description: OpenPGP digital signature -----BEGIN PGP SIGNATURE----- iQEzBAEBCAAdFiEEgAyFJ+N6uu6+XupJAR8vZIA0zr0FAlx/r6MACgkQAR8vZIA0 zr1AGAgAjAKAEe1oc4+GDG1bfkLcQDq27nPWFJvAAJXDGD8RIBSs5Ku6bvvZYoXo CmobBXYEH2mZZ/cHF55brkgoGlymYd+vuu3CxHY/WkP/5cPbxN5SIJBbBLuyyVHn R1VXEw8GvNu/MGBslU7NkpBFwo9P6l74oB6U/UEm/n4ggC6wFjp4wrHSpT2D9dUO eyRG6WDeE9xKfaOy22MY5Oqe7CsHgUt2NsBWxZQ3LW9wciw0IYJZg9W1ykrvcQJV zrey9VuWKJlnU853M7ldvzmjijq/pOqY/AGW3EoFD4WD9944GCSHLYteunN+IbzK PUj4Xl4D1/gL+OYl6GNSfsDcRs6prA== =OQbE -----END PGP SIGNATURE----- --Sig_/CpjiEQg2=pKY24_GPJAjn+n--