summaryrefslogtreecommitdiffstats
path: root/gl/mktime.c
diff options
context:
space:
mode:
authorKristian Schuster <116557017+KriSchu@users.noreply.github.com>2023-02-19 23:49:18 +0100
committerKristian Schuster <116557017+KriSchu@users.noreply.github.com>2023-02-19 23:49:18 +0100
commita0d42777217296c0a7bdb1e1be8d8f6de1b24dd7 (patch)
tree8effe94c57b2f9796ba36090b07551baa8f1e1cb /gl/mktime.c
parentca3d59cd6918c9e2739e783b721d4c1122640fd3 (diff)
parentc07206f2ccc2356aa74bc6813a94c2190017d44e (diff)
downloadmonitoring-plugins-a0d4277.tar.gz
Merge remote-tracking branch 'origin/master' into feature_check_disk_add_ignore_missing_option
Diffstat (limited to 'gl/mktime.c')
-rw-r--r--gl/mktime.c837
1 files changed, 337 insertions, 500 deletions
diff --git a/gl/mktime.c b/gl/mktime.c
index e660a23c..94a4320e 100644
--- a/gl/mktime.c
+++ b/gl/mktime.c
@@ -1,28 +1,37 @@
1/* Convert a 'struct tm' to a time_t value. 1/* Convert a 'struct tm' to a time_t value.
2 Copyright (C) 1993-2013 Free Software Foundation, Inc. 2 Copyright (C) 1993-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library. 3 This file is part of the GNU C Library.
4 Contributed by Paul Eggert <eggert@twinsun.com>. 4 Contributed by Paul Eggert <eggert@twinsun.com>.
5 5
6 The GNU C Library is free software; you can redistribute it and/or 6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public 7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either 8 License as published by the Free Software Foundation; either
9 version 3 of the License, or (at your option) any later version. 9 version 2.1 of the License, or (at your option) any later version.
10 10
11 The GNU C Library is distributed in the hope that it will be useful, 11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details. 14 Lesser General Public License for more details.
15 15
16 You should have received a copy of the GNU General Public 16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see 17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */ 18 <https://www.gnu.org/licenses/>. */
19 19
20/* Define this to have a standalone program to test this implementation of 20/* The following macros influence what gets defined when this file is compiled:
21 mktime. */ 21
22/* #define DEBUG 1 */ 22 Macro/expression Which gnulib module This compilation unit
23 should define
24
25 _LIBC (glibc proper) mktime
26
27 NEED_MKTIME_WORKING mktime rpl_mktime
28 || NEED_MKTIME_WINDOWS
29
30 NEED_MKTIME_INTERNAL mktime-internal mktime_internal
31 */
23 32
24#ifndef _LIBC 33#ifndef _LIBC
25# include <config.h> 34# include <libc-config.h>
26#endif 35#endif
27 36
28/* Assume that leap seconds are possible, unless told otherwise. 37/* Assume that leap seconds are possible, unless told otherwise.
@@ -34,115 +43,123 @@
34 43
35#include <time.h> 44#include <time.h>
36 45
46#include <errno.h>
37#include <limits.h> 47#include <limits.h>
48#include <stdbool.h>
49#include <stdlib.h>
50#include <string.h>
51
52#include <intprops.h>
53#include <verify.h>
54
55#ifndef NEED_MKTIME_INTERNAL
56# define NEED_MKTIME_INTERNAL 0
57#endif
58#ifndef NEED_MKTIME_WINDOWS
59# define NEED_MKTIME_WINDOWS 0
60#endif
61#ifndef NEED_MKTIME_WORKING
62# define NEED_MKTIME_WORKING 0
63#endif
64
65#include "mktime-internal.h"
38 66
39#include <string.h> /* For the real memcpy prototype. */ 67#if !defined _LIBC && (NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS)
40 68static void
41#if DEBUG 69my_tzset (void)
42# include <stdio.h> 70{
43# include <stdlib.h> 71# if NEED_MKTIME_WINDOWS
44/* Make it work even if the system's libc has its own mktime routine. */ 72 /* Rectify the value of the environment variable TZ.
45# undef mktime 73 There are four possible kinds of such values:
46# define mktime my_mktime 74 - Traditional US time zone names, e.g. "PST8PDT". Syntax: see
47#endif /* DEBUG */ 75 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/tzset>
48 76 - Time zone names based on geography, that contain one or more
49/* Some of the code in this file assumes that signed integer overflow 77 slashes, e.g. "Europe/Moscow".
50 silently wraps around. This assumption can't easily be programmed 78 - Time zone names based on geography, without slashes, e.g.
51 around, nor can it be checked for portably at compile-time or 79 "Singapore".
52 easily eliminated at run-time. 80 - Time zone names that contain explicit DST rules. Syntax: see
53 81 <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03>
54 Define WRAPV to 1 if the assumption is valid and if 82 The Microsoft CRT understands only the first kind. It produces incorrect
55 #pragma GCC optimize ("wrapv") 83 results if the value of TZ is of the other kinds.
56 does not trigger GCC bug 51793 84 But in a Cygwin environment, /etc/profile.d/tzset.sh sets TZ to a value
57 <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51793>. 85 of the second kind for most geographies, or of the first kind in a few
58 Otherwise, define it to 0; this forces the use of slower code that, 86 other geographies. If it is of the second kind, neutralize it. For the
59 while not guaranteed by the C Standard, works on all production 87 Microsoft CRT, an absent or empty TZ means the time zone that the user
60 platforms that we know about. */ 88 has set in the Windows Control Panel.
61#ifndef WRAPV 89 If the value of TZ is of the third or fourth kind -- Cygwin programs
62# if (((__GNUC__ == 4 && 4 <= __GNUC_MINOR__) || 4 < __GNUC__) \ 90 understand these syntaxes as well --, it does not matter whether we
63 && defined __GLIBC__) 91 neutralize it or not, since these values occur only when a Cygwin user
64# pragma GCC optimize ("wrapv") 92 has set TZ explicitly; this case is 1. rare and 2. under the user's
65# define WRAPV 1 93 responsibility. */
94 const char *tz = getenv ("TZ");
95 if (tz != NULL && strchr (tz, '/') != NULL)
96 _putenv ("TZ=");
66# else 97# else
67# define WRAPV 0 98 tzset ();
68# endif 99# endif
100}
101# undef __tzset
102# define __tzset() my_tzset ()
69#endif 103#endif
70 104
71/* Verify a requirement at compile-time (unlike assert, which is runtime). */ 105#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL
72#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } 106
107/* A signed type that can represent an integer number of years
108 multiplied by four times the number of seconds in a year. It is
109 needed when converting a tm_year value times the number of seconds
110 in a year. The factor of four comes because these products need
111 to be subtracted from each other, and sometimes with an offset
112 added to them, and then with another timestamp added, without
113 worrying about overflow.
73 114
74/* A signed type that is at least one bit wider than int. */ 115 Much of the code uses long_int to represent __time64_t values, to
75#if INT_MAX <= LONG_MAX / 2 116 lessen the hassle of dealing with platforms where __time64_t is
117 unsigned, and because long_int should suffice to represent all
118 __time64_t values that mktime can generate even on platforms where
119 __time64_t is wider than the int components of struct tm. */
120
121#if INT_MAX <= LONG_MAX / 4 / 366 / 24 / 60 / 60
76typedef long int long_int; 122typedef long int long_int;
77#else 123#else
78typedef long long int long_int; 124typedef long long int long_int;
79#endif 125#endif
80verify (long_int_is_wide_enough, INT_MAX == INT_MAX * (long_int) 2 / 2); 126verify (INT_MAX <= TYPE_MAXIMUM (long_int) / 4 / 366 / 24 / 60 / 60);
81 127
82/* Shift A right by B bits portably, by dividing A by 2**B and 128/* Shift A right by B bits portably, by dividing A by 2**B and
83 truncating towards minus infinity. A and B should be free of side 129 truncating towards minus infinity. B should be in the range 0 <= B
84 effects, and B should be in the range 0 <= B <= INT_BITS - 2, where 130 <= LONG_INT_BITS - 2, where LONG_INT_BITS is the number of useful
85 INT_BITS is the number of useful bits in an int. GNU code can 131 bits in a long_int. LONG_INT_BITS is at least 32.
86 assume that INT_BITS is at least 32.
87 132
88 ISO C99 says that A >> B is implementation-defined if A < 0. Some 133 ISO C99 says that A >> B is implementation-defined if A < 0. Some
89 implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift 134 implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
90 right in the usual way when A < 0, so SHR falls back on division if 135 right in the usual way when A < 0, so SHR falls back on division if
91 ordinary A >> B doesn't seem to be the usual signed shift. */ 136 ordinary A >> B doesn't seem to be the usual signed shift. */
92#define SHR(a, b) \
93 ((-1 >> 1 == -1 \
94 && (long_int) -1 >> 1 == -1 \
95 && ((time_t) -1 >> 1 == -1 || ! TYPE_SIGNED (time_t))) \
96 ? (a) >> (b) \
97 : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
98
99/* The extra casts in the following macros work around compiler bugs,
100 e.g., in Cray C 5.0.3.0. */
101
102/* True if the arithmetic type T is an integer type. bool counts as
103 an integer. */
104#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
105
106/* True if negative values of the signed integer type T use two's
107 complement, or if T is an unsigned integer type. */
108#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
109
110/* True if the arithmetic type T is signed. */
111#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
112
113/* The maximum and minimum values for the integer type T. These
114 macros have undefined behavior if T is signed and has padding bits.
115 If this is a problem for you, please let us know how to fix it for
116 your host. */
117#define TYPE_MINIMUM(t) \
118 ((t) (! TYPE_SIGNED (t) \
119 ? (t) 0 \
120 : ~ TYPE_MAXIMUM (t)))
121#define TYPE_MAXIMUM(t) \
122 ((t) (! TYPE_SIGNED (t) \
123 ? (t) -1 \
124 : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
125
126#ifndef TIME_T_MIN
127# define TIME_T_MIN TYPE_MINIMUM (time_t)
128#endif
129#ifndef TIME_T_MAX
130# define TIME_T_MAX TYPE_MAXIMUM (time_t)
131#endif
132#define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1)
133 137
134verify (time_t_is_integer, TYPE_IS_INTEGER (time_t)); 138static long_int
135verify (twos_complement_arithmetic, 139shr (long_int a, int b)
136 (TYPE_TWOS_COMPLEMENT (int) 140{
137 && TYPE_TWOS_COMPLEMENT (long_int) 141 long_int one = 1;
138 && TYPE_TWOS_COMPLEMENT (time_t))); 142 return (-one >> 1 == -1
143 ? a >> b
144 : (a + (a < 0)) / (one << b) - (a < 0));
145}
146
147/* Bounds for the intersection of __time64_t and long_int. */
148
149static long_int const mktime_min
150 = ((TYPE_SIGNED (__time64_t)
151 && TYPE_MINIMUM (__time64_t) < TYPE_MINIMUM (long_int))
152 ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (__time64_t));
153static long_int const mktime_max
154 = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (__time64_t)
155 ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (__time64_t));
139 156
140#define EPOCH_YEAR 1970 157#define EPOCH_YEAR 1970
141#define TM_YEAR_BASE 1900 158#define TM_YEAR_BASE 1900
142verify (base_year_is_a_multiple_of_100, TM_YEAR_BASE % 100 == 0); 159verify (TM_YEAR_BASE % 100 == 0);
143 160
144/* Return 1 if YEAR + TM_YEAR_BASE is a leap year. */ 161/* Is YEAR + TM_YEAR_BASE a leap year? */
145static int 162static bool
146leapyear (long_int year) 163leapyear (long_int year)
147{ 164{
148 /* Don't add YEAR to TM_YEAR_BASE, as that might overflow. 165 /* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
@@ -166,20 +183,9 @@ const unsigned short int __mon_yday[2][13] =
166 }; 183 };
167 184
168 185
169#ifndef _LIBC 186/* Do the values A and B differ according to the rules for tm_isdst?
170/* Portable standalone applications should supply a <time.h> that 187 A and B differ if one is zero and the other positive. */
171 declares a POSIX-compliant localtime_r, for the benefit of older 188static bool
172 implementations that lack localtime_r or have a nonstandard one.
173 See the gnulib time_r module for one way to implement this. */
174# undef __localtime_r
175# define __localtime_r localtime_r
176# define __mktime_internal mktime_internal
177# include "mktime-internal.h"
178#endif
179
180/* Return 1 if the values A and B differ according to the rules for
181 tm_isdst: A and B differ if one is zero and the other positive. */
182static int
183isdst_differ (int a, int b) 189isdst_differ (int a, int b)
184{ 190{
185 return (!a != !b) && (0 <= a) && (0 <= b); 191 return (!a != !b) && (0 <= a) && (0 <= b);
@@ -187,171 +193,135 @@ isdst_differ (int a, int b)
187 193
188/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) - 194/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
189 (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks 195 (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
190 were not adjusted between the time stamps. 196 were not adjusted between the timestamps.
191 197
192 The YEAR values uses the same numbering as TP->tm_year. Values 198 The YEAR values uses the same numbering as TP->tm_year. Values
193 need not be in the usual range. However, YEAR1 must not be less 199 need not be in the usual range. However, YEAR1 - YEAR0 must not
194 than 2 * INT_MIN or greater than 2 * INT_MAX. 200 overflow even when multiplied by three times the number of seconds
201 in a year, and likewise for YDAY1 - YDAY0 and three times the
202 number of seconds in a day. */
195 203
196 The result may overflow. It is the caller's responsibility to 204static long_int
197 detect overflow. */
198
199static time_t
200ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1, 205ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
201 int year0, int yday0, int hour0, int min0, int sec0) 206 int year0, int yday0, int hour0, int min0, int sec0)
202{ 207{
203 verify (C99_integer_division, -1 / 2 == 0); 208 verify (-1 / 2 == 0);
204 209
205 /* Compute intervening leap days correctly even if year is negative. 210 /* Compute intervening leap days correctly even if year is negative.
206 Take care to avoid integer overflow here. */ 211 Take care to avoid integer overflow here. */
207 int a4 = SHR (year1, 2) + SHR (TM_YEAR_BASE, 2) - ! (year1 & 3); 212 int a4 = shr (year1, 2) + shr (TM_YEAR_BASE, 2) - ! (year1 & 3);
208 int b4 = SHR (year0, 2) + SHR (TM_YEAR_BASE, 2) - ! (year0 & 3); 213 int b4 = shr (year0, 2) + shr (TM_YEAR_BASE, 2) - ! (year0 & 3);
209 int a100 = a4 / 25 - (a4 % 25 < 0); 214 int a100 = (a4 + (a4 < 0)) / 25 - (a4 < 0);
210 int b100 = b4 / 25 - (b4 % 25 < 0); 215 int b100 = (b4 + (b4 < 0)) / 25 - (b4 < 0);
211 int a400 = SHR (a100, 2); 216 int a400 = shr (a100, 2);
212 int b400 = SHR (b100, 2); 217 int b400 = shr (b100, 2);
213 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); 218 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
214 219
215 /* Compute the desired time in time_t precision. Overflow might 220 /* Compute the desired time without overflowing. */
216 occur here. */ 221 long_int years = year1 - year0;
217 time_t tyear1 = year1; 222 long_int days = 365 * years + yday1 - yday0 + intervening_leap_days;
218 time_t years = tyear1 - year0; 223 long_int hours = 24 * days + hour1 - hour0;
219 time_t days = 365 * years + yday1 - yday0 + intervening_leap_days; 224 long_int minutes = 60 * hours + min1 - min0;
220 time_t hours = 24 * days + hour1 - hour0; 225 long_int seconds = 60 * minutes + sec1 - sec0;
221 time_t minutes = 60 * hours + min1 - min0;
222 time_t seconds = 60 * minutes + sec1 - sec0;
223 return seconds; 226 return seconds;
224} 227}
225 228
226/* Return the average of A and B, even if A + B would overflow. */ 229/* Return the average of A and B, even if A + B would overflow.
227static time_t 230 Round toward positive infinity. */
228time_t_avg (time_t a, time_t b) 231static long_int
232long_int_avg (long_int a, long_int b)
229{ 233{
230 return SHR (a, 1) + SHR (b, 1) + (a & b & 1); 234 return shr (a, 1) + shr (b, 1) + ((a | b) & 1);
231} 235}
232 236
233/* Return 1 if A + B does not overflow. If time_t is unsigned and if 237/* Return a long_int value corresponding to (YEAR-YDAY HOUR:MIN:SEC)
234 B's top bit is set, assume that the sum represents A - -B, and 238 minus *TP seconds, assuming no clock adjustments occurred between
235 return 1 if the subtraction does not wrap around. */ 239 the two timestamps.
236static int
237time_t_add_ok (time_t a, time_t b)
238{
239 if (! TYPE_SIGNED (time_t))
240 {
241 time_t sum = a + b;
242 return (sum < a) == (TIME_T_MIDPOINT <= b);
243 }
244 else if (WRAPV)
245 {
246 time_t sum = a + b;
247 return (sum < a) == (b < 0);
248 }
249 else
250 {
251 time_t avg = time_t_avg (a, b);
252 return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
253 }
254}
255 240
256/* Return 1 if A + B does not overflow. */ 241 YEAR and YDAY must not be so large that multiplying them by three times the
257static int 242 number of seconds in a year (or day, respectively) would overflow long_int.
258time_t_int_add_ok (time_t a, int b) 243 *TP should be in the usual range. */
244static long_int
245tm_diff (long_int year, long_int yday, int hour, int min, int sec,
246 struct tm const *tp)
259{ 247{
260 verify (int_no_wider_than_time_t, INT_MAX <= TIME_T_MAX); 248 return ydhms_diff (year, yday, hour, min, sec,
261 if (WRAPV) 249 tp->tm_year, tp->tm_yday,
262 { 250 tp->tm_hour, tp->tm_min, tp->tm_sec);
263 time_t sum = a + b;
264 return (sum < a) == (b < 0);
265 }
266 else
267 {
268 int a_odd = a & 1;
269 time_t avg = SHR (a, 1) + (SHR (b, 1) + (a_odd & b));
270 return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
271 }
272} 251}
273 252
274/* Return a time_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC), 253/* Use CONVERT to convert T to a struct tm value in *TM. T must be in
275 assuming that *T corresponds to *TP and that no clock adjustments 254 range for __time64_t. Return TM if successful, NULL (setting errno) on
276 occurred between *TP and the desired time. 255 failure. */
277 If TP is null, return a value not equal to *T; this avoids false matches. 256static struct tm *
278 If overflow occurs, yield the minimal or maximal value, except do not 257convert_time (struct tm *(*convert) (const __time64_t *, struct tm *),
279 yield a value equal to *T. */ 258 long_int t, struct tm *tm)
280static time_t
281guess_time_tm (long_int year, long_int yday, int hour, int min, int sec,
282 const time_t *t, const struct tm *tp)
283{ 259{
284 if (tp) 260 __time64_t x = t;
285 { 261 return convert (&x, tm);
286 time_t d = ydhms_diff (year, yday, hour, min, sec,
287 tp->tm_year, tp->tm_yday,
288 tp->tm_hour, tp->tm_min, tp->tm_sec);
289 if (time_t_add_ok (*t, d))
290 return *t + d;
291 }
292
293 /* Overflow occurred one way or another. Return the nearest result
294 that is actually in range, except don't report a zero difference
295 if the actual difference is nonzero, as that would cause a false
296 match; and don't oscillate between two values, as that would
297 confuse the spring-forward gap detector. */
298 return (*t < TIME_T_MIDPOINT
299 ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)
300 : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));
301} 262}
302 263
303/* Use CONVERT to convert *T to a broken down time in *TP. 264/* Use CONVERT to convert *T to a broken down time in *TP.
304 If *T is out of range for conversion, adjust it so that 265 If *T is out of range for conversion, adjust it so that
305 it is the nearest in-range value and then convert that. */ 266 it is the nearest in-range value and then convert that.
267 A value is in range if it fits in both __time64_t and long_int.
268 Return TP on success, NULL (setting errno) on failure. */
306static struct tm * 269static struct tm *
307ranged_convert (struct tm *(*convert) (const time_t *, struct tm *), 270ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *),
308 time_t *t, struct tm *tp) 271 long_int *t, struct tm *tp)
309{ 272{
310 struct tm *r = convert (t, tp); 273 long_int t1 = (*t < mktime_min ? mktime_min
311 274 : *t <= mktime_max ? *t : mktime_max);
312 if (!r && *t) 275 struct tm *r = convert_time (convert, t1, tp);
276 if (r)
313 { 277 {
314 time_t bad = *t; 278 *t = t1;
315 time_t ok = 0; 279 return r;
280 }
281 if (errno != EOVERFLOW)
282 return NULL;
316 283
317 /* BAD is a known unconvertible time_t, and OK is a known good one. 284 long_int bad = t1;
318 Use binary search to narrow the range between BAD and OK until 285 long_int ok = 0;
319 they differ by 1. */ 286 struct tm oktm; oktm.tm_sec = -1;
320 while (bad != ok + (bad < 0 ? -1 : 1))
321 {
322 time_t mid = *t = time_t_avg (ok, bad);
323 r = convert (t, tp);
324 if (r)
325 ok = mid;
326 else
327 bad = mid;
328 }
329 287
330 if (!r && ok) 288 /* BAD is a known out-of-range value, and OK is a known in-range one.
331 { 289 Use binary search to narrow the range between BAD and OK until
332 /* The last conversion attempt failed; 290 they differ by 1. */
333 revert to the most recent successful attempt. */ 291 while (true)
334 *t = ok; 292 {
335 r = convert (t, tp); 293 long_int mid = long_int_avg (ok, bad);
336 } 294 if (mid == ok || mid == bad)
295 break;
296 if (convert_time (convert, mid, tp))
297 ok = mid, oktm = *tp;
298 else if (errno != EOVERFLOW)
299 return NULL;
300 else
301 bad = mid;
337 } 302 }
338 303
339 return r; 304 if (oktm.tm_sec < 0)
305 return NULL;
306 *t = ok;
307 *tp = oktm;
308 return tp;
340} 309}
341 310
342 311
343/* Convert *TP to a time_t value, inverting 312/* Convert *TP to a __time64_t value, inverting
344 the monotonic and mostly-unit-linear conversion function CONVERT. 313 the monotonic and mostly-unit-linear conversion function CONVERT.
345 Use *OFFSET to keep track of a guess at the offset of the result, 314 Use *OFFSET to keep track of a guess at the offset of the result,
346 compared to what the result would be for UTC without leap seconds. 315 compared to what the result would be for UTC without leap seconds.
347 If *OFFSET's guess is correct, only one CONVERT call is needed. 316 If *OFFSET's guess is correct, only one CONVERT call is needed.
317 If successful, set *TP to the canonicalized struct tm;
318 otherwise leave *TP alone, return ((time_t) -1) and set errno.
348 This function is external because it is used also by timegm.c. */ 319 This function is external because it is used also by timegm.c. */
349time_t 320__time64_t
350__mktime_internal (struct tm *tp, 321__mktime_internal (struct tm *tp,
351 struct tm *(*convert) (const time_t *, struct tm *), 322 struct tm *(*convert) (const __time64_t *, struct tm *),
352 time_t *offset) 323 mktime_offset_t *offset)
353{ 324{
354 time_t t, gt, t0, t1, t2;
355 struct tm tm; 325 struct tm tm;
356 326
357 /* The maximum number of probes (calls to CONVERT) should be enough 327 /* The maximum number of probes (calls to CONVERT) should be enough
@@ -371,7 +341,7 @@ __mktime_internal (struct tm *tp,
371 int isdst = tp->tm_isdst; 341 int isdst = tp->tm_isdst;
372 342
373 /* 1 if the previous probe was DST. */ 343 /* 1 if the previous probe was DST. */
374 int dst2; 344 int dst2 = 0;
375 345
376 /* Ensure that mon is in range, and set year accordingly. */ 346 /* Ensure that mon is in range, and set year accordingly. */
377 int mon_remainder = mon % 12; 347 int mon_remainder = mon % 12;
@@ -381,9 +351,7 @@ __mktime_internal (struct tm *tp,
381 long_int year = lyear_requested + mon_years; 351 long_int year = lyear_requested + mon_years;
382 352
383 /* The other values need not be in range: 353 /* The other values need not be in range:
384 the remaining code handles minor overflows correctly, 354 the remaining code handles overflows correctly. */
385 assuming int and time_t arithmetic wraps around.
386 Major overflows are caught at the end. */
387 355
388 /* Calculate day of year from year, month, and day of month. 356 /* Calculate day of year from year, month, and day of month.
389 The result need not be in range. */ 357 The result need not be in range. */
@@ -393,14 +361,15 @@ __mktime_internal (struct tm *tp,
393 long_int lmday = mday; 361 long_int lmday = mday;
394 long_int yday = mon_yday + lmday; 362 long_int yday = mon_yday + lmday;
395 363
396 time_t guessed_offset = *offset; 364 mktime_offset_t off = *offset;
365 int negative_offset_guess;
397 366
398 int sec_requested = sec; 367 int sec_requested = sec;
399 368
400 if (LEAP_SECONDS_POSSIBLE) 369 if (LEAP_SECONDS_POSSIBLE)
401 { 370 {
402 /* Handle out-of-range seconds specially, 371 /* Handle out-of-range seconds specially,
403 since ydhms_tm_diff assumes every minute has 60 seconds. */ 372 since ydhms_diff assumes every minute has 60 seconds. */
404 if (sec < 0) 373 if (sec < 0)
405 sec = 0; 374 sec = 0;
406 if (59 < sec) 375 if (59 < sec)
@@ -410,91 +379,47 @@ __mktime_internal (struct tm *tp,
410 /* Invert CONVERT by probing. First assume the same offset as last 379 /* Invert CONVERT by probing. First assume the same offset as last
411 time. */ 380 time. */
412 381
413 t0 = ydhms_diff (year, yday, hour, min, sec, 382 INT_SUBTRACT_WRAPV (0, off, &negative_offset_guess);
414 EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - guessed_offset); 383 long_int t0 = ydhms_diff (year, yday, hour, min, sec,
384 EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0,
385 negative_offset_guess);
386 long_int t = t0, t1 = t0, t2 = t0;
387
388 /* Repeatedly use the error to improve the guess. */
415 389
416 if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3) 390 while (true)
417 { 391 {
418 /* time_t isn't large enough to rule out overflows, so check 392 if (! ranged_convert (convert, &t, &tm))
419 for major overflows. A gross check suffices, since if t0 393 return -1;
420 has overflowed, it is off by a multiple of TIME_T_MAX - 394 long_int dt = tm_diff (year, yday, hour, min, sec, &tm);
421 TIME_T_MIN + 1. So ignore any component of the difference 395 if (dt == 0)
422 that is bounded by a small value. */ 396 break;
423 397
424 /* Approximate log base 2 of the number of time units per 398 if (t == t1 && t != t2
425 biennium. A biennium is 2 years; use this unit instead of 399 && (tm.tm_isdst < 0
426 years to avoid integer overflow. For example, 2 average 400 || (isdst < 0
427 Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds, 401 ? dst2 <= (tm.tm_isdst != 0)
428 which is 63113904 seconds, and rint (log2 (63113904)) is 402 : (isdst != 0) != (tm.tm_isdst != 0))))
429 26. */ 403 /* We can't possibly find a match, as we are oscillating
430 int ALOG2_SECONDS_PER_BIENNIUM = 26; 404 between two values. The requested time probably falls
431 int ALOG2_MINUTES_PER_BIENNIUM = 20; 405 within a spring-forward gap of size DT. Follow the common
432 int ALOG2_HOURS_PER_BIENNIUM = 14; 406 practice in this case, which is to return a time that is DT
433 int ALOG2_DAYS_PER_BIENNIUM = 10; 407 away from the requested time, preferring a time whose
434 int LOG2_YEARS_PER_BIENNIUM = 1; 408 tm_isdst differs from the requested value. (If no tm_isdst
435 409 was requested and only one of the two values has a nonzero
436 int approx_requested_biennia = 410 tm_isdst, prefer that value.) In practice, this is more
437 (SHR (year_requested, LOG2_YEARS_PER_BIENNIUM) 411 useful than returning -1. */
438 - SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM) 412 goto offset_found;
439 + SHR (mday, ALOG2_DAYS_PER_BIENNIUM) 413
440 + SHR (hour, ALOG2_HOURS_PER_BIENNIUM) 414 remaining_probes--;
441 + SHR (min, ALOG2_MINUTES_PER_BIENNIUM) 415 if (remaining_probes == 0)
442 + (LEAP_SECONDS_POSSIBLE
443 ? 0
444 : SHR (sec, ALOG2_SECONDS_PER_BIENNIUM)));
445
446 int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM);
447 int diff = approx_biennia - approx_requested_biennia;
448 int approx_abs_diff = diff < 0 ? -1 - diff : diff;
449
450 /* IRIX 4.0.5 cc miscalculates TIME_T_MIN / 3: it erroneously
451 gives a positive value of 715827882. Setting a variable
452 first then doing math on it seems to work.
453 (ghazi@caip.rutgers.edu) */
454 time_t time_t_max = TIME_T_MAX;
455 time_t time_t_min = TIME_T_MIN;
456 time_t overflow_threshold =
457 (time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
458
459 if (overflow_threshold < approx_abs_diff)
460 { 416 {
461 /* Overflow occurred. Try repairing it; this might work if 417 __set_errno (EOVERFLOW);
462 the time zone offset is enough to undo the overflow. */ 418 return -1;
463 time_t repaired_t0 = -1 - t0;
464 approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
465 diff = approx_biennia - approx_requested_biennia;
466 approx_abs_diff = diff < 0 ? -1 - diff : diff;
467 if (overflow_threshold < approx_abs_diff)
468 return -1;
469 guessed_offset += repaired_t0 - t0;
470 t0 = repaired_t0;
471 } 419 }
472 }
473
474 /* Repeatedly use the error to improve the guess. */
475 420
476 for (t = t1 = t2 = t0, dst2 = 0; 421 t1 = t2, t2 = t, t += dt, dst2 = tm.tm_isdst != 0;
477 (gt = guess_time_tm (year, yday, hour, min, sec, &t, 422 }
478 ranged_convert (convert, &t, &tm)),
479 t != gt);
480 t1 = t2, t2 = t, t = gt, dst2 = tm.tm_isdst != 0)
481 if (t == t1 && t != t2
482 && (tm.tm_isdst < 0
483 || (isdst < 0
484 ? dst2 <= (tm.tm_isdst != 0)
485 : (isdst != 0) != (tm.tm_isdst != 0))))
486 /* We can't possibly find a match, as we are oscillating
487 between two values. The requested time probably falls
488 within a spring-forward gap of size GT - T. Follow the common
489 practice in this case, which is to return a time that is GT - T
490 away from the requested time, preferring a time whose
491 tm_isdst differs from the requested value. (If no tm_isdst
492 was requested and only one of the two values has a nonzero
493 tm_isdst, prefer that value.) In practice, this is more
494 useful than returning -1. */
495 goto offset_found;
496 else if (--remaining_probes == 0)
497 return -1;
498 423
499 /* We have a match. Check whether tm.tm_isdst has the requested 424 /* We have a match. Check whether tm.tm_isdst has the requested
500 value, if any. */ 425 value, if any. */
@@ -504,8 +429,13 @@ __mktime_internal (struct tm *tp,
504 time with the right value, and use its UTC offset. 429 time with the right value, and use its UTC offset.
505 430
506 Heuristic: probe the adjacent timestamps in both directions, 431 Heuristic: probe the adjacent timestamps in both directions,
507 looking for the desired isdst. This should work for all real 432 looking for the desired isdst. If none is found within a
508 time zone histories in the tz database. */ 433 reasonable duration bound, assume a one-hour DST difference.
434 This should work for all real time zone histories in the tz
435 database. */
436
437 /* +1 if we wanted standard time but got DST, -1 if the reverse. */
438 int dst_difference = (isdst == 0) - (tm.tm_isdst == 0);
509 439
510 /* Distance between probes when looking for a DST boundary. In 440 /* Distance between probes when looking for a DST boundary. In
511 tzdata2003a, the shortest period of DST is 601200 seconds 441 tzdata2003a, the shortest period of DST is 601200 seconds
@@ -516,12 +446,14 @@ __mktime_internal (struct tm *tp,
516 periods when probing. */ 446 periods when probing. */
517 int stride = 601200; 447 int stride = 601200;
518 448
519 /* The longest period of DST in tzdata2003a is 536454000 seconds 449 /* In TZDB 2021e, the longest period of DST (or of non-DST), in
520 (e.g., America/Jujuy starting 1946-10-01 01:00). The longest 450 which the DST (or adjacent DST) difference is not one hour,
521 period of non-DST is much longer, but it makes no real sense 451 is 457243209 seconds: e.g., America/Cambridge_Bay with leap
522 to search for more than a year of non-DST, so use the DST 452 seconds, starting 1965-10-31 00:00 in a switch from
523 max. */ 453 double-daylight time (-05) to standard time (-07), and
524 int duration_max = 536454000; 454 continuing to 1980-04-27 02:00 in a switch from standard time
455 (-07) to daylight time (-06). */
456 int duration_max = 457243209;
525 457
526 /* Search in both directions, so the maximum distance is half 458 /* Search in both directions, so the maximum distance is half
527 the duration; add the stride to avoid off-by-1 problems. */ 459 the duration; add the stride to avoid off-by-1 problems. */
@@ -531,211 +463,116 @@ __mktime_internal (struct tm *tp,
531 463
532 for (delta = stride; delta < delta_bound; delta += stride) 464 for (delta = stride; delta < delta_bound; delta += stride)
533 for (direction = -1; direction <= 1; direction += 2) 465 for (direction = -1; direction <= 1; direction += 2)
534 if (time_t_int_add_ok (t, delta * direction)) 466 {
535 { 467 long_int ot;
536 time_t ot = t + delta * direction; 468 if (! INT_ADD_WRAPV (t, delta * direction, &ot))
537 struct tm otm; 469 {
538 ranged_convert (convert, &ot, &otm); 470 struct tm otm;
539 if (! isdst_differ (isdst, otm.tm_isdst)) 471 if (! ranged_convert (convert, &ot, &otm))
540 { 472 return -1;
541 /* We found the desired tm_isdst. 473 if (! isdst_differ (isdst, otm.tm_isdst))
542 Extrapolate back to the desired time. */ 474 {
543 t = guess_time_tm (year, yday, hour, min, sec, &ot, &otm); 475 /* We found the desired tm_isdst.
544 ranged_convert (convert, &t, &tm); 476 Extrapolate back to the desired time. */
545 goto offset_found; 477 long_int gt = ot + tm_diff (year, yday, hour, min, sec,
546 } 478 &otm);
547 } 479 if (mktime_min <= gt && gt <= mktime_max)
480 {
481 if (convert_time (convert, gt, &tm))
482 {
483 t = gt;
484 goto offset_found;
485 }
486 if (errno != EOVERFLOW)
487 return -1;
488 }
489 }
490 }
491 }
492
493 /* No unusual DST offset was found nearby. Assume one-hour DST. */
494 t += 60 * 60 * dst_difference;
495 if (mktime_min <= t && t <= mktime_max && convert_time (convert, t, &tm))
496 goto offset_found;
497
498 __set_errno (EOVERFLOW);
499 return -1;
548 } 500 }
549 501
550 offset_found: 502 offset_found:
551 *offset = guessed_offset + t - t0; 503 /* Set *OFFSET to the low-order bits of T - T0 - NEGATIVE_OFFSET_GUESS.
504 This is just a heuristic to speed up the next mktime call, and
505 correctness is unaffected if integer overflow occurs here. */
506 INT_SUBTRACT_WRAPV (t, t0, offset);
507 INT_SUBTRACT_WRAPV (*offset, negative_offset_guess, offset);
552 508
553 if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec) 509 if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
554 { 510 {
555 /* Adjust time to reflect the tm_sec requested, not the normalized value. 511 /* Adjust time to reflect the tm_sec requested, not the normalized value.
556 Also, repair any damage from a false match due to a leap second. */ 512 Also, repair any damage from a false match due to a leap second. */
557 int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec; 513 long_int sec_adjustment = sec == 0 && tm.tm_sec == 60;
558 if (! time_t_int_add_ok (t, sec_requested)) 514 sec_adjustment -= sec;
559 return -1; 515 sec_adjustment += sec_requested;
560 t1 = t + sec_requested; 516 if (INT_ADD_WRAPV (t, sec_adjustment, &t)
561 if (! time_t_int_add_ok (t1, sec_adjustment)) 517 || ! (mktime_min <= t && t <= mktime_max))
562 return -1; 518 {
563 t2 = t1 + sec_adjustment; 519 __set_errno (EOVERFLOW);
564 if (! convert (&t2, &tm)) 520 return -1;
521 }
522 if (! convert_time (convert, t, &tm))
565 return -1; 523 return -1;
566 t = t2;
567 } 524 }
568 525
569 *tp = tm; 526 *tp = tm;
570 return t; 527 return t;
571} 528}
572 529
530#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL */
573 531
574/* FIXME: This should use a signed type wide enough to hold any UTC 532#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS
575 offset in seconds. 'int' should be good enough for GNU code. We
576 can't fix this unilaterally though, as other modules invoke
577 __mktime_internal. */
578static time_t localtime_offset;
579 533
580/* Convert *TP to a time_t value. */ 534/* Convert *TP to a __time64_t value. */
581time_t 535__time64_t
582mktime (struct tm *tp) 536__mktime64 (struct tm *tp)
583{ 537{
584#ifdef _LIBC
585 /* POSIX.1 8.1.1 requires that whenever mktime() is called, the 538 /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
586 time zone names contained in the external variable 'tzname' shall 539 time zone names contained in the external variable 'tzname' shall
587 be set as if the tzset() function had been called. */ 540 be set as if the tzset() function had been called. */
588 __tzset (); 541 __tzset ();
589#endif
590 542
591 return __mktime_internal (tp, __localtime_r, &localtime_offset); 543# if defined _LIBC || NEED_MKTIME_WORKING
544 static mktime_offset_t localtime_offset;
545 return __mktime_internal (tp, __localtime64_r, &localtime_offset);
546# else
547# undef mktime
548 return mktime (tp);
549# endif
592} 550}
551#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */
593 552
594#ifdef weak_alias 553#if defined _LIBC && __TIMESIZE != 64
595weak_alias (mktime, timelocal)
596#endif
597
598#ifdef _LIBC
599libc_hidden_def (mktime)
600libc_hidden_weak (timelocal)
601#endif
602
603#if DEBUG
604 554
605static int 555libc_hidden_def (__mktime64)
606not_equal_tm (const struct tm *a, const struct tm *b)
607{
608 return ((a->tm_sec ^ b->tm_sec)
609 | (a->tm_min ^ b->tm_min)
610 | (a->tm_hour ^ b->tm_hour)
611 | (a->tm_mday ^ b->tm_mday)
612 | (a->tm_mon ^ b->tm_mon)
613 | (a->tm_year ^ b->tm_year)
614 | (a->tm_yday ^ b->tm_yday)
615 | isdst_differ (a->tm_isdst, b->tm_isdst));
616}
617 556
618static void 557time_t
619print_tm (const struct tm *tp) 558mktime (struct tm *tp)
620{
621 if (tp)
622 printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
623 tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
624 tp->tm_hour, tp->tm_min, tp->tm_sec,
625 tp->tm_yday, tp->tm_wday, tp->tm_isdst);
626 else
627 printf ("0");
628}
629
630static int
631check_result (time_t tk, struct tm tmk, time_t tl, const struct tm *lt)
632{
633 if (tk != tl || !lt || not_equal_tm (&tmk, lt))
634 {
635 printf ("mktime (");
636 print_tm (lt);
637 printf (")\nyields (");
638 print_tm (&tmk);
639 printf (") == %ld, should be %ld\n", (long int) tk, (long int) tl);
640 return 1;
641 }
642
643 return 0;
644}
645
646int
647main (int argc, char **argv)
648{ 559{
649 int status = 0; 560 struct tm tm = *tp;
650 struct tm tm, tmk, tml; 561 __time64_t t = __mktime64 (&tm);
651 struct tm *lt; 562 if (in_time_t_range (t))
652 time_t tk, tl, tl1;
653 char trailer;
654
655 if ((argc == 3 || argc == 4)
656 && (sscanf (argv[1], "%d-%d-%d%c",
657 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
658 == 3)
659 && (sscanf (argv[2], "%d:%d:%d%c",
660 &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
661 == 3))
662 { 563 {
663 tm.tm_year -= TM_YEAR_BASE; 564 *tp = tm;
664 tm.tm_mon--; 565 return t;
665 tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
666 tmk = tm;
667 tl = mktime (&tmk);
668 lt = localtime (&tl);
669 if (lt)
670 {
671 tml = *lt;
672 lt = &tml;
673 }
674 printf ("mktime returns %ld == ", (long int) tl);
675 print_tm (&tmk);
676 printf ("\n");
677 status = check_result (tl, tmk, tl, lt);
678 } 566 }
679 else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0)) 567 else
680 { 568 {
681 time_t from = atol (argv[1]); 569 __set_errno (EOVERFLOW);
682 time_t by = atol (argv[2]); 570 return -1;
683 time_t to = atol (argv[3]);
684
685 if (argc == 4)
686 for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
687 {
688 lt = localtime (&tl);
689 if (lt)
690 {
691 tmk = tml = *lt;
692 tk = mktime (&tmk);
693 status |= check_result (tk, tmk, tl, &tml);
694 }
695 else
696 {
697 printf ("localtime (%ld) yields 0\n", (long int) tl);
698 status = 1;
699 }
700 tl1 = tl + by;
701 if ((tl1 < tl) != (by < 0))
702 break;
703 }
704 else
705 for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
706 {
707 /* Null benchmark. */
708 lt = localtime (&tl);
709 if (lt)
710 {
711 tmk = tml = *lt;
712 tk = tl;
713 status |= check_result (tk, tmk, tl, &tml);
714 }
715 else
716 {
717 printf ("localtime (%ld) yields 0\n", (long int) tl);
718 status = 1;
719 }
720 tl1 = tl + by;
721 if ((tl1 < tl) != (by < 0))
722 break;
723 }
724 } 571 }
725 else
726 printf ("Usage:\
727\t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
728\t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
729\t%s FROM BY TO - # Do not test those values (for benchmark).\n",
730 argv[0], argv[0], argv[0]);
731
732 return status;
733} 572}
734 573
735#endif /* DEBUG */ 574#endif
736 575
737/* 576weak_alias (mktime, timelocal)
738Local Variables: 577libc_hidden_def (mktime)
739compile-command: "gcc -DDEBUG -I. -Wall -W -O2 -g mktime.c -o mktime" 578libc_hidden_weak (timelocal)
740End:
741*/