]> git.ipfire.org Git - thirdparty/glibc.git/blame - time/tzfile.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / time / tzfile.c
CommitLineData
04277e02 1/* Copyright (C) 1991-2019 Free Software Foundation, Inc.
860d3729 2 This file is part of the GNU C Library.
28f540f4 3
860d3729 4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
28f540f4 8
860d3729
UD
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 12 Lesser General Public License for more details.
28f540f4 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
28f540f4 17
a3e0e9ae
UD
18#include <assert.h>
19#include <limits.h>
28f540f4 20#include <stdio.h>
2706ee38 21#include <stdio_ext.h>
a3e0e9ae 22#include <stdlib.h>
28f540f4 23#include <string.h>
a3e0e9ae 24#include <time.h>
9d187dd4 25#include <unistd.h>
fe6cc2ae 26#include <sys/stat.h>
3b60b421 27#include <stdint.h>
28f540f4 28
14ea22e9 29#include <timezone/tzfile.h>
28f540f4 30
c4563d2d 31int __use_tzfile;
fe6cc2ae
UD
32static dev_t tzfile_dev;
33static ino64_t tzfile_ino;
8930fcf9 34static time_t tzfile_mtime;
28f540f4
RM
35
36struct ttinfo
37 {
38 long int offset; /* Seconds east of GMT. */
39 unsigned char isdst; /* Used to set tm_isdst. */
40 unsigned char idx; /* Index into `zone_names'. */
98fa1d6e
RM
41 unsigned char isstd; /* Transition times are in standard time. */
42 unsigned char isgmt; /* Transition times are in GMT. */
28f540f4
RM
43 };
44
45struct leap
46 {
d51f99ce 47 __time64_t transition; /* Time the transition takes effect. */
28f540f4
RM
48 long int change; /* Seconds of correction to apply. */
49 };
50
28f540f4 51static size_t num_transitions;
d51f99ce 52libc_freeres_ptr (static __time64_t *transitions);
c4563d2d 53static unsigned char *type_idxs;
28f540f4 54static size_t num_types;
c4563d2d
UD
55static struct ttinfo *types;
56static char *zone_names;
ff152e3f
UD
57static long int rule_stdoff;
58static long int rule_dstoff;
28f540f4 59static size_t num_leaps;
c4563d2d 60static struct leap *leaps;
fa76dde2 61static char *tzspec;
28f540f4 62
a2cafe30 63#include <endian.h>
ba9234d9 64#include <byteswap.h>
a2cafe30
RM
65
66/* Decode the four bytes at PTR as a signed integer in network byte order. */
67static inline int
9c7ff11a 68__attribute ((always_inline))
a2cafe30
RM
69decode (const void *ptr)
70{
11bf311e 71 if (BYTE_ORDER == BIG_ENDIAN && sizeof (int) == 4)
b20e47cb 72 return *(const int *) ptr;
11bf311e 73 if (sizeof (int) == 4)
ba9234d9 74 return bswap_32 (*(const int *) ptr);
b20e47cb 75
11bf311e
UD
76 const unsigned char *p = ptr;
77 int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0;
064737fb 78
11bf311e
UD
79 result = (result << 8) | *p++;
80 result = (result << 8) | *p++;
81 result = (result << 8) | *p++;
82 result = (result << 8) | *p++;
83
84 return result;
064737fb
UD
85}
86
11bf311e
UD
87
88static inline int64_t
89__attribute ((always_inline))
90decode64 (const void *ptr)
91{
92 if ((BYTE_ORDER == BIG_ENDIAN))
93 return *(const int64_t *) ptr;
94
95 return bswap_64 (*(const int64_t *) ptr);
96}
97
98
28f540f4 99void
c4563d2d 100__tzfile_read (const char *file, size_t extra, char **extrap)
28f540f4 101{
9d187dd4 102 static const char default_tzdir[] = TZDIR;
98fa1d6e 103 size_t num_isstd, num_isgmt;
2e09a79a 104 FILE *f;
28f540f4
RM
105 struct tzhead tzhead;
106 size_t chars;
2e09a79a 107 size_t i;
c4563d2d
UD
108 size_t total_size;
109 size_t types_idx;
110 size_t leaps_idx;
fe6cc2ae 111 int was_using_tzfile = __use_tzfile;
11bf311e 112 int trans_width = 4;
fa76dde2 113 size_t tzspec_len;
45c30c61 114 char *new = NULL;
11bf311e 115
d51f99ce
AA
116 _Static_assert (sizeof (__time64_t) == 8,
117 "__time64_t must be eight bytes");
28f540f4
RM
118
119 __use_tzfile = 0;
120
a3b58440
RM
121 if (file == NULL)
122 /* No user specification; use the site-wide default. */
28f540f4 123 file = TZDEFAULT;
a3b58440 124 else if (*file == '\0')
9a0a462c 125 /* User specified the empty string; use UTC with no leap seconds. */
640b76b7 126 goto ret_free_transitions;
1228ed5c
UD
127 else
128 {
129 /* We must not allow to read an arbitrary file in a setuid
130 program. So we fail for any file which is not in the
7434ccad
UD
131 directory hierachy starting at TZDIR
132 and which is not the system wide default TZDEFAULT. */
1228ed5c
UD
133 if (__libc_enable_secure
134 && ((*file == '/'
4cca6b86 135 && memcmp (file, TZDEFAULT, sizeof TZDEFAULT)
1228ed5c
UD
136 && memcmp (file, default_tzdir, sizeof (default_tzdir) - 1))
137 || strstr (file, "../") != NULL))
7434ccad
UD
138 /* This test is certainly a bit too restrictive but it should
139 catch all critical cases. */
640b76b7 140 goto ret_free_transitions;
1228ed5c 141 }
9d187dd4 142
28f540f4
RM
143 if (*file != '/')
144 {
5290baf0 145 const char *tzdir;
5290baf0 146
74955460 147 tzdir = getenv ("TZDIR");
5290baf0 148 if (tzdir == NULL || *tzdir == '\0')
45c30c61
OB
149 tzdir = default_tzdir;
150 if (__asprintf (&new, "%s/%s", tzdir, file) == -1)
151 goto ret_free_transitions;
28f540f4
RM
152 file = new;
153 }
154
250ecb48
UD
155 /* If we were already using tzfile, check whether the file changed. */
156 struct stat64 st;
157 if (was_using_tzfile
158 && stat64 (file, &st) == 0
159 && tzfile_ino == st.st_ino && tzfile_dev == st.st_dev
160 && tzfile_mtime == st.st_mtime)
45c30c61 161 goto done; /* Nothing to do. */
250ecb48 162
ee8449f7 163 /* Note the file is opened with cancellation in the I/O functions
82af0fa8
UD
164 disabled and if available FD_CLOEXEC set. */
165 f = fopen (file, "rce");
28f540f4 166 if (f == NULL)
640b76b7 167 goto ret_free_transitions;
28f540f4 168
250ecb48 169 /* Get information about the file we are actually using. */
5a6fa4d7 170 if (fstat64 (__fileno (f), &st) != 0)
dab9c348 171 goto lose;
fe6cc2ae 172
640b76b7
UD
173 free ((void *) transitions);
174 transitions = NULL;
175
8930fcf9 176 /* Remember the inode and device number and modification time. */
fe6cc2ae
UD
177 tzfile_dev = st.st_dev;
178 tzfile_ino = st.st_ino;
8930fcf9 179 tzfile_mtime = st.st_mtime;
fe6cc2ae 180
2706ee38
UD
181 /* No threads reading this stream. */
182 __fsetlocking (f, FSETLOCKING_BYCALLER);
183
11bf311e 184 read_again:
5a6fa4d7
JM
185 if (__builtin_expect (__fread_unlocked ((void *) &tzhead, sizeof (tzhead),
186 1, f) != 1, 0)
11bf311e 187 || memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic)) != 0)
28f540f4
RM
188 goto lose;
189
a2cafe30
RM
190 num_transitions = (size_t) decode (tzhead.tzh_timecnt);
191 num_types = (size_t) decode (tzhead.tzh_typecnt);
192 chars = (size_t) decode (tzhead.tzh_charcnt);
193 num_leaps = (size_t) decode (tzhead.tzh_leapcnt);
194 num_isstd = (size_t) decode (tzhead.tzh_ttisstdcnt);
195 num_isgmt = (size_t) decode (tzhead.tzh_ttisgmtcnt);
28f540f4 196
42261ad7
FW
197 if (__glibc_unlikely (num_isstd > num_types || num_isgmt > num_types))
198 goto lose;
199
fc79706a 200 if (trans_width == 4 && tzhead.tzh_version[0] != '\0')
11bf311e
UD
201 {
202 /* We use the 8-byte format. */
203 trans_width = 8;
204
205 /* Position the stream before the second header. */
206 size_t to_skip = (num_transitions * (4 + 1)
207 + num_types * 6
208 + chars
209 + num_leaps * 8
210 + num_isstd
211 + num_isgmt);
212 if (fseek (f, to_skip, SEEK_CUR) != 0)
213 goto lose;
214
215 goto read_again;
216 }
217
97ac2654
UD
218 if (__builtin_expect (num_transitions
219 > ((SIZE_MAX - (__alignof__ (struct ttinfo) - 1))
d51f99ce 220 / (sizeof (__time64_t) + 1)), 0))
97ac2654 221 goto lose;
d51f99ce 222 total_size = num_transitions * (sizeof (__time64_t) + 1);
c4563d2d
UD
223 total_size = ((total_size + __alignof__ (struct ttinfo) - 1)
224 & ~(__alignof__ (struct ttinfo) - 1));
225 types_idx = total_size;
97ac2654
UD
226 if (__builtin_expect (num_types
227 > (SIZE_MAX - total_size) / sizeof (struct ttinfo), 0))
228 goto lose;
229 total_size += num_types * sizeof (struct ttinfo);
a1ffb40e 230 if (__glibc_unlikely (chars > SIZE_MAX - total_size))
97ac2654
UD
231 goto lose;
232 total_size += chars;
233 if (__builtin_expect (__alignof__ (struct leap) - 1
234 > SIZE_MAX - total_size, 0))
235 goto lose;
c4563d2d
UD
236 total_size = ((total_size + __alignof__ (struct leap) - 1)
237 & ~(__alignof__ (struct leap) - 1));
238 leaps_idx = total_size;
97ac2654
UD
239 if (__builtin_expect (num_leaps
240 > (SIZE_MAX - total_size) / sizeof (struct leap), 0))
241 goto lose;
c4563d2d 242 total_size += num_leaps * sizeof (struct leap);
97ac2654 243 tzspec_len = 0;
fc79706a 244 if (trans_width == 8)
97ac2654 245 {
5a6fa4d7 246 off_t rem = st.st_size - __ftello (f);
97ac2654
UD
247 if (__builtin_expect (rem < 0
248 || (size_t) rem < (num_transitions * (8 + 1)
249 + num_types * 6
250 + chars), 0))
251 goto lose;
252 tzspec_len = (size_t) rem - (num_transitions * (8 + 1)
253 + num_types * 6
254 + chars);
255 if (__builtin_expect (num_leaps > SIZE_MAX / 12
256 || tzspec_len < num_leaps * 12, 0))
257 goto lose;
258 tzspec_len -= num_leaps * 12;
a1ffb40e 259 if (__glibc_unlikely (tzspec_len < num_isstd))
97ac2654
UD
260 goto lose;
261 tzspec_len -= num_isstd;
a1ffb40e 262 if (__glibc_unlikely (tzspec_len == 0 || tzspec_len - 1 < num_isgmt))
97ac2654
UD
263 goto lose;
264 tzspec_len -= num_isgmt + 1;
5cffc05e
L
265 if (__glibc_unlikely (tzspec_len == 0
266 || SIZE_MAX - total_size < tzspec_len))
97ac2654
UD
267 goto lose;
268 }
a1ffb40e 269 if (__glibc_unlikely (SIZE_MAX - total_size - tzspec_len < extra))
97ac2654 270 goto lose;
c4563d2d 271
11bf311e
UD
272 /* Allocate enough memory including the extra block requested by the
273 caller. */
fc79706a 274 transitions = malloc (total_size + tzspec_len + extra);
c4563d2d
UD
275 if (transitions == NULL)
276 goto lose;
277
278 type_idxs = (unsigned char *) transitions + (num_transitions
d51f99ce 279 * sizeof (__time64_t));
c4563d2d
UD
280 types = (struct ttinfo *) ((char *) transitions + types_idx);
281 zone_names = (char *) types + num_types * sizeof (struct ttinfo);
282 leaps = (struct leap *) ((char *) transitions + leaps_idx);
fc79706a 283 if (trans_width == 8)
69819d92 284 tzspec = (char *) leaps + num_leaps * sizeof (struct leap) + extra;
fa76dde2
UD
285 else
286 tzspec = NULL;
c4563d2d
UD
287 if (extra > 0)
288 *extrap = (char *) &leaps[num_leaps];
289
fc79706a 290 if (__builtin_expect (trans_width == 8, 1))
28f540f4 291 {
5a6fa4d7
JM
292 if (__builtin_expect (__fread_unlocked (transitions, trans_width + 1,
293 num_transitions, f)
11bf311e 294 != num_transitions, 0))
28f540f4
RM
295 goto lose;
296 }
c4563d2d 297 else
28f540f4 298 {
5a6fa4d7
JM
299 if (__builtin_expect (__fread_unlocked (transitions, 4,
300 num_transitions, f)
9c7ff11a 301 != num_transitions, 0)
5a6fa4d7
JM
302 || __builtin_expect (__fread_unlocked (type_idxs, 1, num_transitions,
303 f) != num_transitions, 0))
28f540f4
RM
304 goto lose;
305 }
306
5290baf0
UD
307 /* Check for bogus indices in the data file, so we can hereafter
308 safely use type_idxs[T] as indices into `types' and never crash. */
309 for (i = 0; i < num_transitions; ++i)
a1ffb40e 310 if (__glibc_unlikely (type_idxs[i] >= num_types))
5290baf0
UD
311 goto lose;
312
fc79706a 313 if (trans_width == 4)
a2cafe30
RM
314 {
315 /* Decode the transition times, stored as 4-byte integers in
fc79706a
FW
316 network (big-endian) byte order. We work from the end of the
317 array so as not to clobber the next element to be
318 processed. */
a2cafe30 319 i = num_transitions;
b20e47cb 320 while (i-- > 0)
a3e0e9ae 321 transitions[i] = decode ((char *) transitions + i * 4);
a2cafe30 322 }
fc79706a 323 else if (BYTE_ORDER != BIG_ENDIAN)
11bf311e
UD
324 {
325 /* Decode the transition times, stored as 8-byte integers in
326 network (big-endian) byte order. */
327 for (i = 0; i < num_transitions; ++i)
328 transitions[i] = decode64 ((char *) transitions + i * 8);
329 }
28f540f4
RM
330
331 for (i = 0; i < num_types; ++i)
332 {
333 unsigned char x[4];
c4563d2d 334 int c;
5a6fa4d7
JM
335 if (__builtin_expect (__fread_unlocked (x, 1,
336 sizeof (x), f) != sizeof (x),
9c7ff11a 337 0))
28f540f4 338 goto lose;
30ac923d 339 c = __getc_unlocked (f);
a1ffb40e 340 if (__glibc_unlikely ((unsigned int) c > 1u))
8b7fb588 341 goto lose;
c4563d2d 342 types[i].isdst = c;
30ac923d 343 c = __getc_unlocked (f);
a1ffb40e 344 if (__glibc_unlikely ((size_t) c > chars))
9c7ff11a 345 /* Bogus index in data file. */
5290baf0 346 goto lose;
c4563d2d 347 types[i].idx = c;
a2cafe30 348 types[i].offset = (long int) decode (x);
28f540f4
RM
349 }
350
5a6fa4d7 351 if (__glibc_unlikely (__fread_unlocked (zone_names, 1, chars, f) != chars))
28f540f4
RM
352 goto lose;
353
354 for (i = 0; i < num_leaps; ++i)
355 {
11bf311e 356 unsigned char x[8];
5a6fa4d7 357 if (__builtin_expect (__fread_unlocked (x, 1, trans_width, f)
11bf311e 358 != trans_width, 0))
28f540f4 359 goto lose;
fc79706a
FW
360 if (trans_width == 4)
361 leaps[i].transition = decode (x);
11bf311e 362 else
fc79706a 363 leaps[i].transition = decode64 (x);
11bf311e 364
5a6fa4d7 365 if (__glibc_unlikely (__fread_unlocked (x, 1, 4, f) != 4))
28f540f4 366 goto lose;
a2cafe30 367 leaps[i].change = (long int) decode (x);
28f540f4
RM
368 }
369
370 for (i = 0; i < num_isstd; ++i)
371 {
30ac923d 372 int c = __getc_unlocked (f);
a1ffb40e 373 if (__glibc_unlikely (c == EOF))
28f540f4
RM
374 goto lose;
375 types[i].isstd = c != 0;
376 }
377 while (i < num_types)
378 types[i++].isstd = 0;
379
98fa1d6e
RM
380 for (i = 0; i < num_isgmt; ++i)
381 {
30ac923d 382 int c = __getc_unlocked (f);
a1ffb40e 383 if (__glibc_unlikely (c == EOF))
98fa1d6e
RM
384 goto lose;
385 types[i].isgmt = c != 0;
386 }
387 while (i < num_types)
388 types[i++].isgmt = 0;
389
fa76dde2 390 /* Read the POSIX TZ-style information if possible. */
fc79706a 391 if (tzspec != NULL)
fa76dde2
UD
392 {
393 /* Skip over the newline first. */
30ac923d 394 if (__getc_unlocked (f) != '\n'
5a6fa4d7 395 || (__fread_unlocked (tzspec, 1, tzspec_len - 1, f)
c6d381d3 396 != tzspec_len - 1))
fa76dde2
UD
397 tzspec = NULL;
398 else
399 tzspec[tzspec_len - 1] = '\0';
400 }
11bf311e 401
7a7c2c24
AS
402 /* Don't use an empty TZ string. */
403 if (tzspec != NULL && tzspec[0] == '\0')
404 tzspec = NULL;
405
860d3729
UD
406 fclose (f);
407
a3e0e9ae
UD
408 /* First "register" all timezone names. */
409 for (i = 0; i < num_types; ++i)
e4e4fde5
PE
410 if (__tzstring (&zone_names[types[i].idx]) == NULL)
411 goto ret_free_transitions;
a3e0e9ae 412
ff152e3f
UD
413 /* Find the standard and daylight time offsets used by the rule file.
414 We choose the offsets in the types of each flavor that are
415 transitioned to earliest in time. */
a3e0e9ae 416 __tzname[0] = NULL;
ff152e3f 417 __tzname[1] = NULL;
a3e0e9ae
UD
418 for (i = num_transitions; i > 0; )
419 {
420 int type = type_idxs[--i];
421 int dst = types[type].isdst;
a3e0e9ae
UD
422
423 if (__tzname[dst] == NULL)
424 {
d3345073
UD
425 int idx = types[type].idx;
426
a3e0e9ae
UD
427 __tzname[dst] = __tzstring (&zone_names[idx]);
428
429 if (__tzname[1 - dst] != NULL)
430 break;
431 }
432 }
433 if (__tzname[0] == NULL)
434 {
435 /* This should only happen if there are no transition rules.
436 In this case there should be only one single type. */
437 assert (num_types == 1);
438 __tzname[0] = __tzstring (zone_names);
439 }
ff152e3f
UD
440 if (__tzname[1] == NULL)
441 __tzname[1] = __tzname[0];
28f540f4 442
90865aa8 443 if (num_transitions == 0)
0155a773 444 /* Use the first rule (which should also be the only one). */
90865aa8
UD
445 rule_stdoff = rule_dstoff = types[0].offset;
446 else
ff152e3f 447 {
d16e36e0 448 int stdoff_set = 0, dstoff_set = 0;
90865aa8 449 rule_stdoff = rule_dstoff = 0;
d3345073
UD
450 i = num_transitions - 1;
451 do
90865aa8 452 {
d16e36e0
AS
453 if (!stdoff_set && !types[type_idxs[i]].isdst)
454 {
455 stdoff_set = 1;
456 rule_stdoff = types[type_idxs[i]].offset;
457 }
d3345073 458 else if (!dstoff_set && types[type_idxs[i]].isdst)
d16e36e0
AS
459 {
460 dstoff_set = 1;
461 rule_dstoff = types[type_idxs[i]].offset;
462 }
463 if (stdoff_set && dstoff_set)
90865aa8
UD
464 break;
465 }
d3345073
UD
466 while (i-- > 0);
467
d16e36e0
AS
468 if (!dstoff_set)
469 rule_dstoff = rule_stdoff;
ff152e3f
UD
470 }
471
472 __daylight = rule_stdoff != rule_dstoff;
473 __timezone = -rule_stdoff;
474
45c30c61 475 done:
28f540f4 476 __use_tzfile = 1;
45c30c61 477 free (new);
28f540f4
RM
478 return;
479
ba9234d9
UD
480 lose:
481 fclose (f);
640b76b7 482 ret_free_transitions:
45c30c61 483 free (new);
640b76b7
UD
484 free ((void *) transitions);
485 transitions = NULL;
28f540f4
RM
486}
487\f
98fa1d6e
RM
488/* The user specified a hand-made timezone, but not its DST rules.
489 We will use the names and offsets from the user, and the rules
490 from the TZDEFRULES file. */
491
28f540f4 492void
cd6ede75
UD
493__tzfile_default (const char *std, const char *dst,
494 long int stdoff, long int dstoff)
28f540f4 495{
c4563d2d
UD
496 size_t stdlen = strlen (std) + 1;
497 size_t dstlen = strlen (dst) + 1;
498 size_t i;
98fa1d6e 499 int isdst;
c4563d2d 500 char *cp;
28f540f4 501
c4563d2d 502 __tzfile_read (TZDEFRULES, stdlen + dstlen, &cp);
28f540f4
RM
503 if (!__use_tzfile)
504 return;
505
506 if (num_types < 2)
507 {
508 __use_tzfile = 0;
509 return;
510 }
511
c4563d2d
UD
512 /* Ignore the zone names read from the file and use the given ones
513 instead. */
514 __mempcpy (__mempcpy (cp, std, stdlen), dst, dstlen);
515 zone_names = cp;
28f540f4 516
88455219
UD
517 /* Now there are only two zones, regardless of what the file contained. */
518 num_types = 2;
519
98fa1d6e
RM
520 /* Now correct the transition times for the user-specified standard and
521 daylight offsets from GMT. */
522 isdst = 0;
98fa1d6e
RM
523 for (i = 0; i < num_transitions; ++i)
524 {
525 struct ttinfo *trans_type = &types[type_idxs[i]];
526
527 /* We will use only types 0 (standard) and 1 (daylight).
528 Fix up this transition to point to whichever matches
529 the flavor of its original type. */
530 type_idxs[i] = trans_type->isdst;
531
532 if (trans_type->isgmt)
533 /* The transition time is in GMT. No correction to apply. */ ;
534 else if (isdst && !trans_type->isstd)
535 /* The type says this transition is in "local wall clock time", and
536 wall clock time as of the previous transition was DST. Correct
537 for the difference between the rule's DST offset and the user's
538 DST offset. */
539 transitions[i] += dstoff - rule_dstoff;
540 else
541 /* This transition is in "local wall clock time", and wall clock
542 time as of this iteration is non-DST. Correct for the
543 difference between the rule's standard offset and the user's
544 standard offset. */
545 transitions[i] += stdoff - rule_stdoff;
546
547 /* The DST state of "local wall clock time" for the next iteration is
548 as specified by this transition. */
549 isdst = trans_type->isdst;
550 }
551
4c326621
UD
552 /* Now that we adjusted the transitions to the requested offsets,
553 reset the rule_stdoff and rule_dstoff values appropriately. They
554 are used elsewhere. */
555 rule_stdoff = stdoff;
556 rule_dstoff = dstoff;
557
98fa1d6e
RM
558 /* Reset types 0 and 1 to describe the user's settings. */
559 types[0].idx = 0;
560 types[0].offset = stdoff;
561 types[0].isdst = 0;
562 types[1].idx = stdlen;
563 types[1].offset = dstoff;
564 types[1].isdst = 1;
28f540f4 565
5290baf0 566 /* Reset the zone names to point to the user's names. */
cd6ede75
UD
567 __tzname[0] = (char *) std;
568 __tzname[1] = (char *) dst;
5290baf0 569
90865aa8
UD
570 /* Set the timezone. */
571 __timezone = -types[0].offset;
572
c83196b0
AS
573 /* Invalidate the tzfile attribute cache to force rereading
574 TZDEFRULES the next time it is used. */
575 tzfile_dev = 0;
576 tzfile_ino = 0;
577 tzfile_mtime = 0;
28f540f4
RM
578}
579\f
fa76dde2 580void
d51f99ce 581__tzfile_compute (__time64_t timer, int use_localtime,
fa76dde2
UD
582 long int *leap_correct, int *leap_hit,
583 struct tm *tp)
28f540f4 584{
2e09a79a 585 size_t i;
89dc9d4c 586
fa76dde2 587 if (use_localtime)
28f540f4 588 {
fa76dde2
UD
589 __tzname[0] = NULL;
590 __tzname[1] = NULL;
591
a1ffb40e 592 if (__glibc_unlikely (num_transitions == 0 || timer < transitions[0]))
89dc9d4c 593 {
fa76dde2
UD
594 /* TIMER is before any transition (or there are no transitions).
595 Choose the first non-DST type
596 (or the first if they're all DST types). */
597 i = 0;
598 while (i < num_types && types[i].isdst)
599 {
600 if (__tzname[1] == NULL)
601 __tzname[1] = __tzstring (&zone_names[types[i].idx]);
89dc9d4c 602
fa76dde2
UD
603 ++i;
604 }
89dc9d4c 605
fa76dde2
UD
606 if (i == num_types)
607 i = 0;
608 __tzname[0] = __tzstring (&zone_names[types[i].idx]);
609 if (__tzname[1] == NULL)
610 {
611 size_t j = i;
612 while (j < num_types)
613 if (types[j].isdst)
614 {
615 __tzname[1] = __tzstring (&zone_names[types[j].idx]);
616 break;
617 }
618 else
619 ++j;
620 }
621 }
a1ffb40e 622 else if (__glibc_unlikely (timer >= transitions[num_transitions - 1]))
89dc9d4c 623 {
a1ffb40e 624 if (__glibc_unlikely (tzspec == NULL))
fa76dde2
UD
625 {
626 use_last:
e2cceb5a 627 i = num_transitions;
fa76dde2
UD
628 goto found;
629 }
630
631 /* Parse the POSIX TZ-style string. */
632 __tzset_parse_tz (tzspec);
633
634 /* Convert to broken down structure. If this fails do not
635 use the string. */
72b8692d
AA
636 if (__glibc_unlikely (! __offtime (timer, 0, tp)))
637 goto use_last;
638
639 /* Use the rules from the TZ string to compute the change. */
fa76dde2
UD
640 __tz_compute (timer, tp, 1);
641
c6d381d3
UD
642 /* If tzspec comes from posixrules loaded by __tzfile_default,
643 override the STD and DST zone names with the ones user
644 requested in TZ envvar. */
a1ffb40e 645 if (__glibc_unlikely (zone_names == (char *) &leaps[num_leaps]))
c6d381d3
UD
646 {
647 assert (num_types == 2);
648 __tzname[0] = __tzstring (zone_names);
649 __tzname[1] = __tzstring (&zone_names[strlen (zone_names) + 1]);
650 }
651
29143408 652 goto leap;
89dc9d4c 653 }
fa76dde2 654 else
13252678 655 {
fa76dde2
UD
656 /* Find the first transition after TIMER, and
657 then pick the type of the transition before it. */
658 size_t lo = 0;
659 size_t hi = num_transitions - 1;
fc79706a
FW
660 /* Assume that DST is changing twice a year and guess
661 initial search spot from it. Half of a gregorian year
662 has on average 365.2425 * 86400 / 2 = 15778476 seconds.
663 The value i can be truncated if size_t is smaller than
d51f99ce 664 __time64_t, but this is harmless because it is just
fc79706a 665 a guess. */
fa76dde2
UD
666 i = (transitions[num_transitions - 1] - timer) / 15778476;
667 if (i < num_transitions)
13252678 668 {
fa76dde2
UD
669 i = num_transitions - 1 - i;
670 if (timer < transitions[i])
13252678 671 {
fa76dde2
UD
672 if (i < 10 || timer >= transitions[i - 10])
673 {
674 /* Linear search. */
675 while (timer < transitions[i - 1])
676 --i;
677 goto found;
678 }
679 hi = i - 10;
13252678 680 }
fa76dde2 681 else
13252678 682 {
fa76dde2
UD
683 if (i + 10 >= num_transitions || timer < transitions[i + 10])
684 {
685 /* Linear search. */
686 while (timer >= transitions[i])
687 ++i;
688 goto found;
689 }
690 lo = i + 10;
13252678 691 }
13252678 692 }
13252678 693
fa76dde2
UD
694 /* Binary search. */
695 /* assert (timer >= transitions[lo] && timer < transitions[hi]); */
696 while (lo + 1 < hi)
697 {
698 i = (lo + hi) / 2;
699 if (timer < transitions[i])
700 hi = i;
701 else
702 lo = i;
703 }
704 i = hi;
89dc9d4c 705
fa76dde2 706 found:
e2cceb5a
UD
707 /* assert (timer >= transitions[i - 1]
708 && (i == num_transitions || timer < transitions[i])); */
fa76dde2
UD
709 __tzname[types[type_idxs[i - 1]].isdst]
710 = __tzstring (&zone_names[types[type_idxs[i - 1]].idx]);
711 size_t j = i;
712 while (j < num_transitions)
89dc9d4c 713 {
fa76dde2
UD
714 int type = type_idxs[j];
715 int dst = types[type].isdst;
716 int idx = types[type].idx;
89dc9d4c 717
fa76dde2
UD
718 if (__tzname[dst] == NULL)
719 {
720 __tzname[dst] = __tzstring (&zone_names[idx]);
89dc9d4c 721
fa76dde2
UD
722 if (__tzname[1 - dst] != NULL)
723 break;
724 }
89dc9d4c 725
fa76dde2
UD
726 ++j;
727 }
28f540f4 728
a1ffb40e 729 if (__glibc_unlikely (__tzname[0] == NULL))
c6d381d3
UD
730 __tzname[0] = __tzname[1];
731
fa76dde2
UD
732 i = type_idxs[i - 1];
733 }
860d3729 734
fa76dde2 735 struct ttinfo *info = &types[i];
ff152e3f
UD
736 __daylight = rule_stdoff != rule_dstoff;
737 __timezone = -rule_stdoff;
a3e0e9ae 738
a3e0e9ae
UD
739 if (__tzname[0] == NULL)
740 {
741 /* This should only happen if there are no transition rules.
742 In this case there should be only one single type. */
743 assert (num_types == 1);
744 __tzname[0] = __tzstring (zone_names);
745 }
ff152e3f
UD
746 if (__tzname[1] == NULL)
747 /* There is no daylight saving time. */
748 __tzname[1] = __tzname[0];
a709dd43 749 tp->tm_isdst = info->isdst;
89dc9d4c
UD
750 assert (strcmp (&zone_names[info->idx], __tzname[tp->tm_isdst]) == 0);
751 tp->tm_zone = __tzname[tp->tm_isdst];
a709dd43 752 tp->tm_gmtoff = info->offset;
9a0a462c 753 }
28f540f4 754
29143408 755 leap:
28f540f4
RM
756 *leap_correct = 0L;
757 *leap_hit = 0;
758
759 /* Find the last leap second correction transition time before TIMER. */
760 i = num_leaps;
761 do
762 if (i-- == 0)
38e68573 763 return;
28f540f4
RM
764 while (timer < leaps[i].transition);
765
766 /* Apply its correction. */
767 *leap_correct = leaps[i].change;
768
769 if (timer == leaps[i].transition && /* Exactly at the transition time. */
770 ((i == 0 && leaps[i].change > 0) ||
771 leaps[i].change > leaps[i - 1].change))
772 {
773 *leap_hit = 1;
ba9234d9
UD
774 while (i > 0
775 && leaps[i].transition == leaps[i - 1].transition + 1
776 && leaps[i].change == leaps[i - 1].change + 1)
28f540f4
RM
777 {
778 ++*leap_hit;
779 --i;
780 }
781 }
28f540f4 782}