From patchwork Thu Jun 14 13:51:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Albert ARIBAUD (3ADEV)" X-Patchwork-Id: 929445 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=sourceware.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=libc-alpha-return-93254-incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=3adev.fr Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="fgJ7Unj6"; dkim-atps=neutral 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 ozlabs.org (Postfix) with ESMTPS id 4164mC43TDz9s01 for ; Thu, 14 Jun 2018 23:51:39 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references; q=dns; s=default; b=I3h/mBVKJgxwpoF+p9q+QnYlERio3Ib TOugIuLrUBnY/mApbGWY+aLfPK1W9v6vGA7bh3TQekES0VGUBLXPnJn5eozWl9VY vkok+ZCVt0n6NOAoqt0azPbvxC5mb59zrI5k2u9ndnPgZfczFa79cW8GOoIu8AtY HBEoh5Dlg3ek= 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:from:to:cc:subject:date:message-id:in-reply-to :references; s=default; bh=PQQp0E9SNDEdkojpLyHoATMwTLg=; b=fgJ7U nj6RWTSiBDoNgbMJ86H3VT2eXGa+iVuV3AqXUpBy6YJjiCdr1vEN/LrDUehip16C MV/0kbg3iqZ+cLy3+ktEsCIfv8W3idM74U1k2/8Tg/lclOebSE8IlVlgvdR7IQbh pCF6TbxoAGzT+HMuEOCpFPrbjlCog84D+ixp8I= Received: (qmail 42710 invoked by alias); 14 Jun 2018 13:51:28 -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 42574 invoked by uid 89); 14 Jun 2018 13:51:27 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, KAM_SHORT, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=drepper X-HELO: smtp6-g21.free.fr From: "Albert ARIBAUD (3ADEV)" To: libc-alpha@sourceware.org Cc: "Albert ARIBAUD (3ADEV)" Subject: [PATCH v2 1/2] Y2038: Add 64-bit time for all architectures Date: Thu, 14 Jun 2018 15:51:15 +0200 Message-Id: <20180614135116.8767-2-albert.aribaud@3adev.fr> In-Reply-To: <20180614135116.8767-1-albert.aribaud@3adev.fr> References: <20180614135116.8767-1-albert.aribaud@3adev.fr> * Add macro __TIMESIZE equal to the bit size of time_t. It equals the architecture __WORDSIZE except for x32 where it equals 64. * Add type __time64_t which is always 64-bit. On 64-bit architectures and on x32, it is #defined as time_t. On other architectures, it has its own type. * Replace all occurrences of internal_time_t with __time64_t. The __time64_t type is public so that the public time_t type can be a typedef or #define of __time64_t when we switch the public API to 64-bit time. Also, provide a function (inline) to check if a __time64_t value fits in a (possibly 32-bit) time_t. This is used when a 32-bit-time wrapper calls a glibc function which returns a __time64_t, so that the wrapper can detect times which it cannot properly return to its caller, and can flag an EOVERFLOW accordingly. --- bits/timesize.h | 23 ++++++++++++ bits/timesizes.h | 37 ++++++++++++++++++++ include/sys/types.h | 1 + include/time.h | 21 +++++++---- posix/bits/types.h | 8 +++++ stdlib/Makefile | 2 +- sysdeps/unix/sysv/linux/x86/bits/timesizes.h | 32 +++++++++++++++++ sysdeps/x86/bits/timesize.h | 21 +++++++++++ time/tzfile.c | 18 +++++----- 9 files changed, 147 insertions(+), 16 deletions(-) create mode 100644 bits/timesize.h create mode 100644 bits/timesizes.h create mode 100644 sysdeps/unix/sysv/linux/x86/bits/timesizes.h create mode 100644 sysdeps/x86/bits/timesize.h diff --git a/bits/timesize.h b/bits/timesize.h new file mode 100644 index 0000000000..58eb22d6f6 --- /dev/null +++ b/bits/timesize.h @@ -0,0 +1,23 @@ +/* Bit size of the time_t type at glibc build time, general case. + Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include // for __WORDSIZE + +/* Size in bits of the 'time_t' type; equals __WORDSIZE except for x32 */ +#define __TIMESIZE __WORDSIZE diff --git a/bits/timesizes.h b/bits/timesizes.h new file mode 100644 index 0000000000..e279b15cd8 --- /dev/null +++ b/bits/timesizes.h @@ -0,0 +1,37 @@ +/* bits/timesizes.h -- underlying types for __time64_t. Generic version. + Copyright (C) 2018 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TIMESIZES_H +#define _BITS_TIMESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#if __TIMESIZE == 64 +/* If we already have 64-bit time then use it */ +#define __TIME64_T_TYPE __TIME_T_TYPE +#else +/* Define a 64-bit type alongsize the 32-bit one */ +#define __TIME64_T_TYPE __SQUAD_TYPE +#endif + +#endif /* bits/timesizes.h */ diff --git a/include/sys/types.h b/include/sys/types.h index 716732f4d4..107b0672ac 100644 --- a/include/sys/types.h +++ b/include/sys/types.h @@ -1 +1,2 @@ #include +#include diff --git a/include/time.h b/include/time.h index 23d2580528..fea072cbb6 100644 --- a/include/time.h +++ b/include/time.h @@ -3,6 +3,7 @@ #ifndef _ISOMAC # include +# include extern __typeof (strftime_l) __strftime_l; libc_hidden_proto (__strftime_l) @@ -26,10 +27,6 @@ extern __typeof (clock_getcpuclockid) __clock_getcpuclockid; /* Now define the internal interfaces. */ struct tm; -/* time_t variant for representing time zone data, independent of - time_t. */ -typedef __int64_t internal_time_t; - /* Defined in mktime.c. */ extern const unsigned short int __mon_yday[2][13] attribute_hidden; @@ -43,7 +40,7 @@ extern int __use_tzfile attribute_hidden; extern void __tzfile_read (const char *file, size_t extra, char **extrap) attribute_hidden; -extern void __tzfile_compute (internal_time_t timer, int use_localtime, +extern void __tzfile_compute (__time64_t timer, int use_localtime, long int *leap_correct, int *leap_hit, struct tm *tp) attribute_hidden; extern void __tzfile_default (const char *std, const char *dst, @@ -101,10 +98,22 @@ extern char * __strptime_internal (const char *rp, const char *fmt, extern double __difftime (time_t time1, time_t time0); - /* Use in the clock_* functions. Size of the field representing the actual clock ID. */ #define CLOCK_IDFIELD_SIZE 3 +/* check whether a time64_t value fits in a time_t */ +# if __TIMESIZE == 64 +/* __time64_t is time_t, so it always fits_in_time_t */ +# define fits_in_time_t(x) 1 +# else +/* Not all __time64_t values can fit; check by type-casting */ +static inline bool +fits_in_time_t (__time64_t t) +{ + return t == (time_t) t; +} +# endif + #endif #endif diff --git a/posix/bits/types.h b/posix/bits/types.h index 5e22ce41bf..0c7289faf8 100644 --- a/posix/bits/types.h +++ b/posix/bits/types.h @@ -25,6 +25,7 @@ #include #include +#include /* Convenience types. */ typedef unsigned char __u_char; @@ -138,6 +139,7 @@ __extension__ typedef unsigned long long int __uintmax_t; # error #endif #include /* Defines __*_T_TYPE macros. */ +#include /* Defines __TIME*_T_TYPE macros. */ __STD_TYPE __DEV_T_TYPE __dev_t; /* Type of device numbers. */ @@ -211,6 +213,12 @@ __STD_TYPE __U32_TYPE __socklen_t; It is not currently necessary for this to be machine-specific. */ typedef int __sig_atomic_t; +#if __TIMESIZE == 64 +# define __time64_t time_t +#else +__STD_TYPE __TIME64_T_TYPE __time64_t; /* Seconds since the Epoch (_TIME_BITS==64). */ +#endif + #undef __STD_TYPE #endif /* bits/types.h */ diff --git a/stdlib/Makefile b/stdlib/Makefile index bf1fbd4a3a..4c6e541f77 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -29,7 +29,7 @@ headers := stdlib.h bits/stdlib.h bits/stdlib-ldbl.h bits/stdlib-float.h \ ucontext.h sys/ucontext.h \ alloca.h fmtmsg.h \ bits/stdlib-bsearch.h sys/random.h bits/stdint-intn.h \ - bits/stdint-uintn.h + bits/stdint-uintn.h bits/timesizes.h bits/timesize.h \ routines := \ atof atoi atol atoll \ diff --git a/sysdeps/unix/sysv/linux/x86/bits/timesizes.h b/sysdeps/unix/sysv/linux/x86/bits/timesizes.h new file mode 100644 index 0000000000..785beab183 --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86/bits/timesizes.h @@ -0,0 +1,32 @@ +/* bits/typesizes.h -- underlying types for __time64_t. Linux/x86-64 version. + Copyright (C) 2018 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TIMESIZES_H +#define _BITS_TIMESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +/* Both x86-64 and x32 use 64-bit time. */ +#define __TIME64_T_TYPE __TIME_T_TYPE + +#endif /* bits/timesizes.h */ diff --git a/sysdeps/x86/bits/timesize.h b/sysdeps/x86/bits/timesize.h new file mode 100644 index 0000000000..8974d81102 --- /dev/null +++ b/sysdeps/x86/bits/timesize.h @@ -0,0 +1,21 @@ +/* Bit size of the time_t type at glibc build time, x86-64 and x32 case. + Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* Both x86-64 and x32 use 64-bit time. */ +#define __TIMESIZE 64 diff --git a/time/tzfile.c b/time/tzfile.c index 2a385b92bc..d7e391c3a3 100644 --- a/time/tzfile.c +++ b/time/tzfile.c @@ -44,12 +44,12 @@ struct ttinfo struct leap { - internal_time_t transition; /* Time the transition takes effect. */ + __time64_t transition; /* Time the transition takes effect. */ long int change; /* Seconds of correction to apply. */ }; static size_t num_transitions; -libc_freeres_ptr (static internal_time_t *transitions); +libc_freeres_ptr (static __time64_t *transitions); static unsigned char *type_idxs; static size_t num_types; static struct ttinfo *types; @@ -113,8 +113,8 @@ __tzfile_read (const char *file, size_t extra, char **extrap) size_t tzspec_len; char *new = NULL; - _Static_assert (sizeof (internal_time_t) == 8, - "internal_time_t must be eight bytes"); + _Static_assert (sizeof (__time64_t) == 8, + "__time64_t must be eight bytes"); __use_tzfile = 0; @@ -220,9 +220,9 @@ __tzfile_read (const char *file, size_t extra, char **extrap) if (__builtin_expect (num_transitions > ((SIZE_MAX - (__alignof__ (struct ttinfo) - 1)) - / (sizeof (internal_time_t) + 1)), 0)) + / (sizeof (__time64_t) + 1)), 0)) goto lose; - total_size = num_transitions * (sizeof (internal_time_t) + 1); + total_size = num_transitions * (sizeof (__time64_t) + 1); total_size = ((total_size + __alignof__ (struct ttinfo) - 1) & ~(__alignof__ (struct ttinfo) - 1)); types_idx = total_size; @@ -279,7 +279,7 @@ __tzfile_read (const char *file, size_t extra, char **extrap) goto lose; type_idxs = (unsigned char *) transitions + (num_transitions - * sizeof (internal_time_t)); + * sizeof (__time64_t)); types = (struct ttinfo *) ((char *) transitions + types_idx); zone_names = (char *) types + num_types * sizeof (struct ttinfo); leaps = (struct leap *) ((char *) transitions + leaps_idx); @@ -580,7 +580,7 @@ __tzfile_default (const char *std, const char *dst, } void -__tzfile_compute (internal_time_t timer, int use_localtime, +__tzfile_compute (__time64_t timer, int use_localtime, long int *leap_correct, int *leap_hit, struct tm *tp) { @@ -669,7 +669,7 @@ __tzfile_compute (internal_time_t timer, int use_localtime, initial search spot from it. Half of a gregorian year has on average 365.2425 * 86400 / 2 = 15778476 seconds. The value i can be truncated if size_t is smaller than - internal_time_t, but this is harmless because it is just + __time64_t, but this is harmless because it is just a guess. */ i = (transitions[num_transitions - 1] - timer) / 15778476; if (i < num_transitions) From patchwork Thu Jun 14 13:51:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Albert ARIBAUD (3ADEV)" X-Patchwork-Id: 929446 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=sourceware.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=libc-alpha-return-93255-incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=3adev.fr Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="Uo2FcPIn"; dkim-atps=neutral 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 ozlabs.org (Postfix) with ESMTPS id 4164mN50yWz9s01 for ; Thu, 14 Jun 2018 23:51:48 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references; q=dns; s=default; b=I63KM7B8H/7t05rbEYFimYxi/r2QbE5 zuCtVD8sxMnb3oBT+pDhyiwAXWU4SLWFg39QFCjWC3e393HvZP5+PozXJiTeDnV9 +5FAkFObTezjAL9bf0od5JZvgbM+7UKwlM9YKR9JsPrvF9JJ5Vu4oaOl+fijfmLy YvlfYqMmubVk= 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:from:to:cc:subject:date:message-id:in-reply-to :references; s=default; bh=0p+IFdAPnyuo9SeD4Y/9rWjrAX0=; b=Uo2Fc PInv2eUcK+h/ZN5wh8r3XWZh4uoPrbG++rKARf6nU+Cp5u9wyqyVTMZpcd4YQmg4 iwrfKoJpTuXMUY0fF4rfpBwcZVafvjdMosbO0PucJ6DZjhWxm9zkZ0veUHUT6hg8 w9/4H9vy2CkCgPtyuH8Us09IWfaSkxOAjID1U0= Received: (qmail 43185 invoked by alias); 14 Jun 2018 13:51:32 -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 43042 invoked by uid 89); 14 Jun 2018 13:51:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, KAM_SHORT, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=1751, DAYS, hour, OFFSET X-HELO: smtp6-g21.free.fr From: "Albert ARIBAUD (3ADEV)" To: libc-alpha@sourceware.org Cc: "Albert ARIBAUD (3ADEV)" Subject: [PATCH v2 2/2] Y2038: make __tz_convert compatible with 64-bit-time Date: Thu, 14 Jun 2018 15:51:16 +0200 Message-Id: <20180614135116.8767-3-albert.aribaud@3adev.fr> In-Reply-To: <20180614135116.8767-1-albert.aribaud@3adev.fr> References: <20180614135116.8767-1-albert.aribaud@3adev.fr> This implies that its callers be 64-bit-time compatible too. It is done by creating 64-bit-time versions of these and turning their original 32-bit-time versions into wrappers (at a slight execution time cost). The callers affected are: * localtime * localtime_r * ctime * ctime_r * gmtime * gmtime_r Note that in time/tzfile.c we do not need to check for time_t overflows anymore as introduced by commit fc79706a323 since we now use internal_time_t. --- include/time.h | 36 +++++++++++++++++++++++++++++++----- time/ctime.c | 20 +++++++++++++++++--- time/ctime_r.c | 20 +++++++++++++++++--- time/gmtime.c | 40 +++++++++++++++++++++++++++++++++++----- time/localtime.c | 37 +++++++++++++++++++++++++++++++++---- time/offtime.c | 12 ++++++------ time/tzfile.c | 14 ++++---------- time/tzset.c | 30 ++++++++++++------------------ 8 files changed, 155 insertions(+), 54 deletions(-) diff --git a/include/time.h b/include/time.h index fea072cbb6..b314317650 100644 --- a/include/time.h +++ b/include/time.h @@ -47,7 +47,7 @@ extern void __tzfile_default (const char *std, const char *dst, long int stdoff, long int dstoff) attribute_hidden; extern void __tzset_parse_tz (const char *tz) attribute_hidden; -extern void __tz_compute (time_t timer, struct tm *tm, int use_localtime) +extern void __tz_compute (__time64_t timer, struct tm *tm, int use_localtime) __THROW attribute_hidden; /* Subroutine of `mktime'. Return the `time_t' representation of TP and @@ -57,18 +57,44 @@ extern time_t __mktime_internal (struct tm *__tp, struct tm *(*__func) (const time_t *, struct tm *), time_t *__offset) attribute_hidden; +#if __TIMESIZE == 64 +# define __ctime64 ctime +# define __ctime64_r ctime_r +#endif + +#if __TIMESIZE == 64 +# define __localtime64 localtime +#else +extern struct tm *__localtime64 (const __time64_t *__timer); +#endif + extern struct tm *__localtime_r (const time_t *__timer, struct tm *__tp) attribute_hidden; +#if __TIMESIZE == 64 +# define __localtime64_r __localtime_r +#else +extern struct tm *__localtime64_r (const __time64_t *__timer, + struct tm *__tp) attribute_hidden; +#endif + extern struct tm *__gmtime_r (const time_t *__restrict __timer, struct tm *__restrict __tp); libc_hidden_proto (__gmtime_r) -/* Compute the `struct tm' representation of *T, +#if __TIMESIZE == 64 +# define __gmtime64 gmtime +# define __gmtime64_r __gmtime_r +#else +extern struct tm *__gmtime64_r (const __time64_t *__restrict __timer, + struct tm *__restrict __tp); +#endif + +/* Compute the `struct tm' representation of T, offset OFFSET seconds east of UTC, and store year, yday, mon, mday, wday, hour, min, sec into *TP. Return nonzero if successful. */ -extern int __offtime (const time_t *__timer, +extern int __offtime (const __time64_t __timer, long int __offset, struct tm *__tp) attribute_hidden; @@ -77,8 +103,8 @@ extern char *__asctime_r (const struct tm *__tp, char *__buf) extern void __tzset (void) attribute_hidden; /* Prototype for the internal function to get information based on TZ. */ -extern struct tm *__tz_convert (const time_t *timer, int use_localtime, - struct tm *tp) attribute_hidden; +extern struct tm *__tz_convert (const __time64_t timer, int use_localtime, + struct tm *tp) attribute_hidden; extern int __nanosleep (const struct timespec *__requested_time, struct timespec *__remaining); diff --git a/time/ctime.c b/time/ctime.c index 1222614f29..ee98ed902e 100644 --- a/time/ctime.c +++ b/time/ctime.c @@ -16,13 +16,27 @@ . */ #include +#include /* Return a string as returned by asctime which is the representation of *T in that form. */ +char * +__ctime64 (const __time64_t *t) +{ +/* The C Standard says ctime (t) is equivalent to asctime (localtime (t)). + In particular, ctime and asctime must yield the same pointer. */ + return asctime (__localtime64 (t)); +} + +/* Provide a 32-bit wrapper if needed */ + +#if (__TIMESIZE != 64) + char * ctime (const time_t *t) { - /* The C Standard says ctime (t) is equivalent to asctime (localtime (t)). - In particular, ctime and asctime must yield the same pointer. */ - return asctime (localtime (t)); + __time64_t t64 = *t; + return __ctime64 (&t64); } + +#endif diff --git a/time/ctime_r.c b/time/ctime_r.c index c111146d76..d042adffce 100644 --- a/time/ctime_r.c +++ b/time/ctime_r.c @@ -18,12 +18,26 @@ . */ #include +#include /* Return a string as returned by asctime which is the representation - of *T in that form. Reentrant version. */ + of *T in that form. */ char * -ctime_r (const time_t *t, char *buf) +__ctime64_r (const __time64_t *t, char *buf) { struct tm tm; - return __asctime_r (__localtime_r (t, &tm), buf); + return __asctime_r (__localtime64_r (t, &tm), buf); } + +/* Provide a 32-bit wrapper if needed */ + +#if (__TIMESIZE != 64) + +char * +ctime_r (const time_t *t, char *buf) +{ + __time64_t t64 = *t; + return __ctime64_r (&t64, buf); +} + +#endif diff --git a/time/gmtime.c b/time/gmtime.c index dc33b3e68a..51560a5bab 100644 --- a/time/gmtime.c +++ b/time/gmtime.c @@ -17,21 +17,51 @@ . */ #include +#include + +/* Return the `struct tm' representation of 64-bit-time *T + in UTC, using *TP to store the result. */ +struct tm * +__gmtime64_r (const __time64_t *t, struct tm *tp) +{ + return __tz_convert (*t, 0, tp); +} + +/* Provide a 32-bit wrapper if needed */ + +#if (__TIMESIZE != 64) -/* Return the `struct tm' representation of *T in UTC, - using *TP to store the result. */ struct tm * __gmtime_r (const time_t *t, struct tm *tp) { - return __tz_convert (t, 0, tp); + __time64_t t64 = *t; + return __gmtime64_r (&t64, tp); } + +#endif + +/* This always works because either __TIMESIZE != 64 and __gmtime_r exists + or __TIMESIZE == 64 and the definition of __gmtime64_r above actually + defined __gmtime_r. */ libc_hidden_def (__gmtime_r) weak_alias (__gmtime_r, gmtime_r) +/* Return the `struct tm' representation of 64-bit-time *T in UTC. */ +struct tm * +__gmtime64 (const __time64_t *t) +{ + return __tz_convert (*t, 0, &_tmbuf); +} + +/* Provide a 32-bit wrapper if needed */ + +#if (__TIMESIZE != 64) -/* Return the `struct tm' representation of *T in UTC. */ struct tm * gmtime (const time_t *t) { - return __tz_convert (t, 0, &_tmbuf); + __time64_t t64 = *t; + return __gmtime64 (&t64); } + +#endif diff --git a/time/localtime.c b/time/localtime.c index 8684a8a971..9794d8c28c 100644 --- a/time/localtime.c +++ b/time/localtime.c @@ -17,25 +17,54 @@ . */ #include +#include /* The C Standard says that localtime and gmtime return the same pointer. */ struct tm _tmbuf; - /* Return the `struct tm' representation of *T in local time, using *TP to store the result. */ +struct tm * +__localtime64_r (const __time64_t *t, struct tm *tp) +{ + return __tz_convert (*t, 1, tp); +} + +/* Provide a 32-bit wrapper if needed */ + +#if (__TIMESIZE != 64) + struct tm * __localtime_r (const time_t *t, struct tm *tp) { - return __tz_convert (t, 1, tp); + __time64_t t64 = *t; + return __localtime64_r (&t64, tp); } -weak_alias (__localtime_r, localtime_r) +#endif + +/* This always works because either __TIMESIZE != 64 and __localtime_r + exists or __TIMESIZE == 64 and the definition of __localtime64_r above + actually defined __localtime_r. */ +weak_alias (__localtime_r, localtime_r) /* Return the `struct tm' representation of *T in local time. */ +struct tm * +__localtime64 (const __time64_t *t) +{ + return __tz_convert (*t, 1, &_tmbuf); +} + +/* Provide a 32-bit wrapper if needed */ + +#if (__TIMESIZE != 64) + struct tm * localtime (const time_t *t) { - return __tz_convert (t, 1, &_tmbuf); + __time64_t t64 = *t; + return __localtime64 (&t64); } libc_hidden_def (localtime) + +#endif diff --git a/time/offtime.c b/time/offtime.c index 04c48389fc..ede23c418f 100644 --- a/time/offtime.c +++ b/time/offtime.c @@ -21,18 +21,18 @@ #define SECS_PER_HOUR (60 * 60) #define SECS_PER_DAY (SECS_PER_HOUR * 24) -/* Compute the `struct tm' representation of *T, +/* Compute the `struct tm' representation of T, offset OFFSET seconds east of UTC, and store year, yday, mon, mday, wday, hour, min, sec into *TP. Return nonzero if successful. */ int -__offtime (const time_t *t, long int offset, struct tm *tp) +__offtime (const __time64_t t, long int offset, struct tm *tp) { - time_t days, rem, y; + __time64_t days, rem, y; const unsigned short int *ip; - days = *t / SECS_PER_DAY; - rem = *t % SECS_PER_DAY; + days = t / SECS_PER_DAY; + rem = t % SECS_PER_DAY; rem += offset; while (rem < 0) { @@ -60,7 +60,7 @@ __offtime (const time_t *t, long int offset, struct tm *tp) while (days < 0 || days >= (__isleap (y) ? 366 : 365)) { /* Guess a corrected year, assuming 365 days per year. */ - time_t yg = y + days / 365 - (days % 365 < 0); + __time64_t yg = y + days / 365 - (days % 365 < 0); /* Adjust DAYS and Y to match the guessed year. */ days -= ((yg - y) * 365 diff --git a/time/tzfile.c b/time/tzfile.c index d7e391c3a3..972e3ff5cf 100644 --- a/time/tzfile.c +++ b/time/tzfile.c @@ -635,16 +635,10 @@ __tzfile_compute (__time64_t timer, int use_localtime, /* Convert to broken down structure. If this fails do not use the string. */ - { - time_t truncated = timer; - if (__glibc_unlikely (truncated != timer - || ! __offtime (&truncated, 0, tp))) - goto use_last; - } - - /* Use the rules from the TZ string to compute the change. - timer fits into time_t due to the truncation check - above. */ + if (__glibc_unlikely (! __offtime (timer, 0, tp))) + goto use_last; + + /* Use the rules from the TZ string to compute the change. */ __tz_compute (timer, tp, 1); /* If tzspec comes from posixrules loaded by __tzfile_default, diff --git a/time/tzset.c b/time/tzset.c index a828b9fb75..4e91d9dca6 100644 --- a/time/tzset.c +++ b/time/tzset.c @@ -16,7 +16,6 @@ . */ #include -#include #include #include #include @@ -27,7 +26,7 @@ #include -#define SECSPERDAY ((time_t) 86400) +#define SECSPERDAY ((__time64_t) 86400) char *__tzname[2] = { (char *) "GMT", (char *) "GMT" }; int __daylight = 0; @@ -55,7 +54,7 @@ typedef struct /* We cache the computed time of change for a given year so we don't have to recompute it. */ - time_t change; /* When to change to this zone. */ + __time64_t change; /* When to change to this zone. */ int computed_for; /* Year above is computed for. */ } tz_rule; @@ -416,7 +415,7 @@ tzset_internal (int always) tz_rules[0].name = tz_rules[1].name = "UTC"; if (J0 != 0) tz_rules[0].type = tz_rules[1].type = J0; - tz_rules[0].change = tz_rules[1].change = (time_t) -1; + tz_rules[0].change = tz_rules[1].change = -1; update_vars (); return; } @@ -424,13 +423,13 @@ tzset_internal (int always) __tzset_parse_tz (tz); } -/* Figure out the exact time (as a time_t) in YEAR +/* Figure out the exact time (as a __time64_t) in YEAR when the change described by RULE will occur and put it in RULE->change, saving YEAR in RULE->computed_for. */ static void compute_change (tz_rule *rule, int year) { - time_t t; + __time64_t t; if (year != -1 && rule->computed_for == year) /* Operations on times in 2 BC will be slower. Oh well. */ @@ -514,9 +513,10 @@ compute_change (tz_rule *rule, int year) /* Figure out the correct timezone for TM and set `__tzname', - `__timezone', and `__daylight' accordingly. */ + `__timezone', and `__daylight' accordingly. + NOTE: this takes a __time64_t value, so passing a time_t value is OK. */ void -__tz_compute (time_t timer, struct tm *tm, int use_localtime) +__tz_compute (__time64_t timer, struct tm *tm, int use_localtime) { compute_change (&tz_rules[0], 1900 + tm->tm_year); compute_change (&tz_rules[1], 1900 + tm->tm_year); @@ -562,20 +562,14 @@ __tzset (void) } weak_alias (__tzset, tzset) -/* Return the `struct tm' representation of *TIMER in the local timezone. +/* Return the `struct tm' representation of TIMER in the local timezone. Use local time if USE_LOCALTIME is nonzero, UTC otherwise. */ struct tm * -__tz_convert (const time_t *timer, int use_localtime, struct tm *tp) +__tz_convert (const __time64_t timer, int use_localtime, struct tm *tp) { long int leap_correction; int leap_extra_secs; - if (timer == NULL) - { - __set_errno (EINVAL); - return NULL; - } - __libc_lock_lock (tzset_lock); /* Update internal database according to current TZ setting. @@ -584,14 +578,14 @@ __tz_convert (const time_t *timer, int use_localtime, struct tm *tp) tzset_internal (tp == &_tmbuf && use_localtime); if (__use_tzfile) - __tzfile_compute (*timer, use_localtime, &leap_correction, + __tzfile_compute (timer, use_localtime, &leap_correction, &leap_extra_secs, tp); else { if (! __offtime (timer, 0, tp)) tp = NULL; else - __tz_compute (*timer, tp, use_localtime); + __tz_compute (timer, tp, use_localtime); leap_correction = 0L; leap_extra_secs = 0; }