1/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
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.
8
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
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
17
18#include <assert.h>
19#include <limits.h>
20#include <stdio.h>
21#include <stdio_ext.h>
22#include <stdlib.h>
23#include <string.h>
24#include <time.h>
25#include <unistd.h>
26#include <sys/stat.h>
27#include <stdint.h>
28
29#include <timezone/tzfile.h>
30
31int __use_tzfile;
32static dev_t tzfile_dev;
33static ino64_t tzfile_ino;
34static time_t tzfile_mtime;
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'. */
41 unsigned char isstd; /* Transition times are in standard time. */
42 unsigned char isgmt; /* Transition times are in GMT. */
43 };
44
45struct leap
46 {
47 internal_time_t transition; /* Time the transition takes effect. */
48 long int change; /* Seconds of correction to apply. */
49 };
50
51static size_t num_transitions;
52libc_freeres_ptr (static internal_time_t *transitions);
53static unsigned char *type_idxs;
54static size_t num_types;
55static struct ttinfo *types;
56static char *zone_names;
57static long int rule_stdoff;
58static long int rule_dstoff;
59static size_t num_leaps;
60static struct leap *leaps;
61static char *tzspec;
62
63#include <endian.h>
64#include <byteswap.h>
65
66/* Decode the four bytes at PTR as a signed integer in network byte order. */
67static inline int
68__attribute ((always_inline))
69decode (const void *ptr)
70{
71 if (BYTE_ORDER == BIG_ENDIAN && sizeof (int) == 4)
72 return *(const int *) ptr;
73 if (sizeof (int) == 4)
74 return bswap_32 (*(const int *) ptr);
75
76 const unsigned char *p = ptr;
77 int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0;
78
79 result = (result << 8) | *p++;
80 result = (result << 8) | *p++;
81 result = (result << 8) | *p++;
82 result = (result << 8) | *p++;
83
84 return result;
85}
86
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
99void
100__tzfile_read (const char *file, size_t extra, char **extrap)
101{
102 static const char default_tzdir[] = TZDIR;
103 size_t num_isstd, num_isgmt;
104 FILE *f;
105 struct tzhead tzhead;
106 size_t chars;
107 size_t i;
108 size_t total_size;
109 size_t types_idx;
110 size_t leaps_idx;
111 int was_using_tzfile = __use_tzfile;
112 int trans_width = 4;
113 size_t tzspec_len;
114 char *new = NULL;
115
116 _Static_assert (sizeof (internal_time_t) == 8,
117 "internal_time_t must be eight bytes");
118
119 __use_tzfile = 0;
120
121 if (file == NULL)
122 /* No user specification; use the site-wide default. */
123 file = TZDEFAULT;
124 else if (*file == '\0')
125 /* User specified the empty string; use UTC with no leap seconds. */
126 goto ret_free_transitions;
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
131 directory hierachy starting at TZDIR
132 and which is not the system wide default TZDEFAULT. */
133 if (__libc_enable_secure
134 && ((*file == '/'
135 && memcmp (file, TZDEFAULT, sizeof TZDEFAULT)
136 && memcmp (file, default_tzdir, sizeof (default_tzdir) - 1))
137 || strstr (file, "../") != NULL))
138 /* This test is certainly a bit too restrictive but it should
139 catch all critical cases. */
140 goto ret_free_transitions;
141 }
142
143 if (*file != '/')
144 {
145 const char *tzdir;
146
147 tzdir = getenv ("TZDIR");
148 if (tzdir == NULL || *tzdir == '\0')
149 tzdir = default_tzdir;
150 if (__asprintf (&new, "%s/%s", tzdir, file) == -1)
151 goto ret_free_transitions;
152 file = new;
153 }
154
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)
161 goto done; /* Nothing to do. */
162
163 /* Note the file is opened with cancellation in the I/O functions
164 disabled and if available FD_CLOEXEC set. */
165 f = fopen (file, "rce");
166 if (f == NULL)
167 goto ret_free_transitions;
168
169 /* Get information about the file we are actually using. */
170 if (fstat64 (__fileno (f), &st) != 0)
171 {
172 fclose (f);
173 goto ret_free_transitions;
174 }
175
176 free ((void *) transitions);
177 transitions = NULL;
178
179 /* Remember the inode and device number and modification time. */
180 tzfile_dev = st.st_dev;
181 tzfile_ino = st.st_ino;
182 tzfile_mtime = st.st_mtime;
183
184 /* No threads reading this stream. */
185 __fsetlocking (f, FSETLOCKING_BYCALLER);
186
187 read_again:
188 if (__builtin_expect (__fread_unlocked ((void *) &tzhead, sizeof (tzhead),
189 1, f) != 1, 0)
190 || memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic)) != 0)
191 goto lose;
192
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);
199
200 if (__glibc_unlikely (num_isstd > num_types || num_isgmt > num_types))
201 goto lose;
202
203 if (trans_width == 4 && tzhead.tzh_version[0] != '\0')
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
221 if (__builtin_expect (num_transitions
222 > ((SIZE_MAX - (__alignof__ (struct ttinfo) - 1))
223 / (sizeof (internal_time_t) + 1)), 0))
224 goto lose;
225 total_size = num_transitions * (sizeof (internal_time_t) + 1);
226 total_size = ((total_size + __alignof__ (struct ttinfo) - 1)
227 & ~(__alignof__ (struct ttinfo) - 1));
228 types_idx = total_size;
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);
233 if (__glibc_unlikely (chars > SIZE_MAX - total_size))
234 goto lose;
235 total_size += chars;
236 if (__builtin_expect (__alignof__ (struct leap) - 1
237 > SIZE_MAX - total_size, 0))
238 goto lose;
239 total_size = ((total_size + __alignof__ (struct leap) - 1)
240 & ~(__alignof__ (struct leap) - 1));
241 leaps_idx = total_size;
242 if (__builtin_expect (num_leaps
243 > (SIZE_MAX - total_size) / sizeof (struct leap), 0))
244 goto lose;
245 total_size += num_leaps * sizeof (struct leap);
246 tzspec_len = 0;
247 if (trans_width == 8)
248 {
249 off_t rem = st.st_size - __ftello (f);
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;
262 if (__glibc_unlikely (tzspec_len < num_isstd))
263 goto lose;
264 tzspec_len -= num_isstd;
265 if (__glibc_unlikely (tzspec_len == 0 || tzspec_len - 1 < num_isgmt))
266 goto lose;
267 tzspec_len -= num_isgmt + 1;
268 if (__glibc_unlikely (tzspec_len == 0
269 || SIZE_MAX - total_size < tzspec_len))
270 goto lose;
271 }
272 if (__glibc_unlikely (SIZE_MAX - total_size - tzspec_len < extra))
273 goto lose;
274
275 /* Allocate enough memory including the extra block requested by the
276 caller. */
277 transitions = malloc (total_size + tzspec_len + extra);
278 if (transitions == NULL)
279 goto lose;
280
281 type_idxs = (unsigned char *) transitions + (num_transitions
282 * sizeof (internal_time_t));
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);
286 if (trans_width == 8)
287 tzspec = (char *) leaps + num_leaps * sizeof (struct leap) + extra;
288 else
289 tzspec = NULL;
290 if (extra > 0)
291 *extrap = (char *) &leaps[num_leaps];
292
293 if (__builtin_expect (trans_width == 8, 1))
294 {
295 if (__builtin_expect (__fread_unlocked (transitions, trans_width + 1,
296 num_transitions, f)
297 != num_transitions, 0))
298 goto lose;
299 }
300 else
301 {
302 if (__builtin_expect (__fread_unlocked (transitions, 4,
303 num_transitions, f)
304 != num_transitions, 0)
305 || __builtin_expect (__fread_unlocked (type_idxs, 1, num_transitions,
306 f) != num_transitions, 0))
307 goto lose;
308 }
309
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)
313 if (__glibc_unlikely (type_idxs[i] >= num_types))
314 goto lose;
315
316 if (trans_width == 4)
317 {
318 /* Decode the transition times, stored as 4-byte integers in
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. */
322 i = num_transitions;
323 while (i-- > 0)
324 transitions[i] = decode ((char *) transitions + i * 4);
325 }
326 else if (BYTE_ORDER != BIG_ENDIAN)
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 }
333
334 for (i = 0; i < num_types; ++i)
335 {
336 unsigned char x[4];
337 int c;
338 if (__builtin_expect (__fread_unlocked (x, 1,
339 sizeof (x), f) != sizeof (x),
340 0))
341 goto lose;
342 c = __getc_unlocked (f);
343 if (__glibc_unlikely ((unsigned int) c > 1u))
344 goto lose;
345 types[i].isdst = c;
346 c = __getc_unlocked (f);
347 if (__glibc_unlikely ((size_t) c > chars))
348 /* Bogus index in data file. */
349 goto lose;
350 types[i].idx = c;
351 types[i].offset = (long int) decode (x);
352 }
353
354 if (__glibc_unlikely (__fread_unlocked (zone_names, 1, chars, f) != chars))
355 goto lose;
356
357 for (i = 0; i < num_leaps; ++i)
358 {
359 unsigned char x[8];
360 if (__builtin_expect (__fread_unlocked (x, 1, trans_width, f)
361 != trans_width, 0))
362 goto lose;
363 if (trans_width == 4)
364 leaps[i].transition = decode (x);
365 else
366 leaps[i].transition = decode64 (x);
367
368 if (__glibc_unlikely (__fread_unlocked (x, 1, 4, f) != 4))
369 goto lose;
370 leaps[i].change = (long int) decode (x);
371 }
372
373 for (i = 0; i < num_isstd; ++i)
374 {
375 int c = __getc_unlocked (f);
376 if (__glibc_unlikely (c == EOF))
377 goto lose;
378 types[i].isstd = c != 0;
379 }
380 while (i < num_types)
381 types[i++].isstd = 0;
382
383 for (i = 0; i < num_isgmt; ++i)
384 {
385 int c = __getc_unlocked (f);
386 if (__glibc_unlikely (c == EOF))
387 goto lose;
388 types[i].isgmt = c != 0;
389 }
390 while (i < num_types)
391 types[i++].isgmt = 0;
392
393 /* Read the POSIX TZ-style information if possible. */
394 if (tzspec != NULL)
395 {
396 /* Skip over the newline first. */
397 if (__getc_unlocked (f) != '\n'
398 || (__fread_unlocked (tzspec, 1, tzspec_len - 1, f)
399 != tzspec_len - 1))
400 tzspec = NULL;
401 else
402 tzspec[tzspec_len - 1] = '\0';
403 }
404
405 /* Don't use an empty TZ string. */
406 if (tzspec != NULL && tzspec[0] == '\0')
407 tzspec = NULL;
408
409 fclose (f);
410
411 /* First "register" all timezone names. */
412 for (i = 0; i < num_types; ++i)
413 if (__tzstring (&zone_names[types[i].idx]) == NULL)
414 goto ret_free_transitions;
415
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. */
419 __tzname[0] = NULL;
420 __tzname[1] = NULL;
421 for (i = num_transitions; i > 0; )
422 {
423 int type = type_idxs[--i];
424 int dst = types[type].isdst;
425
426 if (__tzname[dst] == NULL)
427 {
428 int idx = types[type].idx;
429
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 }
443 if (__tzname[1] == NULL)
444 __tzname[1] = __tzname[0];
445
446 if (num_transitions == 0)
447 /* Use the first rule (which should also be the only one). */
448 rule_stdoff = rule_dstoff = types[0].offset;
449 else
450 {
451 int stdoff_set = 0, dstoff_set = 0;
452 rule_stdoff = rule_dstoff = 0;
453 i = num_transitions - 1;
454 do
455 {
456 if (!stdoff_set && !types[type_idxs[i]].isdst)
457 {
458 stdoff_set = 1;
459 rule_stdoff = types[type_idxs[i]].offset;
460 }
461 else if (!dstoff_set && types[type_idxs[i]].isdst)
462 {
463 dstoff_set = 1;
464 rule_dstoff = types[type_idxs[i]].offset;
465 }
466 if (stdoff_set && dstoff_set)
467 break;
468 }
469 while (i-- > 0);
470
471 if (!dstoff_set)
472 rule_dstoff = rule_stdoff;
473 }
474
475 __daylight = rule_stdoff != rule_dstoff;
476 __timezone = -rule_stdoff;
477
478 done:
479 __use_tzfile = 1;
480 free (new);
481 return;
482
483 lose:
484 fclose (f);
485 ret_free_transitions:
486 free (new);
487 free ((void *) transitions);
488 transitions = NULL;
489}
490
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
495void
496__tzfile_default (const char *std, const char *dst,
497 long int stdoff, long int dstoff)
498{
499 size_t stdlen = strlen (std) + 1;
500 size_t dstlen = strlen (dst) + 1;
501 size_t i;
502 int isdst;
503 char *cp;
504
505 __tzfile_read (TZDEFRULES, stdlen + dstlen, &cp);
506 if (!__use_tzfile)
507 return;
508
509 if (num_types < 2)
510 {
511 __use_tzfile = 0;
512 return;
513 }
514
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;
519
520 /* Now there are only two zones, regardless of what the file contained. */
521 num_types = 2;
522
523 /* Now correct the transition times for the user-specified standard and
524 daylight offsets from GMT. */
525 isdst = 0;
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
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
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;
568
569 /* Reset the zone names to point to the user's names. */
570 __tzname[0] = (char *) std;
571 __tzname[1] = (char *) dst;
572
573 /* Set the timezone. */
574 __timezone = -types[0].offset;
575
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;
581}
582
583void
584__tzfile_compute (internal_time_t timer, int use_localtime,
585 long int *leap_correct, int *leap_hit,
586 struct tm *tp)
587{
588 size_t i;
589
590 if (use_localtime)
591 {
592 __tzname[0] = NULL;
593 __tzname[1] = NULL;
594
595 if (__glibc_unlikely (num_transitions == 0 || timer < transitions[0]))
596 {
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]);
605
606 ++i;
607 }
608
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 }
625 else if (__glibc_unlikely (timer >= transitions[num_transitions - 1]))
626 {
627 if (__glibc_unlikely (tzspec == NULL))
628 {
629 use_last:
630 i = num_transitions;
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. */
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. */
649 __tz_compute (timer, tp, 1);
650
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. */
654 if (__glibc_unlikely (zone_names == (char *) &leaps[num_leaps]))
655 {
656 assert (num_types == 2);
657 __tzname[0] = __tzstring (zone_names);
658 __tzname[1] = __tzstring (&zone_names[strlen (zone_names) + 1]);
659 }
660
661 goto leap;
662 }
663 else
664 {
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;
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. */
675 i = (transitions[num_transitions - 1] - timer) / 15778476;
676 if (i < num_transitions)
677 {
678 i = num_transitions - 1 - i;
679 if (timer < transitions[i])
680 {
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;
689 }
690 else
691 {
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;
700 }
701 }
702
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;
714
715 found:
716 /* assert (timer >= transitions[i - 1]
717 && (i == num_transitions || timer < transitions[i])); */
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)
722 {
723 int type = type_idxs[j];
724 int dst = types[type].isdst;
725 int idx = types[type].idx;
726
727 if (__tzname[dst] == NULL)
728 {
729 __tzname[dst] = __tzstring (&zone_names[idx]);
730
731 if (__tzname[1 - dst] != NULL)
732 break;
733 }
734
735 ++j;
736 }
737
738 if (__glibc_unlikely (__tzname[0] == NULL))
739 __tzname[0] = __tzname[1];
740
741 i = type_idxs[i - 1];
742 }
743
744 struct ttinfo *info = &types[i];
745 __daylight = rule_stdoff != rule_dstoff;
746 __timezone = -rule_stdoff;
747
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 }
755 if (__tzname[1] == NULL)
756 /* There is no daylight saving time. */
757 __tzname[1] = __tzname[0];
758 tp->tm_isdst = info->isdst;
759 assert (strcmp (&zone_names[info->idx], __tzname[tp->tm_isdst]) == 0);
760 tp->tm_zone = __tzname[tp->tm_isdst];
761 tp->tm_gmtoff = info->offset;
762 }
763
764 leap:
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)
772 return;
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;
783 while (i > 0
784 && leaps[i].transition == leaps[i - 1].transition + 1
785 && leaps[i].change == leaps[i - 1].change + 1)
786 {
787 ++*leap_hit;
788 --i;
789 }
790 }
791}
792