]> git.ipfire.org Git - thirdparty/glibc.git/blame - time/tzfile.c
Fix tzfile low-memory assertion failure
[thirdparty/glibc.git] / time / tzfile.c
CommitLineData
688903eb 1/* Copyright (C) 1991-2018 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 {
fc79706a 47 internal_time_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;
fc79706a 52libc_freeres_ptr (static internal_time_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
fc79706a
FW
116 _Static_assert (sizeof (internal_time_t) == 8,
117 "internal_time_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)
fe6cc2ae
UD
171 {
172 fclose (f);
640b76b7 173 goto ret_free_transitions;
fe6cc2ae 174 }
fe6cc2ae 175
640b76b7
UD
176 free ((void *) transitions);
177 transitions = NULL;
178
8930fcf9 179 /* Remember the inode and device number and modification time. */
fe6cc2ae
UD
180 tzfile_dev = st.st_dev;
181 tzfile_ino = st.st_ino;
8930fcf9 182 tzfile_mtime = st.st_mtime;
fe6cc2ae 183
2706ee38
UD
184 /* No threads reading this stream. */
185 __fsetlocking (f, FSETLOCKING_BYCALLER);
186
11bf311e 187 read_again:
5a6fa4d7
JM
188 if (__builtin_expect (__fread_unlocked ((void *) &tzhead, sizeof (tzhead),
189 1, f) != 1, 0)
11bf311e 190 || memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic)) != 0)
28f540f4
RM
191 goto lose;
192
a2cafe30
RM
193 num_transitions = (size_t) decode (tzhead.tzh_timecnt);
194 num_types = (size_t) decode (tzhead.tzh_typecnt);
195 chars = (size_t) decode (tzhead.tzh_charcnt);
196 num_leaps = (size_t) decode (tzhead.tzh_leapcnt);
197 num_isstd = (size_t) decode (tzhead.tzh_ttisstdcnt);
198 num_isgmt = (size_t) decode (tzhead.tzh_ttisgmtcnt);
28f540f4 199
42261ad7
FW
200 if (__glibc_unlikely (num_isstd > num_types || num_isgmt > num_types))
201 goto lose;
202
fc79706a 203 if (trans_width == 4 && tzhead.tzh_version[0] != '\0')
11bf311e
UD
204 {
205 /* We use the 8-byte format. */
206 trans_width = 8;
207
208 /* Position the stream before the second header. */
209 size_t to_skip = (num_transitions * (4 + 1)
210 + num_types * 6
211 + chars
212 + num_leaps * 8
213 + num_isstd
214 + num_isgmt);
215 if (fseek (f, to_skip, SEEK_CUR) != 0)
216 goto lose;
217
218 goto read_again;
219 }
220
97ac2654
UD
221 if (__builtin_expect (num_transitions
222 > ((SIZE_MAX - (__alignof__ (struct ttinfo) - 1))
fc79706a 223 / (sizeof (internal_time_t) + 1)), 0))
97ac2654 224 goto lose;
fc79706a 225 total_size = num_transitions * (sizeof (internal_time_t) + 1);
c4563d2d
UD
226 total_size = ((total_size + __alignof__ (struct ttinfo) - 1)
227 & ~(__alignof__ (struct ttinfo) - 1));
228 types_idx = total_size;
97ac2654
UD
229 if (__builtin_expect (num_types
230 > (SIZE_MAX - total_size) / sizeof (struct ttinfo), 0))
231 goto lose;
232 total_size += num_types * sizeof (struct ttinfo);
a1ffb40e 233 if (__glibc_unlikely (chars > SIZE_MAX - total_size))
97ac2654
UD
234 goto lose;
235 total_size += chars;
236 if (__builtin_expect (__alignof__ (struct leap) - 1
237 > SIZE_MAX - total_size, 0))
238 goto lose;
c4563d2d
UD
239 total_size = ((total_size + __alignof__ (struct leap) - 1)
240 & ~(__alignof__ (struct leap) - 1));
241 leaps_idx = total_size;
97ac2654
UD
242 if (__builtin_expect (num_leaps
243 > (SIZE_MAX - total_size) / sizeof (struct leap), 0))
244 goto lose;
c4563d2d 245 total_size += num_leaps * sizeof (struct leap);
97ac2654 246 tzspec_len = 0;
fc79706a 247 if (trans_width == 8)
97ac2654 248 {
5a6fa4d7 249 off_t rem = st.st_size - __ftello (f);
97ac2654
UD
250 if (__builtin_expect (rem < 0
251 || (size_t) rem < (num_transitions * (8 + 1)
252 + num_types * 6
253 + chars), 0))
254 goto lose;
255 tzspec_len = (size_t) rem - (num_transitions * (8 + 1)
256 + num_types * 6
257 + chars);
258 if (__builtin_expect (num_leaps > SIZE_MAX / 12
259 || tzspec_len < num_leaps * 12, 0))
260 goto lose;
261 tzspec_len -= num_leaps * 12;
a1ffb40e 262 if (__glibc_unlikely (tzspec_len < num_isstd))
97ac2654
UD
263 goto lose;
264 tzspec_len -= num_isstd;
a1ffb40e 265 if (__glibc_unlikely (tzspec_len == 0 || tzspec_len - 1 < num_isgmt))
97ac2654
UD
266 goto lose;
267 tzspec_len -= num_isgmt + 1;
5cffc05e
L
268 if (__glibc_unlikely (tzspec_len == 0
269 || SIZE_MAX - total_size < tzspec_len))
97ac2654
UD
270 goto lose;
271 }
a1ffb40e 272 if (__glibc_unlikely (SIZE_MAX - total_size - tzspec_len < extra))
97ac2654 273 goto lose;
c4563d2d 274
11bf311e
UD
275 /* Allocate enough memory including the extra block requested by the
276 caller. */
fc79706a 277 transitions = malloc (total_size + tzspec_len + extra);
c4563d2d
UD
278 if (transitions == NULL)
279 goto lose;
280
281 type_idxs = (unsigned char *) transitions + (num_transitions
fc79706a 282 * sizeof (internal_time_t));
c4563d2d
UD
283 types = (struct ttinfo *) ((char *) transitions + types_idx);
284 zone_names = (char *) types + num_types * sizeof (struct ttinfo);
285 leaps = (struct leap *) ((char *) transitions + leaps_idx);
fc79706a 286 if (trans_width == 8)
69819d92 287 tzspec = (char *) leaps + num_leaps * sizeof (struct leap) + extra;
fa76dde2
UD
288 else
289 tzspec = NULL;
c4563d2d
UD
290 if (extra > 0)
291 *extrap = (char *) &leaps[num_leaps];
292
fc79706a 293 if (__builtin_expect (trans_width == 8, 1))
28f540f4 294 {
5a6fa4d7
JM
295 if (__builtin_expect (__fread_unlocked (transitions, trans_width + 1,
296 num_transitions, f)
11bf311e 297 != num_transitions, 0))
28f540f4
RM
298 goto lose;
299 }
c4563d2d 300 else
28f540f4 301 {
5a6fa4d7
JM
302 if (__builtin_expect (__fread_unlocked (transitions, 4,
303 num_transitions, f)
9c7ff11a 304 != num_transitions, 0)
5a6fa4d7
JM
305 || __builtin_expect (__fread_unlocked (type_idxs, 1, num_transitions,
306 f) != num_transitions, 0))
28f540f4
RM
307 goto lose;
308 }
309
5290baf0
UD
310 /* Check for bogus indices in the data file, so we can hereafter
311 safely use type_idxs[T] as indices into `types' and never crash. */
312 for (i = 0; i < num_transitions; ++i)
a1ffb40e 313 if (__glibc_unlikely (type_idxs[i] >= num_types))
5290baf0
UD
314 goto lose;
315
fc79706a 316 if (trans_width == 4)
a2cafe30
RM
317 {
318 /* Decode the transition times, stored as 4-byte integers in
fc79706a
FW
319 network (big-endian) byte order. We work from the end of the
320 array so as not to clobber the next element to be
321 processed. */
a2cafe30 322 i = num_transitions;
b20e47cb 323 while (i-- > 0)
a3e0e9ae 324 transitions[i] = decode ((char *) transitions + i * 4);
a2cafe30 325 }
fc79706a 326 else if (BYTE_ORDER != BIG_ENDIAN)
11bf311e
UD
327 {
328 /* Decode the transition times, stored as 8-byte integers in
329 network (big-endian) byte order. */
330 for (i = 0; i < num_transitions; ++i)
331 transitions[i] = decode64 ((char *) transitions + i * 8);
332 }
28f540f4
RM
333
334 for (i = 0; i < num_types; ++i)
335 {
336 unsigned char x[4];
c4563d2d 337 int c;
5a6fa4d7
JM
338 if (__builtin_expect (__fread_unlocked (x, 1,
339 sizeof (x), f) != sizeof (x),
9c7ff11a 340 0))
28f540f4 341 goto lose;
30ac923d 342 c = __getc_unlocked (f);
a1ffb40e 343 if (__glibc_unlikely ((unsigned int) c > 1u))
8b7fb588 344 goto lose;
c4563d2d 345 types[i].isdst = c;
30ac923d 346 c = __getc_unlocked (f);
a1ffb40e 347 if (__glibc_unlikely ((size_t) c > chars))
9c7ff11a 348 /* Bogus index in data file. */
5290baf0 349 goto lose;
c4563d2d 350 types[i].idx = c;
a2cafe30 351 types[i].offset = (long int) decode (x);
28f540f4
RM
352 }
353
5a6fa4d7 354 if (__glibc_unlikely (__fread_unlocked (zone_names, 1, chars, f) != chars))
28f540f4
RM
355 goto lose;
356
357 for (i = 0; i < num_leaps; ++i)
358 {
11bf311e 359 unsigned char x[8];
5a6fa4d7 360 if (__builtin_expect (__fread_unlocked (x, 1, trans_width, f)
11bf311e 361 != trans_width, 0))
28f540f4 362 goto lose;
fc79706a
FW
363 if (trans_width == 4)
364 leaps[i].transition = decode (x);
11bf311e 365 else
fc79706a 366 leaps[i].transition = decode64 (x);
11bf311e 367
5a6fa4d7 368 if (__glibc_unlikely (__fread_unlocked (x, 1, 4, f) != 4))
28f540f4 369 goto lose;
a2cafe30 370 leaps[i].change = (long int) decode (x);
28f540f4
RM
371 }
372
373 for (i = 0; i < num_isstd; ++i)
374 {
30ac923d 375 int c = __getc_unlocked (f);
a1ffb40e 376 if (__glibc_unlikely (c == EOF))
28f540f4
RM
377 goto lose;
378 types[i].isstd = c != 0;
379 }
380 while (i < num_types)
381 types[i++].isstd = 0;
382
98fa1d6e
RM
383 for (i = 0; i < num_isgmt; ++i)
384 {
30ac923d 385 int c = __getc_unlocked (f);
a1ffb40e 386 if (__glibc_unlikely (c == EOF))
98fa1d6e
RM
387 goto lose;
388 types[i].isgmt = c != 0;
389 }
390 while (i < num_types)
391 types[i++].isgmt = 0;
392
fa76dde2 393 /* Read the POSIX TZ-style information if possible. */
fc79706a 394 if (tzspec != NULL)
fa76dde2
UD
395 {
396 /* Skip over the newline first. */
30ac923d 397 if (__getc_unlocked (f) != '\n'
5a6fa4d7 398 || (__fread_unlocked (tzspec, 1, tzspec_len - 1, f)
c6d381d3 399 != tzspec_len - 1))
fa76dde2
UD
400 tzspec = NULL;
401 else
402 tzspec[tzspec_len - 1] = '\0';
403 }
11bf311e 404
7a7c2c24
AS
405 /* Don't use an empty TZ string. */
406 if (tzspec != NULL && tzspec[0] == '\0')
407 tzspec = NULL;
408
860d3729
UD
409 fclose (f);
410
a3e0e9ae
UD
411 /* First "register" all timezone names. */
412 for (i = 0; i < num_types; ++i)
e4e4fde5
PE
413 if (__tzstring (&zone_names[types[i].idx]) == NULL)
414 goto ret_free_transitions;
a3e0e9ae 415
ff152e3f
UD
416 /* Find the standard and daylight time offsets used by the rule file.
417 We choose the offsets in the types of each flavor that are
418 transitioned to earliest in time. */
a3e0e9ae 419 __tzname[0] = NULL;
ff152e3f 420 __tzname[1] = NULL;
a3e0e9ae
UD
421 for (i = num_transitions; i > 0; )
422 {
423 int type = type_idxs[--i];
424 int dst = types[type].isdst;
a3e0e9ae
UD
425
426 if (__tzname[dst] == NULL)
427 {
d3345073
UD
428 int idx = types[type].idx;
429
a3e0e9ae
UD
430 __tzname[dst] = __tzstring (&zone_names[idx]);
431
432 if (__tzname[1 - dst] != NULL)
433 break;
434 }
435 }
436 if (__tzname[0] == NULL)
437 {
438 /* This should only happen if there are no transition rules.
439 In this case there should be only one single type. */
440 assert (num_types == 1);
441 __tzname[0] = __tzstring (zone_names);
442 }
ff152e3f
UD
443 if (__tzname[1] == NULL)
444 __tzname[1] = __tzname[0];
28f540f4 445
90865aa8 446 if (num_transitions == 0)
0155a773 447 /* Use the first rule (which should also be the only one). */
90865aa8
UD
448 rule_stdoff = rule_dstoff = types[0].offset;
449 else
ff152e3f 450 {
d16e36e0 451 int stdoff_set = 0, dstoff_set = 0;
90865aa8 452 rule_stdoff = rule_dstoff = 0;
d3345073
UD
453 i = num_transitions - 1;
454 do
90865aa8 455 {
d16e36e0
AS
456 if (!stdoff_set && !types[type_idxs[i]].isdst)
457 {
458 stdoff_set = 1;
459 rule_stdoff = types[type_idxs[i]].offset;
460 }
d3345073 461 else if (!dstoff_set && types[type_idxs[i]].isdst)
d16e36e0
AS
462 {
463 dstoff_set = 1;
464 rule_dstoff = types[type_idxs[i]].offset;
465 }
466 if (stdoff_set && dstoff_set)
90865aa8
UD
467 break;
468 }
d3345073
UD
469 while (i-- > 0);
470
d16e36e0
AS
471 if (!dstoff_set)
472 rule_dstoff = rule_stdoff;
ff152e3f
UD
473 }
474
475 __daylight = rule_stdoff != rule_dstoff;
476 __timezone = -rule_stdoff;
477
45c30c61 478 done:
28f540f4 479 __use_tzfile = 1;
45c30c61 480 free (new);
28f540f4
RM
481 return;
482
ba9234d9
UD
483 lose:
484 fclose (f);
640b76b7 485 ret_free_transitions:
45c30c61 486 free (new);
640b76b7
UD
487 free ((void *) transitions);
488 transitions = NULL;
28f540f4
RM
489}
490\f
98fa1d6e
RM
491/* The user specified a hand-made timezone, but not its DST rules.
492 We will use the names and offsets from the user, and the rules
493 from the TZDEFRULES file. */
494
28f540f4 495void
cd6ede75
UD
496__tzfile_default (const char *std, const char *dst,
497 long int stdoff, long int dstoff)
28f540f4 498{
c4563d2d
UD
499 size_t stdlen = strlen (std) + 1;
500 size_t dstlen = strlen (dst) + 1;
501 size_t i;
98fa1d6e 502 int isdst;
c4563d2d 503 char *cp;
28f540f4 504
c4563d2d 505 __tzfile_read (TZDEFRULES, stdlen + dstlen, &cp);
28f540f4
RM
506 if (!__use_tzfile)
507 return;
508
509 if (num_types < 2)
510 {
511 __use_tzfile = 0;
512 return;
513 }
514
c4563d2d
UD
515 /* Ignore the zone names read from the file and use the given ones
516 instead. */
517 __mempcpy (__mempcpy (cp, std, stdlen), dst, dstlen);
518 zone_names = cp;
28f540f4 519
88455219
UD
520 /* Now there are only two zones, regardless of what the file contained. */
521 num_types = 2;
522
98fa1d6e
RM
523 /* Now correct the transition times for the user-specified standard and
524 daylight offsets from GMT. */
525 isdst = 0;
98fa1d6e
RM
526 for (i = 0; i < num_transitions; ++i)
527 {
528 struct ttinfo *trans_type = &types[type_idxs[i]];
529
530 /* We will use only types 0 (standard) and 1 (daylight).
531 Fix up this transition to point to whichever matches
532 the flavor of its original type. */
533 type_idxs[i] = trans_type->isdst;
534
535 if (trans_type->isgmt)
536 /* The transition time is in GMT. No correction to apply. */ ;
537 else if (isdst && !trans_type->isstd)
538 /* The type says this transition is in "local wall clock time", and
539 wall clock time as of the previous transition was DST. Correct
540 for the difference between the rule's DST offset and the user's
541 DST offset. */
542 transitions[i] += dstoff - rule_dstoff;
543 else
544 /* This transition is in "local wall clock time", and wall clock
545 time as of this iteration is non-DST. Correct for the
546 difference between the rule's standard offset and the user's
547 standard offset. */
548 transitions[i] += stdoff - rule_stdoff;
549
550 /* The DST state of "local wall clock time" for the next iteration is
551 as specified by this transition. */
552 isdst = trans_type->isdst;
553 }
554
4c326621
UD
555 /* Now that we adjusted the transitions to the requested offsets,
556 reset the rule_stdoff and rule_dstoff values appropriately. They
557 are used elsewhere. */
558 rule_stdoff = stdoff;
559 rule_dstoff = dstoff;
560
98fa1d6e
RM
561 /* Reset types 0 and 1 to describe the user's settings. */
562 types[0].idx = 0;
563 types[0].offset = stdoff;
564 types[0].isdst = 0;
565 types[1].idx = stdlen;
566 types[1].offset = dstoff;
567 types[1].isdst = 1;
28f540f4 568
5290baf0 569 /* Reset the zone names to point to the user's names. */
cd6ede75
UD
570 __tzname[0] = (char *) std;
571 __tzname[1] = (char *) dst;
5290baf0 572
90865aa8
UD
573 /* Set the timezone. */
574 __timezone = -types[0].offset;
575
c83196b0
AS
576 /* Invalidate the tzfile attribute cache to force rereading
577 TZDEFRULES the next time it is used. */
578 tzfile_dev = 0;
579 tzfile_ino = 0;
580 tzfile_mtime = 0;
28f540f4
RM
581}
582\f
fa76dde2 583void
fc79706a 584__tzfile_compute (internal_time_t timer, int use_localtime,
fa76dde2
UD
585 long int *leap_correct, int *leap_hit,
586 struct tm *tp)
28f540f4 587{
2e09a79a 588 size_t i;
89dc9d4c 589
fa76dde2 590 if (use_localtime)
28f540f4 591 {
fa76dde2
UD
592 __tzname[0] = NULL;
593 __tzname[1] = NULL;
594
a1ffb40e 595 if (__glibc_unlikely (num_transitions == 0 || timer < transitions[0]))
89dc9d4c 596 {
fa76dde2
UD
597 /* TIMER is before any transition (or there are no transitions).
598 Choose the first non-DST type
599 (or the first if they're all DST types). */
600 i = 0;
601 while (i < num_types && types[i].isdst)
602 {
603 if (__tzname[1] == NULL)
604 __tzname[1] = __tzstring (&zone_names[types[i].idx]);
89dc9d4c 605
fa76dde2
UD
606 ++i;
607 }
89dc9d4c 608
fa76dde2
UD
609 if (i == num_types)
610 i = 0;
611 __tzname[0] = __tzstring (&zone_names[types[i].idx]);
612 if (__tzname[1] == NULL)
613 {
614 size_t j = i;
615 while (j < num_types)
616 if (types[j].isdst)
617 {
618 __tzname[1] = __tzstring (&zone_names[types[j].idx]);
619 break;
620 }
621 else
622 ++j;
623 }
624 }
a1ffb40e 625 else if (__glibc_unlikely (timer >= transitions[num_transitions - 1]))
89dc9d4c 626 {
a1ffb40e 627 if (__glibc_unlikely (tzspec == NULL))
fa76dde2
UD
628 {
629 use_last:
e2cceb5a 630 i = num_transitions;
fa76dde2
UD
631 goto found;
632 }
633
634 /* Parse the POSIX TZ-style string. */
635 __tzset_parse_tz (tzspec);
636
637 /* Convert to broken down structure. If this fails do not
638 use the string. */
fc79706a
FW
639 {
640 time_t truncated = timer;
641 if (__glibc_unlikely (truncated != timer
642 || ! __offtime (&truncated, 0, tp)))
643 goto use_last;
644 }
645
646 /* Use the rules from the TZ string to compute the change.
647 timer fits into time_t due to the truncation check
648 above. */
fa76dde2
UD
649 __tz_compute (timer, tp, 1);
650
c6d381d3
UD
651 /* If tzspec comes from posixrules loaded by __tzfile_default,
652 override the STD and DST zone names with the ones user
653 requested in TZ envvar. */
a1ffb40e 654 if (__glibc_unlikely (zone_names == (char *) &leaps[num_leaps]))
c6d381d3
UD
655 {
656 assert (num_types == 2);
657 __tzname[0] = __tzstring (zone_names);
658 __tzname[1] = __tzstring (&zone_names[strlen (zone_names) + 1]);
659 }
660
29143408 661 goto leap;
89dc9d4c 662 }
fa76dde2 663 else
13252678 664 {
fa76dde2
UD
665 /* Find the first transition after TIMER, and
666 then pick the type of the transition before it. */
667 size_t lo = 0;
668 size_t hi = num_transitions - 1;
fc79706a
FW
669 /* Assume that DST is changing twice a year and guess
670 initial search spot from it. Half of a gregorian year
671 has on average 365.2425 * 86400 / 2 = 15778476 seconds.
672 The value i can be truncated if size_t is smaller than
673 internal_time_t, but this is harmless because it is just
674 a guess. */
fa76dde2
UD
675 i = (transitions[num_transitions - 1] - timer) / 15778476;
676 if (i < num_transitions)
13252678 677 {
fa76dde2
UD
678 i = num_transitions - 1 - i;
679 if (timer < transitions[i])
13252678 680 {
fa76dde2
UD
681 if (i < 10 || timer >= transitions[i - 10])
682 {
683 /* Linear search. */
684 while (timer < transitions[i - 1])
685 --i;
686 goto found;
687 }
688 hi = i - 10;
13252678 689 }
fa76dde2 690 else
13252678 691 {
fa76dde2
UD
692 if (i + 10 >= num_transitions || timer < transitions[i + 10])
693 {
694 /* Linear search. */
695 while (timer >= transitions[i])
696 ++i;
697 goto found;
698 }
699 lo = i + 10;
13252678 700 }
13252678 701 }
13252678 702
fa76dde2
UD
703 /* Binary search. */
704 /* assert (timer >= transitions[lo] && timer < transitions[hi]); */
705 while (lo + 1 < hi)
706 {
707 i = (lo + hi) / 2;
708 if (timer < transitions[i])
709 hi = i;
710 else
711 lo = i;
712 }
713 i = hi;
89dc9d4c 714
fa76dde2 715 found:
e2cceb5a
UD
716 /* assert (timer >= transitions[i - 1]
717 && (i == num_transitions || timer < transitions[i])); */
fa76dde2
UD
718 __tzname[types[type_idxs[i - 1]].isdst]
719 = __tzstring (&zone_names[types[type_idxs[i - 1]].idx]);
720 size_t j = i;
721 while (j < num_transitions)
89dc9d4c 722 {
fa76dde2
UD
723 int type = type_idxs[j];
724 int dst = types[type].isdst;
725 int idx = types[type].idx;
89dc9d4c 726
fa76dde2
UD
727 if (__tzname[dst] == NULL)
728 {
729 __tzname[dst] = __tzstring (&zone_names[idx]);
89dc9d4c 730
fa76dde2
UD
731 if (__tzname[1 - dst] != NULL)
732 break;
733 }
89dc9d4c 734
fa76dde2
UD
735 ++j;
736 }
28f540f4 737
a1ffb40e 738 if (__glibc_unlikely (__tzname[0] == NULL))
c6d381d3
UD
739 __tzname[0] = __tzname[1];
740
fa76dde2
UD
741 i = type_idxs[i - 1];
742 }
860d3729 743
fa76dde2 744 struct ttinfo *info = &types[i];
ff152e3f
UD
745 __daylight = rule_stdoff != rule_dstoff;
746 __timezone = -rule_stdoff;
a3e0e9ae 747
a3e0e9ae
UD
748 if (__tzname[0] == NULL)
749 {
750 /* This should only happen if there are no transition rules.
751 In this case there should be only one single type. */
752 assert (num_types == 1);
753 __tzname[0] = __tzstring (zone_names);
754 }
ff152e3f
UD
755 if (__tzname[1] == NULL)
756 /* There is no daylight saving time. */
757 __tzname[1] = __tzname[0];
a709dd43 758 tp->tm_isdst = info->isdst;
89dc9d4c
UD
759 assert (strcmp (&zone_names[info->idx], __tzname[tp->tm_isdst]) == 0);
760 tp->tm_zone = __tzname[tp->tm_isdst];
a709dd43 761 tp->tm_gmtoff = info->offset;
9a0a462c 762 }
28f540f4 763
29143408 764 leap:
28f540f4
RM
765 *leap_correct = 0L;
766 *leap_hit = 0;
767
768 /* Find the last leap second correction transition time before TIMER. */
769 i = num_leaps;
770 do
771 if (i-- == 0)
38e68573 772 return;
28f540f4
RM
773 while (timer < leaps[i].transition);
774
775 /* Apply its correction. */
776 *leap_correct = leaps[i].change;
777
778 if (timer == leaps[i].transition && /* Exactly at the transition time. */
779 ((i == 0 && leaps[i].change > 0) ||
780 leaps[i].change > leaps[i - 1].change))
781 {
782 *leap_hit = 1;
ba9234d9
UD
783 while (i > 0
784 && leaps[i].transition == leaps[i - 1].transition + 1
785 && leaps[i].change == leaps[i - 1].change + 1)
28f540f4
RM
786 {
787 ++*leap_hit;
788 --i;
789 }
790 }
28f540f4 791}