1 /* Copyright (C) 1991-2018 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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.
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/>. */
21 #include <stdio_ext.h>
29 #include <timezone/tzfile.h>
32 static dev_t tzfile_dev
;
33 static ino64_t tzfile_ino
;
34 static time_t tzfile_mtime
;
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. */
47 internal_time_t transition
; /* Time the transition takes effect. */
48 long int change
; /* Seconds of correction to apply. */
51 static size_t num_transitions
;
52 libc_freeres_ptr (static internal_time_t
*transitions
);
53 static unsigned char *type_idxs
;
54 static size_t num_types
;
55 static struct ttinfo
*types
;
56 static char *zone_names
;
57 static long int rule_stdoff
;
58 static long int rule_dstoff
;
59 static size_t num_leaps
;
60 static struct leap
*leaps
;
66 /* Decode the four bytes at PTR as a signed integer in network byte order. */
68 __attribute ((always_inline
))
69 decode (const void *ptr
)
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
);
76 const unsigned char *p
= ptr
;
77 int result
= *p
& (1 << (CHAR_BIT
- 1)) ? ~0 : 0;
79 result
= (result
<< 8) | *p
++;
80 result
= (result
<< 8) | *p
++;
81 result
= (result
<< 8) | *p
++;
82 result
= (result
<< 8) | *p
++;
89 __attribute ((always_inline
))
90 decode64 (const void *ptr
)
92 if ((BYTE_ORDER
== BIG_ENDIAN
))
93 return *(const int64_t *) ptr
;
95 return bswap_64 (*(const int64_t *) ptr
);
100 __tzfile_read (const char *file
, size_t extra
, char **extrap
)
102 static const char default_tzdir
[] = TZDIR
;
103 size_t num_isstd
, num_isgmt
;
105 struct tzhead tzhead
;
111 int was_using_tzfile
= __use_tzfile
;
116 _Static_assert (sizeof (internal_time_t
) == 8,
117 "internal_time_t must be eight bytes");
122 /* No user specification; use the site-wide default. */
124 else if (*file
== '\0')
125 /* User specified the empty string; use UTC with no leap seconds. */
126 goto ret_free_transitions
;
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
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
;
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
;
155 /* If we were already using tzfile, check whether the file changed. */
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. */
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");
167 goto ret_free_transitions
;
169 /* Get information about the file we are actually using. */
170 if (fstat64 (__fileno (f
), &st
) != 0)
173 goto ret_free_transitions
;
176 free ((void *) transitions
);
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
;
184 /* No threads reading this stream. */
185 __fsetlocking (f
, FSETLOCKING_BYCALLER
);
188 if (__builtin_expect (__fread_unlocked ((void *) &tzhead
, sizeof (tzhead
),
190 || memcmp (tzhead
.tzh_magic
, TZ_MAGIC
, sizeof (tzhead
.tzh_magic
)) != 0)
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
);
200 if (__glibc_unlikely (num_isstd
> num_types
|| num_isgmt
> num_types
))
203 if (trans_width
== 4 && tzhead
.tzh_version
[0] != '\0')
205 /* We use the 8-byte format. */
208 /* Position the stream before the second header. */
209 size_t to_skip
= (num_transitions
* (4 + 1)
215 if (fseek (f
, to_skip
, SEEK_CUR
) != 0)
221 if (__builtin_expect (num_transitions
222 > ((SIZE_MAX
- (__alignof__ (struct ttinfo
) - 1))
223 / (sizeof (internal_time_t
) + 1)), 0))
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))
232 total_size
+= num_types
* sizeof (struct ttinfo
);
233 if (__glibc_unlikely (chars
> SIZE_MAX
- total_size
))
236 if (__builtin_expect (__alignof__ (struct leap
) - 1
237 > SIZE_MAX
- total_size
, 0))
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))
245 total_size
+= num_leaps
* sizeof (struct leap
);
247 if (trans_width
== 8)
249 off_t rem
= st
.st_size
- __ftello (f
);
250 if (__builtin_expect (rem
< 0
251 || (size_t) rem
< (num_transitions
* (8 + 1)
255 tzspec_len
= (size_t) rem
- (num_transitions
* (8 + 1)
258 if (__builtin_expect (num_leaps
> SIZE_MAX
/ 12
259 || tzspec_len
< num_leaps
* 12, 0))
261 tzspec_len
-= num_leaps
* 12;
262 if (__glibc_unlikely (tzspec_len
< num_isstd
))
264 tzspec_len
-= num_isstd
;
265 if (__glibc_unlikely (tzspec_len
== 0 || tzspec_len
- 1 < num_isgmt
))
267 tzspec_len
-= num_isgmt
+ 1;
268 if (__glibc_unlikely (tzspec_len
== 0
269 || SIZE_MAX
- total_size
< tzspec_len
))
272 if (__glibc_unlikely (SIZE_MAX
- total_size
- tzspec_len
< extra
))
275 /* Allocate enough memory including the extra block requested by the
277 transitions
= malloc (total_size
+ tzspec_len
+ extra
);
278 if (transitions
== NULL
)
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
;
291 *extrap
= (char *) &leaps
[num_leaps
];
293 if (__builtin_expect (trans_width
== 8, 1))
295 if (__builtin_expect (__fread_unlocked (transitions
, trans_width
+ 1,
297 != num_transitions
, 0))
302 if (__builtin_expect (__fread_unlocked (transitions
, 4,
304 != num_transitions
, 0)
305 || __builtin_expect (__fread_unlocked (type_idxs
, 1, num_transitions
,
306 f
) != num_transitions
, 0))
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
))
316 if (trans_width
== 4)
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
324 transitions
[i
] = decode ((char *) transitions
+ i
* 4);
326 else if (BYTE_ORDER
!= BIG_ENDIAN
)
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);
334 for (i
= 0; i
< num_types
; ++i
)
338 if (__builtin_expect (__fread_unlocked (x
, 1,
339 sizeof (x
), f
) != sizeof (x
),
342 c
= __getc_unlocked (f
);
343 if (__glibc_unlikely ((unsigned int) c
> 1u))
346 c
= __getc_unlocked (f
);
347 if (__glibc_unlikely ((size_t) c
> chars
))
348 /* Bogus index in data file. */
351 types
[i
].offset
= (long int) decode (x
);
354 if (__glibc_unlikely (__fread_unlocked (zone_names
, 1, chars
, f
) != chars
))
357 for (i
= 0; i
< num_leaps
; ++i
)
360 if (__builtin_expect (__fread_unlocked (x
, 1, trans_width
, f
)
363 if (trans_width
== 4)
364 leaps
[i
].transition
= decode (x
);
366 leaps
[i
].transition
= decode64 (x
);
368 if (__glibc_unlikely (__fread_unlocked (x
, 1, 4, f
) != 4))
370 leaps
[i
].change
= (long int) decode (x
);
373 for (i
= 0; i
< num_isstd
; ++i
)
375 int c
= __getc_unlocked (f
);
376 if (__glibc_unlikely (c
== EOF
))
378 types
[i
].isstd
= c
!= 0;
380 while (i
< num_types
)
381 types
[i
++].isstd
= 0;
383 for (i
= 0; i
< num_isgmt
; ++i
)
385 int c
= __getc_unlocked (f
);
386 if (__glibc_unlikely (c
== EOF
))
388 types
[i
].isgmt
= c
!= 0;
390 while (i
< num_types
)
391 types
[i
++].isgmt
= 0;
393 /* Read the POSIX TZ-style information if possible. */
396 /* Skip over the newline first. */
397 if (__getc_unlocked (f
) != '\n'
398 || (__fread_unlocked (tzspec
, 1, tzspec_len
- 1, f
)
402 tzspec
[tzspec_len
- 1] = '\0';
405 /* Don't use an empty TZ string. */
406 if (tzspec
!= NULL
&& tzspec
[0] == '\0')
411 /* First "register" all timezone names. */
412 for (i
= 0; i
< num_types
; ++i
)
413 (void) __tzstring (&zone_names
[types
[i
].idx
]);
415 /* Find the standard and daylight time offsets used by the rule file.
416 We choose the offsets in the types of each flavor that are
417 transitioned to earliest in time. */
420 for (i
= num_transitions
; i
> 0; )
422 int type
= type_idxs
[--i
];
423 int dst
= types
[type
].isdst
;
425 if (__tzname
[dst
] == NULL
)
427 int idx
= types
[type
].idx
;
429 __tzname
[dst
] = __tzstring (&zone_names
[idx
]);
431 if (__tzname
[1 - dst
] != NULL
)
435 if (__tzname
[0] == NULL
)
437 /* This should only happen if there are no transition rules.
438 In this case there should be only one single type. */
439 assert (num_types
== 1);
440 __tzname
[0] = __tzstring (zone_names
);
442 if (__tzname
[1] == NULL
)
443 __tzname
[1] = __tzname
[0];
445 if (num_transitions
== 0)
446 /* Use the first rule (which should also be the only one). */
447 rule_stdoff
= rule_dstoff
= types
[0].offset
;
450 int stdoff_set
= 0, dstoff_set
= 0;
451 rule_stdoff
= rule_dstoff
= 0;
452 i
= num_transitions
- 1;
455 if (!stdoff_set
&& !types
[type_idxs
[i
]].isdst
)
458 rule_stdoff
= types
[type_idxs
[i
]].offset
;
460 else if (!dstoff_set
&& types
[type_idxs
[i
]].isdst
)
463 rule_dstoff
= types
[type_idxs
[i
]].offset
;
465 if (stdoff_set
&& dstoff_set
)
471 rule_dstoff
= rule_stdoff
;
474 __daylight
= rule_stdoff
!= rule_dstoff
;
475 __timezone
= -rule_stdoff
;
484 ret_free_transitions
:
486 free ((void *) transitions
);
490 /* The user specified a hand-made timezone, but not its DST rules.
491 We will use the names and offsets from the user, and the rules
492 from the TZDEFRULES file. */
495 __tzfile_default (const char *std
, const char *dst
,
496 long int stdoff
, long int dstoff
)
498 size_t stdlen
= strlen (std
) + 1;
499 size_t dstlen
= strlen (dst
) + 1;
504 __tzfile_read (TZDEFRULES
, stdlen
+ dstlen
, &cp
);
514 /* Ignore the zone names read from the file and use the given ones
516 __mempcpy (__mempcpy (cp
, std
, stdlen
), dst
, dstlen
);
519 /* Now there are only two zones, regardless of what the file contained. */
522 /* Now correct the transition times for the user-specified standard and
523 daylight offsets from GMT. */
525 for (i
= 0; i
< num_transitions
; ++i
)
527 struct ttinfo
*trans_type
= &types
[type_idxs
[i
]];
529 /* We will use only types 0 (standard) and 1 (daylight).
530 Fix up this transition to point to whichever matches
531 the flavor of its original type. */
532 type_idxs
[i
] = trans_type
->isdst
;
534 if (trans_type
->isgmt
)
535 /* The transition time is in GMT. No correction to apply. */ ;
536 else if (isdst
&& !trans_type
->isstd
)
537 /* The type says this transition is in "local wall clock time", and
538 wall clock time as of the previous transition was DST. Correct
539 for the difference between the rule's DST offset and the user's
541 transitions
[i
] += dstoff
- rule_dstoff
;
543 /* This transition is in "local wall clock time", and wall clock
544 time as of this iteration is non-DST. Correct for the
545 difference between the rule's standard offset and the user's
547 transitions
[i
] += stdoff
- rule_stdoff
;
549 /* The DST state of "local wall clock time" for the next iteration is
550 as specified by this transition. */
551 isdst
= trans_type
->isdst
;
554 /* Now that we adjusted the transitions to the requested offsets,
555 reset the rule_stdoff and rule_dstoff values appropriately. They
556 are used elsewhere. */
557 rule_stdoff
= stdoff
;
558 rule_dstoff
= dstoff
;
560 /* Reset types 0 and 1 to describe the user's settings. */
562 types
[0].offset
= stdoff
;
564 types
[1].idx
= stdlen
;
565 types
[1].offset
= dstoff
;
568 /* Reset the zone names to point to the user's names. */
569 __tzname
[0] = (char *) std
;
570 __tzname
[1] = (char *) dst
;
572 /* Set the timezone. */
573 __timezone
= -types
[0].offset
;
575 /* Invalidate the tzfile attribute cache to force rereading
576 TZDEFRULES the next time it is used. */
583 __tzfile_compute (internal_time_t timer
, int use_localtime
,
584 long int *leap_correct
, int *leap_hit
,
594 if (__glibc_unlikely (num_transitions
== 0 || timer
< transitions
[0]))
596 /* TIMER is before any transition (or there are no transitions).
597 Choose the first non-DST type
598 (or the first if they're all DST types). */
600 while (i
< num_types
&& types
[i
].isdst
)
602 if (__tzname
[1] == NULL
)
603 __tzname
[1] = __tzstring (&zone_names
[types
[i
].idx
]);
610 __tzname
[0] = __tzstring (&zone_names
[types
[i
].idx
]);
611 if (__tzname
[1] == NULL
)
614 while (j
< num_types
)
617 __tzname
[1] = __tzstring (&zone_names
[types
[j
].idx
]);
624 else if (__glibc_unlikely (timer
>= transitions
[num_transitions
- 1]))
626 if (__glibc_unlikely (tzspec
== NULL
))
633 /* Parse the POSIX TZ-style string. */
634 __tzset_parse_tz (tzspec
);
636 /* Convert to broken down structure. If this fails do not
639 time_t truncated
= timer
;
640 if (__glibc_unlikely (truncated
!= timer
641 || ! __offtime (&truncated
, 0, tp
)))
645 /* Use the rules from the TZ string to compute the change.
646 timer fits into time_t due to the truncation check
648 __tz_compute (timer
, tp
, 1);
650 /* If tzspec comes from posixrules loaded by __tzfile_default,
651 override the STD and DST zone names with the ones user
652 requested in TZ envvar. */
653 if (__glibc_unlikely (zone_names
== (char *) &leaps
[num_leaps
]))
655 assert (num_types
== 2);
656 __tzname
[0] = __tzstring (zone_names
);
657 __tzname
[1] = __tzstring (&zone_names
[strlen (zone_names
) + 1]);
664 /* Find the first transition after TIMER, and
665 then pick the type of the transition before it. */
667 size_t hi
= num_transitions
- 1;
668 /* Assume that DST is changing twice a year and guess
669 initial search spot from it. Half of a gregorian year
670 has on average 365.2425 * 86400 / 2 = 15778476 seconds.
671 The value i can be truncated if size_t is smaller than
672 internal_time_t, but this is harmless because it is just
674 i
= (transitions
[num_transitions
- 1] - timer
) / 15778476;
675 if (i
< num_transitions
)
677 i
= num_transitions
- 1 - i
;
678 if (timer
< transitions
[i
])
680 if (i
< 10 || timer
>= transitions
[i
- 10])
683 while (timer
< transitions
[i
- 1])
691 if (i
+ 10 >= num_transitions
|| timer
< transitions
[i
+ 10])
694 while (timer
>= transitions
[i
])
703 /* assert (timer >= transitions[lo] && timer < transitions[hi]); */
707 if (timer
< transitions
[i
])
715 /* assert (timer >= transitions[i - 1]
716 && (i == num_transitions || timer < transitions[i])); */
717 __tzname
[types
[type_idxs
[i
- 1]].isdst
]
718 = __tzstring (&zone_names
[types
[type_idxs
[i
- 1]].idx
]);
720 while (j
< num_transitions
)
722 int type
= type_idxs
[j
];
723 int dst
= types
[type
].isdst
;
724 int idx
= types
[type
].idx
;
726 if (__tzname
[dst
] == NULL
)
728 __tzname
[dst
] = __tzstring (&zone_names
[idx
]);
730 if (__tzname
[1 - dst
] != NULL
)
737 if (__glibc_unlikely (__tzname
[0] == NULL
))
738 __tzname
[0] = __tzname
[1];
740 i
= type_idxs
[i
- 1];
743 struct ttinfo
*info
= &types
[i
];
744 __daylight
= rule_stdoff
!= rule_dstoff
;
745 __timezone
= -rule_stdoff
;
747 if (__tzname
[0] == NULL
)
749 /* This should only happen if there are no transition rules.
750 In this case there should be only one single type. */
751 assert (num_types
== 1);
752 __tzname
[0] = __tzstring (zone_names
);
754 if (__tzname
[1] == NULL
)
755 /* There is no daylight saving time. */
756 __tzname
[1] = __tzname
[0];
757 tp
->tm_isdst
= info
->isdst
;
758 assert (strcmp (&zone_names
[info
->idx
], __tzname
[tp
->tm_isdst
]) == 0);
759 tp
->tm_zone
= __tzname
[tp
->tm_isdst
];
760 tp
->tm_gmtoff
= info
->offset
;
767 /* Find the last leap second correction transition time before TIMER. */
772 while (timer
< leaps
[i
].transition
);
774 /* Apply its correction. */
775 *leap_correct
= leaps
[i
].change
;
777 if (timer
== leaps
[i
].transition
&& /* Exactly at the transition time. */
778 ((i
== 0 && leaps
[i
].change
> 0) ||
779 leaps
[i
].change
> leaps
[i
- 1].change
))
783 && leaps
[i
].transition
== leaps
[i
- 1].transition
+ 1
784 && leaps
[i
].change
== leaps
[i
- 1].change
+ 1)