| 1 | /* Convert a 'struct tm' to a time_t value. | 
|---|
| 2 | Copyright (C) 1993-2020 Free Software Foundation, Inc. | 
|---|
| 3 | This file is part of the GNU C Library. | 
|---|
| 4 | Contributed by Paul Eggert <eggert@twinsun.com>. | 
|---|
| 5 |  | 
|---|
| 6 | The GNU C Library is free software; you can redistribute it and/or | 
|---|
| 7 | modify it under the terms of the GNU Lesser General Public | 
|---|
| 8 | License as published by the Free Software Foundation; either | 
|---|
| 9 | version 2.1 of the License, or (at your option) any later version. | 
|---|
| 10 |  | 
|---|
| 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 | 
|---|
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
| 14 | Lesser General Public License for more details. | 
|---|
| 15 |  | 
|---|
| 16 | You should have received a copy of the GNU Lesser General Public | 
|---|
| 17 | License along with the GNU C Library; if not, see | 
|---|
| 18 | <https://www.gnu.org/licenses/>.  */ | 
|---|
| 19 |  | 
|---|
| 20 | /* The following macros influence what gets defined when this file is compiled: | 
|---|
| 21 |  | 
|---|
| 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 | */ | 
|---|
| 32 |  | 
|---|
| 33 | #ifndef _LIBC | 
|---|
| 34 | # include <libc-config.h> | 
|---|
| 35 | #endif | 
|---|
| 36 |  | 
|---|
| 37 | /* Assume that leap seconds are possible, unless told otherwise. | 
|---|
| 38 | If the host has a 'zic' command with a '-L leapsecondfilename' option, | 
|---|
| 39 | then it supports leap seconds; otherwise it probably doesn't.  */ | 
|---|
| 40 | #ifndef LEAP_SECONDS_POSSIBLE | 
|---|
| 41 | # define LEAP_SECONDS_POSSIBLE 1 | 
|---|
| 42 | #endif | 
|---|
| 43 |  | 
|---|
| 44 | #include <time.h> | 
|---|
| 45 |  | 
|---|
| 46 | #include <errno.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" | 
|---|
| 66 |  | 
|---|
| 67 | #if !defined _LIBC && (NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS) | 
|---|
| 68 | static void | 
|---|
| 69 | my_tzset (void) | 
|---|
| 70 | { | 
|---|
| 71 | # if NEED_MKTIME_WINDOWS | 
|---|
| 72 | /* Rectify the value of the environment variable TZ. | 
|---|
| 73 | There are four possible kinds of such values: | 
|---|
| 74 | - Traditional US time zone names, e.g. "PST8PDT".  Syntax: see | 
|---|
| 75 | <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/tzset> | 
|---|
| 76 | - Time zone names based on geography, that contain one or more | 
|---|
| 77 | slashes, e.g. "Europe/Moscow". | 
|---|
| 78 | - Time zone names based on geography, without slashes, e.g. | 
|---|
| 79 | "Singapore". | 
|---|
| 80 | - Time zone names that contain explicit DST rules.  Syntax: see | 
|---|
| 81 | <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03> | 
|---|
| 82 | The Microsoft CRT understands only the first kind.  It produces incorrect | 
|---|
| 83 | results if the value of TZ is of the other kinds. | 
|---|
| 84 | But in a Cygwin environment, /etc/profile.d/tzset.sh sets TZ to a value | 
|---|
| 85 | of the second kind for most geographies, or of the first kind in a few | 
|---|
| 86 | other geographies.  If it is of the second kind, neutralize it.  For the | 
|---|
| 87 | Microsoft CRT, an absent or empty TZ means the time zone that the user | 
|---|
| 88 | has set in the Windows Control Panel. | 
|---|
| 89 | If the value of TZ is of the third or fourth kind -- Cygwin programs | 
|---|
| 90 | understand these syntaxes as well --, it does not matter whether we | 
|---|
| 91 | neutralize it or not, since these values occur only when a Cygwin user | 
|---|
| 92 | has set TZ explicitly; this case is 1. rare and 2. under the user's | 
|---|
| 93 | responsibility.  */ | 
|---|
| 94 | const char *tz = getenv ( "TZ"); | 
|---|
| 95 | if (tz != NULL && strchr (tz, '/') != NULL) | 
|---|
| 96 | _putenv ( "TZ="); | 
|---|
| 97 | # elif HAVE_TZSET | 
|---|
| 98 | tzset (); | 
|---|
| 99 | # endif | 
|---|
| 100 | } | 
|---|
| 101 | # undef __tzset | 
|---|
| 102 | # define __tzset() my_tzset () | 
|---|
| 103 | #endif | 
|---|
| 104 |  | 
|---|
| 105 | #if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL | 
|---|
| 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. | 
|---|
| 114 |  | 
|---|
| 115 | Much of the code uses long_int to represent __time64_t values, to | 
|---|
| 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 | 
|---|
| 122 | typedef long int long_int; | 
|---|
| 123 | #else | 
|---|
| 124 | typedef long long int long_int; | 
|---|
| 125 | #endif | 
|---|
| 126 | verify (INT_MAX <= TYPE_MAXIMUM (long_int) / 4 / 366 / 24 / 60 / 60); | 
|---|
| 127 |  | 
|---|
| 128 | /* Shift A right by B bits portably, by dividing A by 2**B and | 
|---|
| 129 | truncating towards minus infinity.  B should be in the range 0 <= B | 
|---|
| 130 | <= LONG_INT_BITS - 2, where LONG_INT_BITS is the number of useful | 
|---|
| 131 | bits in a long_int.  LONG_INT_BITS is at least 32. | 
|---|
| 132 |  | 
|---|
| 133 | ISO C99 says that A >> B is implementation-defined if A < 0.  Some | 
|---|
| 134 | implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift | 
|---|
| 135 | right in the usual way when A < 0, so SHR falls back on division if | 
|---|
| 136 | ordinary A >> B doesn't seem to be the usual signed shift.  */ | 
|---|
| 137 |  | 
|---|
| 138 | static long_int | 
|---|
| 139 | shr (long_int a, int b) | 
|---|
| 140 | { | 
|---|
| 141 | long_int one = 1; | 
|---|
| 142 | return (-one >> 1 == -1 | 
|---|
| 143 | ? a >> b | 
|---|
| 144 | : a / (one << b) - (a % (one << b) < 0)); | 
|---|
| 145 | } | 
|---|
| 146 |  | 
|---|
| 147 | /* Bounds for the intersection of __time64_t and long_int.  */ | 
|---|
| 148 |  | 
|---|
| 149 | static 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)); | 
|---|
| 153 | static long_int const mktime_max | 
|---|
| 154 | = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (__time64_t) | 
|---|
| 155 | ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (__time64_t)); | 
|---|
| 156 |  | 
|---|
| 157 | #define EPOCH_YEAR 1970 | 
|---|
| 158 | #define TM_YEAR_BASE 1900 | 
|---|
| 159 | verify (TM_YEAR_BASE % 100 == 0); | 
|---|
| 160 |  | 
|---|
| 161 | /* Is YEAR + TM_YEAR_BASE a leap year?  */ | 
|---|
| 162 | static bool | 
|---|
| 163 | leapyear (long_int year) | 
|---|
| 164 | { | 
|---|
| 165 | /* Don't add YEAR to TM_YEAR_BASE, as that might overflow. | 
|---|
| 166 | Also, work even if YEAR is negative.  */ | 
|---|
| 167 | return | 
|---|
| 168 | ((year & 3) == 0 | 
|---|
| 169 | && (year % 100 != 0 | 
|---|
| 170 | || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3))); | 
|---|
| 171 | } | 
|---|
| 172 |  | 
|---|
| 173 | /* How many days come before each month (0-12).  */ | 
|---|
| 174 | #ifndef _LIBC | 
|---|
| 175 | static | 
|---|
| 176 | #endif | 
|---|
| 177 | const unsigned short int __mon_yday[2][13] = | 
|---|
| 178 | { | 
|---|
| 179 | /* Normal years.  */ | 
|---|
| 180 | { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, | 
|---|
| 181 | /* Leap years.  */ | 
|---|
| 182 | { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } | 
|---|
| 183 | }; | 
|---|
| 184 |  | 
|---|
| 185 |  | 
|---|
| 186 | /* Do the values A and B differ according to the rules for tm_isdst? | 
|---|
| 187 | A and B differ if one is zero and the other positive.  */ | 
|---|
| 188 | static bool | 
|---|
| 189 | isdst_differ (int a, int b) | 
|---|
| 190 | { | 
|---|
| 191 | return (!a != !b) && (0 <= a) && (0 <= b); | 
|---|
| 192 | } | 
|---|
| 193 |  | 
|---|
| 194 | /* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) - | 
|---|
| 195 | (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks | 
|---|
| 196 | were not adjusted between the timestamps. | 
|---|
| 197 |  | 
|---|
| 198 | The YEAR values uses the same numbering as TP->tm_year.  Values | 
|---|
| 199 | need not be in the usual range.  However, YEAR1 - YEAR0 must not | 
|---|
| 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.  */ | 
|---|
| 203 |  | 
|---|
| 204 | static long_int | 
|---|
| 205 | ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1, | 
|---|
| 206 | int year0, int yday0, int hour0, int min0, int sec0) | 
|---|
| 207 | { | 
|---|
| 208 | verify (-1 / 2 == 0); | 
|---|
| 209 |  | 
|---|
| 210 | /* Compute intervening leap days correctly even if year is negative. | 
|---|
| 211 | Take care to avoid integer overflow here.  */ | 
|---|
| 212 | int a4 = shr (year1, 2) + shr (TM_YEAR_BASE, 2) - ! (year1 & 3); | 
|---|
| 213 | int b4 = shr (year0, 2) + shr (TM_YEAR_BASE, 2) - ! (year0 & 3); | 
|---|
| 214 | int a100 = a4 / 25 - (a4 % 25 < 0); | 
|---|
| 215 | int b100 = b4 / 25 - (b4 % 25 < 0); | 
|---|
| 216 | int a400 = shr (a100, 2); | 
|---|
| 217 | int b400 = shr (b100, 2); | 
|---|
| 218 | int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); | 
|---|
| 219 |  | 
|---|
| 220 | /* Compute the desired time without overflowing.  */ | 
|---|
| 221 | long_int years = year1 - year0; | 
|---|
| 222 | long_int days = 365 * years + yday1 - yday0 + intervening_leap_days; | 
|---|
| 223 | long_int hours = 24 * days + hour1 - hour0; | 
|---|
| 224 | long_int minutes = 60 * hours + min1 - min0; | 
|---|
| 225 | long_int seconds = 60 * minutes + sec1 - sec0; | 
|---|
| 226 | return seconds; | 
|---|
| 227 | } | 
|---|
| 228 |  | 
|---|
| 229 | /* Return the average of A and B, even if A + B would overflow. | 
|---|
| 230 | Round toward positive infinity.  */ | 
|---|
| 231 | static long_int | 
|---|
| 232 | long_int_avg (long_int a, long_int b) | 
|---|
| 233 | { | 
|---|
| 234 | return shr (a, 1) + shr (b, 1) + ((a | b) & 1); | 
|---|
| 235 | } | 
|---|
| 236 |  | 
|---|
| 237 | /* Return a long_int value corresponding to (YEAR-YDAY HOUR:MIN:SEC) | 
|---|
| 238 | minus *TP seconds, assuming no clock adjustments occurred between | 
|---|
| 239 | the two timestamps. | 
|---|
| 240 |  | 
|---|
| 241 | YEAR and YDAY must not be so large that multiplying them by three times the | 
|---|
| 242 | number of seconds in a year (or day, respectively) would overflow long_int. | 
|---|
| 243 | *TP should be in the usual range.  */ | 
|---|
| 244 | static long_int | 
|---|
| 245 | tm_diff (long_int year, long_int yday, int hour, int min, int sec, | 
|---|
| 246 | struct tm const *tp) | 
|---|
| 247 | { | 
|---|
| 248 | return ydhms_diff (year, yday, hour, min, sec, | 
|---|
| 249 | tp->tm_year, tp->tm_yday, | 
|---|
| 250 | tp->tm_hour, tp->tm_min, tp->tm_sec); | 
|---|
| 251 | } | 
|---|
| 252 |  | 
|---|
| 253 | /* Use CONVERT to convert T to a struct tm value in *TM.  T must be in | 
|---|
| 254 | range for __time64_t.  Return TM if successful, NULL (setting errno) on | 
|---|
| 255 | failure.  */ | 
|---|
| 256 | static struct tm * | 
|---|
| 257 | convert_time (struct tm *(*convert) (const __time64_t *, struct tm *), | 
|---|
| 258 | long_int t, struct tm *tm) | 
|---|
| 259 | { | 
|---|
| 260 | __time64_t x = t; | 
|---|
| 261 | return convert (&x, tm); | 
|---|
| 262 | } | 
|---|
| 263 |  | 
|---|
| 264 | /* Use CONVERT to convert *T to a broken down time in *TP. | 
|---|
| 265 | If *T is out of range for conversion, adjust it so 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.  */ | 
|---|
| 269 | static struct tm * | 
|---|
| 270 | ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *), | 
|---|
| 271 | long_int *t, struct tm *tp) | 
|---|
| 272 | { | 
|---|
| 273 | long_int t1 = (*t < mktime_min ? mktime_min | 
|---|
| 274 | : *t <= mktime_max ? *t : mktime_max); | 
|---|
| 275 | struct tm *r = convert_time (convert, t1, tp); | 
|---|
| 276 | if (r) | 
|---|
| 277 | { | 
|---|
| 278 | *t = t1; | 
|---|
| 279 | return r; | 
|---|
| 280 | } | 
|---|
| 281 | if (errno != EOVERFLOW) | 
|---|
| 282 | return NULL; | 
|---|
| 283 |  | 
|---|
| 284 | long_int bad = t1; | 
|---|
| 285 | long_int ok = 0; | 
|---|
| 286 | struct tm oktm; oktm.tm_sec = -1; | 
|---|
| 287 |  | 
|---|
| 288 | /* BAD is a known out-of-range value, and OK is a known in-range one. | 
|---|
| 289 | Use binary search to narrow the range between BAD and OK until | 
|---|
| 290 | they differ by 1.  */ | 
|---|
| 291 | while (true) | 
|---|
| 292 | { | 
|---|
| 293 | long_int mid = long_int_avg (ok, bad); | 
|---|
| 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; | 
|---|
| 302 | } | 
|---|
| 303 |  | 
|---|
| 304 | if (oktm.tm_sec < 0) | 
|---|
| 305 | return NULL; | 
|---|
| 306 | *t = ok; | 
|---|
| 307 | *tp = oktm; | 
|---|
| 308 | return tp; | 
|---|
| 309 | } | 
|---|
| 310 |  | 
|---|
| 311 |  | 
|---|
| 312 | /* Convert *TP to a __time64_t value, inverting | 
|---|
| 313 | the monotonic and mostly-unit-linear conversion function CONVERT. | 
|---|
| 314 | Use *OFFSET to keep track of a guess at the offset of the result, | 
|---|
| 315 | compared to what the result would be for UTC without leap seconds. | 
|---|
| 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. | 
|---|
| 319 | This function is external because it is used also by timegm.c.  */ | 
|---|
| 320 | __time64_t | 
|---|
| 321 | __mktime_internal (struct tm *tp, | 
|---|
| 322 | struct tm *(*convert) (const __time64_t *, struct tm *), | 
|---|
| 323 | mktime_offset_t *offset) | 
|---|
| 324 | { | 
|---|
| 325 | struct tm tm; | 
|---|
| 326 |  | 
|---|
| 327 | /* The maximum number of probes (calls to CONVERT) should be enough | 
|---|
| 328 | to handle any combinations of time zone rule changes, solar time, | 
|---|
| 329 | leap seconds, and oscillations around a spring-forward gap. | 
|---|
| 330 | POSIX.1 prohibits leap seconds, but some hosts have them anyway.  */ | 
|---|
| 331 | int remaining_probes = 6; | 
|---|
| 332 |  | 
|---|
| 333 | /* Time requested.  Copy it in case CONVERT modifies *TP; this can | 
|---|
| 334 | occur if TP is localtime's returned value and CONVERT is localtime.  */ | 
|---|
| 335 | int sec = tp->tm_sec; | 
|---|
| 336 | int min = tp->tm_min; | 
|---|
| 337 | int hour = tp->tm_hour; | 
|---|
| 338 | int mday = tp->tm_mday; | 
|---|
| 339 | int mon = tp->tm_mon; | 
|---|
| 340 | int year_requested = tp->tm_year; | 
|---|
| 341 | int isdst = tp->tm_isdst; | 
|---|
| 342 |  | 
|---|
| 343 | /* 1 if the previous probe was DST.  */ | 
|---|
| 344 | int dst2 = 0; | 
|---|
| 345 |  | 
|---|
| 346 | /* Ensure that mon is in range, and set year accordingly.  */ | 
|---|
| 347 | int mon_remainder = mon % 12; | 
|---|
| 348 | int negative_mon_remainder = mon_remainder < 0; | 
|---|
| 349 | int mon_years = mon / 12 - negative_mon_remainder; | 
|---|
| 350 | long_int lyear_requested = year_requested; | 
|---|
| 351 | long_int year = lyear_requested + mon_years; | 
|---|
| 352 |  | 
|---|
| 353 | /* The other values need not be in range: | 
|---|
| 354 | the remaining code handles overflows correctly.  */ | 
|---|
| 355 |  | 
|---|
| 356 | /* Calculate day of year from year, month, and day of month. | 
|---|
| 357 | The result need not be in range.  */ | 
|---|
| 358 | int mon_yday = ((__mon_yday[leapyear (year)] | 
|---|
| 359 | [mon_remainder + 12 * negative_mon_remainder]) | 
|---|
| 360 | - 1); | 
|---|
| 361 | long_int lmday = mday; | 
|---|
| 362 | long_int yday = mon_yday + lmday; | 
|---|
| 363 |  | 
|---|
| 364 | mktime_offset_t off = *offset; | 
|---|
| 365 | int negative_offset_guess; | 
|---|
| 366 |  | 
|---|
| 367 | int sec_requested = sec; | 
|---|
| 368 |  | 
|---|
| 369 | if (LEAP_SECONDS_POSSIBLE) | 
|---|
| 370 | { | 
|---|
| 371 | /* Handle out-of-range seconds specially, | 
|---|
| 372 | since ydhms_diff assumes every minute has 60 seconds.  */ | 
|---|
| 373 | if (sec < 0) | 
|---|
| 374 | sec = 0; | 
|---|
| 375 | if (59 < sec) | 
|---|
| 376 | sec = 59; | 
|---|
| 377 | } | 
|---|
| 378 |  | 
|---|
| 379 | /* Invert CONVERT by probing.  First assume the same offset as last | 
|---|
| 380 | time.  */ | 
|---|
| 381 |  | 
|---|
| 382 | INT_SUBTRACT_WRAPV (0, off, &negative_offset_guess); | 
|---|
| 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.  */ | 
|---|
| 389 |  | 
|---|
| 390 | while (true) | 
|---|
| 391 | { | 
|---|
| 392 | if (! ranged_convert (convert, &t, &tm)) | 
|---|
| 393 | return -1; | 
|---|
| 394 | long_int dt = tm_diff (year, yday, hour, min, sec, &tm); | 
|---|
| 395 | if (dt == 0) | 
|---|
| 396 | break; | 
|---|
| 397 |  | 
|---|
| 398 | if (t == t1 && t != t2 | 
|---|
| 399 | && (tm.tm_isdst < 0 | 
|---|
| 400 | || (isdst < 0 | 
|---|
| 401 | ? dst2 <= (tm.tm_isdst != 0) | 
|---|
| 402 | : (isdst != 0) != (tm.tm_isdst != 0)))) | 
|---|
| 403 | /* We can't possibly find a match, as we are oscillating | 
|---|
| 404 | between two values.  The requested time probably falls | 
|---|
| 405 | within a spring-forward gap of size DT.  Follow the common | 
|---|
| 406 | practice in this case, which is to return a time that is DT | 
|---|
| 407 | away from the requested time, preferring a time whose | 
|---|
| 408 | tm_isdst differs from the requested value.  (If no tm_isdst | 
|---|
| 409 | was requested and only one of the two values has a nonzero | 
|---|
| 410 | tm_isdst, prefer that value.)  In practice, this is more | 
|---|
| 411 | useful than returning -1.  */ | 
|---|
| 412 | goto offset_found; | 
|---|
| 413 |  | 
|---|
| 414 | remaining_probes--; | 
|---|
| 415 | if (remaining_probes == 0) | 
|---|
| 416 | { | 
|---|
| 417 | __set_errno (EOVERFLOW); | 
|---|
| 418 | return -1; | 
|---|
| 419 | } | 
|---|
| 420 |  | 
|---|
| 421 | t1 = t2, t2 = t, t += dt, dst2 = tm.tm_isdst != 0; | 
|---|
| 422 | } | 
|---|
| 423 |  | 
|---|
| 424 | /* We have a match.  Check whether tm.tm_isdst has the requested | 
|---|
| 425 | value, if any.  */ | 
|---|
| 426 | if (isdst_differ (isdst, tm.tm_isdst)) | 
|---|
| 427 | { | 
|---|
| 428 | /* tm.tm_isdst has the wrong value.  Look for a neighboring | 
|---|
| 429 | time with the right value, and use its UTC offset. | 
|---|
| 430 |  | 
|---|
| 431 | Heuristic: probe the adjacent timestamps in both directions, | 
|---|
| 432 | looking for the desired isdst.  This should work for all real | 
|---|
| 433 | time zone histories in the tz database.  */ | 
|---|
| 434 |  | 
|---|
| 435 | /* Distance between probes when looking for a DST boundary.  In | 
|---|
| 436 | tzdata2003a, the shortest period of DST is 601200 seconds | 
|---|
| 437 | (e.g., America/Recife starting 2000-10-08 01:00), and the | 
|---|
| 438 | shortest period of non-DST surrounded by DST is 694800 | 
|---|
| 439 | seconds (Africa/Tunis starting 1943-04-17 01:00).  Use the | 
|---|
| 440 | minimum of these two values, so we don't miss these short | 
|---|
| 441 | periods when probing.  */ | 
|---|
| 442 | int stride = 601200; | 
|---|
| 443 |  | 
|---|
| 444 | /* The longest period of DST in tzdata2003a is 536454000 seconds | 
|---|
| 445 | (e.g., America/Jujuy starting 1946-10-01 01:00).  The longest | 
|---|
| 446 | period of non-DST is much longer, but it makes no real sense | 
|---|
| 447 | to search for more than a year of non-DST, so use the DST | 
|---|
| 448 | max.  */ | 
|---|
| 449 | int duration_max = 536454000; | 
|---|
| 450 |  | 
|---|
| 451 | /* Search in both directions, so the maximum distance is half | 
|---|
| 452 | the duration; add the stride to avoid off-by-1 problems.  */ | 
|---|
| 453 | int delta_bound = duration_max / 2 + stride; | 
|---|
| 454 |  | 
|---|
| 455 | int delta, direction; | 
|---|
| 456 |  | 
|---|
| 457 | for (delta = stride; delta < delta_bound; delta += stride) | 
|---|
| 458 | for (direction = -1; direction <= 1; direction += 2) | 
|---|
| 459 | { | 
|---|
| 460 | long_int ot; | 
|---|
| 461 | if (! INT_ADD_WRAPV (t, delta * direction, &ot)) | 
|---|
| 462 | { | 
|---|
| 463 | struct tm otm; | 
|---|
| 464 | if (! ranged_convert (convert, &ot, &otm)) | 
|---|
| 465 | return -1; | 
|---|
| 466 | if (! isdst_differ (isdst, otm.tm_isdst)) | 
|---|
| 467 | { | 
|---|
| 468 | /* We found the desired tm_isdst. | 
|---|
| 469 | Extrapolate back to the desired time.  */ | 
|---|
| 470 | long_int gt = ot + tm_diff (year, yday, hour, min, sec, | 
|---|
| 471 | &otm); | 
|---|
| 472 | if (mktime_min <= gt && gt <= mktime_max) | 
|---|
| 473 | { | 
|---|
| 474 | if (convert_time (convert, gt, &tm)) | 
|---|
| 475 | { | 
|---|
| 476 | t = gt; | 
|---|
| 477 | goto offset_found; | 
|---|
| 478 | } | 
|---|
| 479 | if (errno != EOVERFLOW) | 
|---|
| 480 | return -1; | 
|---|
| 481 | } | 
|---|
| 482 | } | 
|---|
| 483 | } | 
|---|
| 484 | } | 
|---|
| 485 |  | 
|---|
| 486 | __set_errno (EOVERFLOW); | 
|---|
| 487 | return -1; | 
|---|
| 488 | } | 
|---|
| 489 |  | 
|---|
| 490 | offset_found: | 
|---|
| 491 | /* Set *OFFSET to the low-order bits of T - T0 - NEGATIVE_OFFSET_GUESS. | 
|---|
| 492 | This is just a heuristic to speed up the next mktime call, and | 
|---|
| 493 | correctness is unaffected if integer overflow occurs here.  */ | 
|---|
| 494 | INT_SUBTRACT_WRAPV (t, t0, offset); | 
|---|
| 495 | INT_SUBTRACT_WRAPV (*offset, negative_offset_guess, offset); | 
|---|
| 496 |  | 
|---|
| 497 | if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec) | 
|---|
| 498 | { | 
|---|
| 499 | /* Adjust time to reflect the tm_sec requested, not the normalized value. | 
|---|
| 500 | Also, repair any damage from a false match due to a leap second.  */ | 
|---|
| 501 | long_int sec_adjustment = sec == 0 && tm.tm_sec == 60; | 
|---|
| 502 | sec_adjustment -= sec; | 
|---|
| 503 | sec_adjustment += sec_requested; | 
|---|
| 504 | if (INT_ADD_WRAPV (t, sec_adjustment, &t) | 
|---|
| 505 | || ! (mktime_min <= t && t <= mktime_max)) | 
|---|
| 506 | { | 
|---|
| 507 | __set_errno (EOVERFLOW); | 
|---|
| 508 | return -1; | 
|---|
| 509 | } | 
|---|
| 510 | if (! convert_time (convert, t, &tm)) | 
|---|
| 511 | return -1; | 
|---|
| 512 | } | 
|---|
| 513 |  | 
|---|
| 514 | *tp = tm; | 
|---|
| 515 | return t; | 
|---|
| 516 | } | 
|---|
| 517 |  | 
|---|
| 518 | #endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL */ | 
|---|
| 519 |  | 
|---|
| 520 | #if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS | 
|---|
| 521 |  | 
|---|
| 522 | /* Convert *TP to a __time64_t value.  */ | 
|---|
| 523 | __time64_t | 
|---|
| 524 | __mktime64 (struct tm *tp) | 
|---|
| 525 | { | 
|---|
| 526 | /* POSIX.1 8.1.1 requires that whenever mktime() is called, the | 
|---|
| 527 | time zone names contained in the external variable 'tzname' shall | 
|---|
| 528 | be set as if the tzset() function had been called.  */ | 
|---|
| 529 | __tzset (); | 
|---|
| 530 |  | 
|---|
| 531 | # if defined _LIBC || NEED_MKTIME_WORKING | 
|---|
| 532 | static mktime_offset_t localtime_offset; | 
|---|
| 533 | return __mktime_internal (tp, __localtime64_r, &localtime_offset); | 
|---|
| 534 | # else | 
|---|
| 535 | #  undef mktime | 
|---|
| 536 | return mktime (tp); | 
|---|
| 537 | # endif | 
|---|
| 538 | } | 
|---|
| 539 | #endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */ | 
|---|
| 540 |  | 
|---|
| 541 | #if defined _LIBC && __TIMESIZE != 64 | 
|---|
| 542 |  | 
|---|
| 543 | libc_hidden_def (__mktime64) | 
|---|
| 544 |  | 
|---|
| 545 | time_t | 
|---|
| 546 | mktime (struct tm *tp) | 
|---|
| 547 | { | 
|---|
| 548 | struct tm tm = *tp; | 
|---|
| 549 | __time64_t t = __mktime64 (&tm); | 
|---|
| 550 | if (in_time_t_range (t)) | 
|---|
| 551 | { | 
|---|
| 552 | *tp = tm; | 
|---|
| 553 | return t; | 
|---|
| 554 | } | 
|---|
| 555 | else | 
|---|
| 556 | { | 
|---|
| 557 | __set_errno (EOVERFLOW); | 
|---|
| 558 | return -1; | 
|---|
| 559 | } | 
|---|
| 560 | } | 
|---|
| 561 |  | 
|---|
| 562 | #endif | 
|---|
| 563 |  | 
|---|
| 564 | weak_alias (mktime, timelocal) | 
|---|
| 565 | libc_hidden_def (mktime) | 
|---|
| 566 | libc_hidden_weak (timelocal) | 
|---|
| 567 |  | 
|---|