1 /* Copyright (C) 1991-1993,1995-2001,2003,2004,2006,2007,2009,2011
2 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 #include <stdio_ext.h>
31 #include <timezone/tzfile.h>
34 static dev_t tzfile_dev
;
35 static ino64_t tzfile_ino
;
36 static time_t tzfile_mtime
;
40 long int offset
; /* Seconds east of GMT. */
41 unsigned char isdst
; /* Used to set tm_isdst. */
42 unsigned char idx
; /* Index into `zone_names'. */
43 unsigned char isstd
; /* Transition times are in standard time. */
44 unsigned char isgmt
; /* Transition times are in GMT. */
49 time_t transition
; /* Time the transition takes effect. */
50 long int change
; /* Seconds of correction to apply. */
53 static void compute_tzname_max (size_t) internal_function
;
55 static size_t num_transitions
;
56 libc_freeres_ptr (static time_t *transitions
);
57 static unsigned char *type_idxs
;
58 static size_t num_types
;
59 static struct ttinfo
*types
;
60 static char *zone_names
;
61 static long int rule_stdoff
;
62 static long int rule_dstoff
;
63 static size_t num_leaps
;
64 static struct leap
*leaps
;
70 /* Decode the four bytes at PTR as a signed integer in network byte order. */
72 __attribute ((always_inline
))
73 decode (const void *ptr
)
75 if (BYTE_ORDER
== BIG_ENDIAN
&& sizeof (int) == 4)
76 return *(const int *) ptr
;
77 if (sizeof (int) == 4)
78 return bswap_32 (*(const int *) ptr
);
80 const unsigned char *p
= ptr
;
81 int result
= *p
& (1 << (CHAR_BIT
- 1)) ? ~0 : 0;
83 result
= (result
<< 8) | *p
++;
84 result
= (result
<< 8) | *p
++;
85 result
= (result
<< 8) | *p
++;
86 result
= (result
<< 8) | *p
++;
93 __attribute ((always_inline
))
94 decode64 (const void *ptr
)
96 if ((BYTE_ORDER
== BIG_ENDIAN
))
97 return *(const int64_t *) ptr
;
99 return bswap_64 (*(const int64_t *) ptr
);
104 __tzfile_read (const char *file
, size_t extra
, char **extrap
)
106 static const char default_tzdir
[] = TZDIR
;
107 size_t num_isstd
, num_isgmt
;
109 struct tzhead tzhead
;
115 int was_using_tzfile
= __use_tzfile
;
119 if (sizeof (time_t) != 4 && sizeof (time_t) != 8)
125 /* No user specification; use the site-wide default. */
127 else if (*file
== '\0')
128 /* User specified the empty string; use UTC with no leap seconds. */
129 goto ret_free_transitions
;
132 /* We must not allow to read an arbitrary file in a setuid
133 program. So we fail for any file which is not in the
134 directory hierachy starting at TZDIR
135 and which is not the system wide default TZDEFAULT. */
136 if (__libc_enable_secure
138 && memcmp (file
, TZDEFAULT
, sizeof TZDEFAULT
)
139 && memcmp (file
, default_tzdir
, sizeof (default_tzdir
) - 1))
140 || strstr (file
, "../") != NULL
))
141 /* This test is certainly a bit too restrictive but it should
142 catch all critical cases. */
143 goto ret_free_transitions
;
149 unsigned int len
, tzdir_len
;
152 tzdir
= getenv ("TZDIR");
153 if (tzdir
== NULL
|| *tzdir
== '\0')
155 tzdir
= default_tzdir
;
156 tzdir_len
= sizeof (default_tzdir
) - 1;
159 tzdir_len
= strlen (tzdir
);
160 len
= strlen (file
) + 1;
161 new = (char *) __alloca (tzdir_len
+ 1 + len
);
162 tmp
= __mempcpy (new, tzdir
, tzdir_len
);
164 memcpy (tmp
, file
, len
);
168 /* If we were already using tzfile, check whether the file changed. */
171 && stat64 (file
, &st
) == 0
172 && tzfile_ino
== st
.st_ino
&& tzfile_dev
== st
.st_dev
173 && tzfile_mtime
== st
.st_mtime
)
180 /* Note the file is opened with cancellation in the I/O functions
181 disabled and if available FD_CLOEXEC set. */
182 f
= fopen (file
, "rce");
184 goto ret_free_transitions
;
186 /* Get information about the file we are actually using. */
187 if (fstat64 (fileno (f
), &st
) != 0)
190 goto ret_free_transitions
;
193 free ((void *) transitions
);
196 /* Remember the inode and device number and modification time. */
197 tzfile_dev
= st
.st_dev
;
198 tzfile_ino
= st
.st_ino
;
199 tzfile_mtime
= st
.st_mtime
;
201 /* No threads reading this stream. */
202 __fsetlocking (f
, FSETLOCKING_BYCALLER
);
205 if (__builtin_expect (fread_unlocked ((void *) &tzhead
, sizeof (tzhead
),
207 || memcmp (tzhead
.tzh_magic
, TZ_MAGIC
, sizeof (tzhead
.tzh_magic
)) != 0)
210 num_transitions
= (size_t) decode (tzhead
.tzh_timecnt
);
211 num_types
= (size_t) decode (tzhead
.tzh_typecnt
);
212 chars
= (size_t) decode (tzhead
.tzh_charcnt
);
213 num_leaps
= (size_t) decode (tzhead
.tzh_leapcnt
);
214 num_isstd
= (size_t) decode (tzhead
.tzh_ttisstdcnt
);
215 num_isgmt
= (size_t) decode (tzhead
.tzh_ttisgmtcnt
);
217 /* For platforms with 64-bit time_t we use the new format if available. */
218 if (sizeof (time_t) == 8 && trans_width
== 4
219 && tzhead
.tzh_version
[0] != '\0')
221 /* We use the 8-byte format. */
224 /* Position the stream before the second header. */
225 size_t to_skip
= (num_transitions
* (4 + 1)
231 if (fseek (f
, to_skip
, SEEK_CUR
) != 0)
237 if (__builtin_expect (num_transitions
238 > ((SIZE_MAX
- (__alignof__ (struct ttinfo
) - 1))
239 / (sizeof (time_t) + 1)), 0))
241 total_size
= num_transitions
* (sizeof (time_t) + 1);
242 total_size
= ((total_size
+ __alignof__ (struct ttinfo
) - 1)
243 & ~(__alignof__ (struct ttinfo
) - 1));
244 types_idx
= total_size
;
245 if (__builtin_expect (num_types
246 > (SIZE_MAX
- total_size
) / sizeof (struct ttinfo
), 0))
248 total_size
+= num_types
* sizeof (struct ttinfo
);
249 if (__builtin_expect (chars
> SIZE_MAX
- total_size
, 0))
252 if (__builtin_expect (__alignof__ (struct leap
) - 1
253 > SIZE_MAX
- total_size
, 0))
255 total_size
= ((total_size
+ __alignof__ (struct leap
) - 1)
256 & ~(__alignof__ (struct leap
) - 1));
257 leaps_idx
= total_size
;
258 if (__builtin_expect (num_leaps
259 > (SIZE_MAX
- total_size
) / sizeof (struct leap
), 0))
261 total_size
+= num_leaps
* sizeof (struct leap
);
263 if (sizeof (time_t) == 8 && trans_width
== 8)
265 off_t rem
= st
.st_size
- ftello (f
);
266 if (__builtin_expect (rem
< 0
267 || (size_t) rem
< (num_transitions
* (8 + 1)
271 tzspec_len
= (size_t) rem
- (num_transitions
* (8 + 1)
274 if (__builtin_expect (num_leaps
> SIZE_MAX
/ 12
275 || tzspec_len
< num_leaps
* 12, 0))
277 tzspec_len
-= num_leaps
* 12;
278 if (__builtin_expect (tzspec_len
< num_isstd
, 0))
280 tzspec_len
-= num_isstd
;
281 if (__builtin_expect (tzspec_len
== 0 || tzspec_len
- 1 < num_isgmt
, 0))
283 tzspec_len
-= num_isgmt
+ 1;
284 if (__builtin_expect (SIZE_MAX
- total_size
< tzspec_len
, 0))
287 if (__builtin_expect (SIZE_MAX
- total_size
- tzspec_len
< extra
, 0))
290 /* Allocate enough memory including the extra block requested by the
292 transitions
= (time_t *) malloc (total_size
+ tzspec_len
+ extra
);
293 if (transitions
== NULL
)
296 type_idxs
= (unsigned char *) transitions
+ (num_transitions
298 types
= (struct ttinfo
*) ((char *) transitions
+ types_idx
);
299 zone_names
= (char *) types
+ num_types
* sizeof (struct ttinfo
);
300 leaps
= (struct leap
*) ((char *) transitions
+ leaps_idx
);
301 if (sizeof (time_t) == 8 && trans_width
== 8)
302 tzspec
= (char *) leaps
+ num_leaps
* sizeof (struct leap
) + extra
;
306 *extrap
= (char *) &leaps
[num_leaps
];
308 if (sizeof (time_t) == 4 || __builtin_expect (trans_width
== 8, 1))
310 if (__builtin_expect (fread_unlocked (transitions
, trans_width
+ 1,
312 != num_transitions
, 0))
317 if (__builtin_expect (fread_unlocked (transitions
, 4, num_transitions
, f
)
318 != num_transitions
, 0)
319 || __builtin_expect (fread_unlocked (type_idxs
, 1, num_transitions
,
320 f
) != num_transitions
, 0))
324 /* Check for bogus indices in the data file, so we can hereafter
325 safely use type_idxs[T] as indices into `types' and never crash. */
326 for (i
= 0; i
< num_transitions
; ++i
)
327 if (__builtin_expect (type_idxs
[i
] >= num_types
, 0))
330 if ((BYTE_ORDER
!= BIG_ENDIAN
&& (sizeof (time_t) == 4 || trans_width
== 4))
331 || (BYTE_ORDER
== BIG_ENDIAN
&& sizeof (time_t) == 8
332 && trans_width
== 4))
334 /* Decode the transition times, stored as 4-byte integers in
335 network (big-endian) byte order. We work from the end of
336 the array so as not to clobber the next element to be
337 processed when sizeof (time_t) > 4. */
340 transitions
[i
] = decode ((char *) transitions
+ i
* 4);
342 else if (BYTE_ORDER
!= BIG_ENDIAN
&& sizeof (time_t) == 8)
344 /* Decode the transition times, stored as 8-byte integers in
345 network (big-endian) byte order. */
346 for (i
= 0; i
< num_transitions
; ++i
)
347 transitions
[i
] = decode64 ((char *) transitions
+ i
* 8);
350 for (i
= 0; i
< num_types
; ++i
)
354 if (__builtin_expect (fread_unlocked (x
, 1, sizeof (x
), f
) != sizeof (x
),
357 c
= getc_unlocked (f
);
358 if (__builtin_expect ((unsigned int) c
> 1u, 0))
361 c
= getc_unlocked (f
);
362 if (__builtin_expect ((size_t) c
> chars
, 0))
363 /* Bogus index in data file. */
366 types
[i
].offset
= (long int) decode (x
);
369 if (__builtin_expect (fread_unlocked (zone_names
, 1, chars
, f
) != chars
, 0))
372 for (i
= 0; i
< num_leaps
; ++i
)
375 if (__builtin_expect (fread_unlocked (x
, 1, trans_width
, f
)
378 if (sizeof (time_t) == 4 || trans_width
== 4)
379 leaps
[i
].transition
= (time_t) decode (x
);
381 leaps
[i
].transition
= (time_t) decode64 (x
);
383 if (__builtin_expect (fread_unlocked (x
, 1, 4, f
) != 4, 0))
385 leaps
[i
].change
= (long int) decode (x
);
388 for (i
= 0; i
< num_isstd
; ++i
)
390 int c
= getc_unlocked (f
);
391 if (__builtin_expect (c
== EOF
, 0))
393 types
[i
].isstd
= c
!= 0;
395 while (i
< num_types
)
396 types
[i
++].isstd
= 0;
398 for (i
= 0; i
< num_isgmt
; ++i
)
400 int c
= getc_unlocked (f
);
401 if (__builtin_expect (c
== EOF
, 0))
403 types
[i
].isgmt
= c
!= 0;
405 while (i
< num_types
)
406 types
[i
++].isgmt
= 0;
408 /* Read the POSIX TZ-style information if possible. */
409 if (sizeof (time_t) == 8 && tzspec
!= NULL
)
411 /* Skip over the newline first. */
412 if (getc_unlocked (f
) != '\n'
413 || (fread_unlocked (tzspec
, 1, tzspec_len
- 1, f
)
417 tzspec
[tzspec_len
- 1] = '\0';
419 else if (sizeof (time_t) == 4 && tzhead
.tzh_version
[0] != '\0')
421 /* Get the TZ string. */
422 if (__builtin_expect (fread_unlocked ((void *) &tzhead
, sizeof (tzhead
),
424 || (memcmp (tzhead
.tzh_magic
, TZ_MAGIC
, sizeof (tzhead
.tzh_magic
))
428 size_t num_transitions2
= (size_t) decode (tzhead
.tzh_timecnt
);
429 size_t num_types2
= (size_t) decode (tzhead
.tzh_typecnt
);
430 size_t chars2
= (size_t) decode (tzhead
.tzh_charcnt
);
431 size_t num_leaps2
= (size_t) decode (tzhead
.tzh_leapcnt
);
432 size_t num_isstd2
= (size_t) decode (tzhead
.tzh_ttisstdcnt
);
433 size_t num_isgmt2
= (size_t) decode (tzhead
.tzh_ttisgmtcnt
);
435 /* Position the stream before the second header. */
436 size_t to_skip
= (num_transitions2
* (8 + 1)
443 if (fseek (f
, to_skip
, SEEK_CUR
) != 0
444 || (off
= ftello (f
)) < 0
445 || st
.st_size
< off
+ 2)
448 tzspec_len
= st
.st_size
- off
- 1;
449 char *tzstr
= alloca (tzspec_len
);
450 if (getc_unlocked (f
) != '\n'
451 || (fread_unlocked (tzstr
, 1, tzspec_len
- 1, f
) != tzspec_len
- 1))
453 tzstr
[tzspec_len
- 1] = '\0';
454 tzspec
= __tzstring (tzstr
);
457 /* Don't use an empty TZ string. */
458 if (tzspec
!= NULL
&& tzspec
[0] == '\0')
463 /* First "register" all timezone names. */
464 for (i
= 0; i
< num_types
; ++i
)
465 (void) __tzstring (&zone_names
[types
[i
].idx
]);
467 /* Find the standard and daylight time offsets used by the rule file.
468 We choose the offsets in the types of each flavor that are
469 transitioned to earliest in time. */
472 for (i
= num_transitions
; i
> 0; )
474 int type
= type_idxs
[--i
];
475 int dst
= types
[type
].isdst
;
477 if (__tzname
[dst
] == NULL
)
479 int idx
= types
[type
].idx
;
481 __tzname
[dst
] = __tzstring (&zone_names
[idx
]);
483 if (__tzname
[1 - dst
] != NULL
)
487 if (__tzname
[0] == NULL
)
489 /* This should only happen if there are no transition rules.
490 In this case there should be only one single type. */
491 assert (num_types
== 1);
492 __tzname
[0] = __tzstring (zone_names
);
494 if (__tzname
[1] == NULL
)
495 __tzname
[1] = __tzname
[0];
497 compute_tzname_max (chars
);
499 if (num_transitions
== 0)
500 /* Use the first rule (which should also be the only one). */
501 rule_stdoff
= rule_dstoff
= types
[0].offset
;
504 int stdoff_set
= 0, dstoff_set
= 0;
505 rule_stdoff
= rule_dstoff
= 0;
506 i
= num_transitions
- 1;
509 if (!stdoff_set
&& !types
[type_idxs
[i
]].isdst
)
512 rule_stdoff
= types
[type_idxs
[i
]].offset
;
514 else if (!dstoff_set
&& types
[type_idxs
[i
]].isdst
)
517 rule_dstoff
= types
[type_idxs
[i
]].offset
;
519 if (stdoff_set
&& dstoff_set
)
525 rule_dstoff
= rule_stdoff
;
528 __daylight
= rule_stdoff
!= rule_dstoff
;
529 __timezone
= -rule_stdoff
;
536 ret_free_transitions
:
537 free ((void *) transitions
);
541 /* The user specified a hand-made timezone, but not its DST rules.
542 We will use the names and offsets from the user, and the rules
543 from the TZDEFRULES file. */
546 __tzfile_default (const char *std
, const char *dst
,
547 long int stdoff
, long int dstoff
)
549 size_t stdlen
= strlen (std
) + 1;
550 size_t dstlen
= strlen (dst
) + 1;
555 __tzfile_read (TZDEFRULES
, stdlen
+ dstlen
, &cp
);
565 /* Ignore the zone names read from the file and use the given ones
567 __mempcpy (__mempcpy (cp
, std
, stdlen
), dst
, dstlen
);
570 /* Now there are only two zones, regardless of what the file contained. */
573 /* Now correct the transition times for the user-specified standard and
574 daylight offsets from GMT. */
576 for (i
= 0; i
< num_transitions
; ++i
)
578 struct ttinfo
*trans_type
= &types
[type_idxs
[i
]];
580 /* We will use only types 0 (standard) and 1 (daylight).
581 Fix up this transition to point to whichever matches
582 the flavor of its original type. */
583 type_idxs
[i
] = trans_type
->isdst
;
585 if (trans_type
->isgmt
)
586 /* The transition time is in GMT. No correction to apply. */ ;
587 else if (isdst
&& !trans_type
->isstd
)
588 /* The type says this transition is in "local wall clock time", and
589 wall clock time as of the previous transition was DST. Correct
590 for the difference between the rule's DST offset and the user's
592 transitions
[i
] += dstoff
- rule_dstoff
;
594 /* This transition is in "local wall clock time", and wall clock
595 time as of this iteration is non-DST. Correct for the
596 difference between the rule's standard offset and the user's
598 transitions
[i
] += stdoff
- rule_stdoff
;
600 /* The DST state of "local wall clock time" for the next iteration is
601 as specified by this transition. */
602 isdst
= trans_type
->isdst
;
605 /* Now that we adjusted the transitions to the requested offsets,
606 reset the rule_stdoff and rule_dstoff values appropriately. They
607 are used elsewhere. */
608 rule_stdoff
= stdoff
;
609 rule_dstoff
= dstoff
;
611 /* Reset types 0 and 1 to describe the user's settings. */
613 types
[0].offset
= stdoff
;
615 types
[1].idx
= stdlen
;
616 types
[1].offset
= dstoff
;
619 /* Reset the zone names to point to the user's names. */
620 __tzname
[0] = (char *) std
;
621 __tzname
[1] = (char *) dst
;
623 /* Set the timezone. */
624 __timezone
= -types
[0].offset
;
626 compute_tzname_max (stdlen
+ dstlen
);
630 __tzfile_compute (time_t timer
, int use_localtime
,
631 long int *leap_correct
, int *leap_hit
,
641 if (__builtin_expect (num_transitions
== 0 || timer
< transitions
[0], 0))
643 /* TIMER is before any transition (or there are no transitions).
644 Choose the first non-DST type
645 (or the first if they're all DST types). */
647 while (i
< num_types
&& types
[i
].isdst
)
649 if (__tzname
[1] == NULL
)
650 __tzname
[1] = __tzstring (&zone_names
[types
[i
].idx
]);
657 __tzname
[0] = __tzstring (&zone_names
[types
[i
].idx
]);
658 if (__tzname
[1] == NULL
)
661 while (j
< num_types
)
664 __tzname
[1] = __tzstring (&zone_names
[types
[j
].idx
]);
671 else if (__builtin_expect (timer
>= transitions
[num_transitions
- 1], 0))
673 if (__builtin_expect (tzspec
== NULL
, 0))
680 /* Parse the POSIX TZ-style string. */
681 __tzset_parse_tz (tzspec
);
683 /* Convert to broken down structure. If this fails do not
685 if (__builtin_expect (! __offtime (&timer
, 0, tp
), 0))
688 /* Use the rules from the TZ string to compute the change. */
689 __tz_compute (timer
, tp
, 1);
691 /* If tzspec comes from posixrules loaded by __tzfile_default,
692 override the STD and DST zone names with the ones user
693 requested in TZ envvar. */
694 if (__builtin_expect (zone_names
== (char *) &leaps
[num_leaps
], 0))
696 assert (num_types
== 2);
697 __tzname
[0] = __tzstring (zone_names
);
698 __tzname
[1] = __tzstring (&zone_names
[strlen (zone_names
) + 1]);
705 /* Find the first transition after TIMER, and
706 then pick the type of the transition before it. */
708 size_t hi
= num_transitions
- 1;
709 /* Assume that DST is changing twice a year and guess initial
711 Half of a gregorian year has on average 365.2425 * 86400 / 2
712 = 15778476 seconds. */
713 i
= (transitions
[num_transitions
- 1] - timer
) / 15778476;
714 if (i
< num_transitions
)
716 i
= num_transitions
- 1 - i
;
717 if (timer
< transitions
[i
])
719 if (i
< 10 || timer
>= transitions
[i
- 10])
722 while (timer
< transitions
[i
- 1])
730 if (i
+ 10 >= num_transitions
|| timer
< transitions
[i
+ 10])
733 while (timer
>= transitions
[i
])
742 /* assert (timer >= transitions[lo] && timer < transitions[hi]); */
746 if (timer
< transitions
[i
])
754 /* assert (timer >= transitions[i - 1]
755 && (i == num_transitions || timer < transitions[i])); */
756 __tzname
[types
[type_idxs
[i
- 1]].isdst
]
757 = __tzstring (&zone_names
[types
[type_idxs
[i
- 1]].idx
]);
759 while (j
< num_transitions
)
761 int type
= type_idxs
[j
];
762 int dst
= types
[type
].isdst
;
763 int idx
= types
[type
].idx
;
765 if (__tzname
[dst
] == NULL
)
767 __tzname
[dst
] = __tzstring (&zone_names
[idx
]);
769 if (__tzname
[1 - dst
] != NULL
)
776 if (__builtin_expect (__tzname
[0] == NULL
, 0))
777 __tzname
[0] = __tzname
[1];
779 i
= type_idxs
[i
- 1];
782 struct ttinfo
*info
= &types
[i
];
783 __daylight
= rule_stdoff
!= rule_dstoff
;
784 __timezone
= -rule_stdoff
;
786 if (__tzname
[0] == NULL
)
788 /* This should only happen if there are no transition rules.
789 In this case there should be only one single type. */
790 assert (num_types
== 1);
791 __tzname
[0] = __tzstring (zone_names
);
793 if (__tzname
[1] == NULL
)
794 /* There is no daylight saving time. */
795 __tzname
[1] = __tzname
[0];
796 tp
->tm_isdst
= info
->isdst
;
797 assert (strcmp (&zone_names
[info
->idx
], __tzname
[tp
->tm_isdst
]) == 0);
798 tp
->tm_zone
= __tzname
[tp
->tm_isdst
];
799 tp
->tm_gmtoff
= info
->offset
;
806 /* Find the last leap second correction transition time before TIMER. */
811 while (timer
< leaps
[i
].transition
);
813 /* Apply its correction. */
814 *leap_correct
= leaps
[i
].change
;
816 if (timer
== leaps
[i
].transition
&& /* Exactly at the transition time. */
817 ((i
== 0 && leaps
[i
].change
> 0) ||
818 leaps
[i
].change
> leaps
[i
- 1].change
))
822 && leaps
[i
].transition
== leaps
[i
- 1].transition
+ 1
823 && leaps
[i
].change
== leaps
[i
- 1].change
+ 1)
833 compute_tzname_max (size_t chars
)
840 const char *start
= p
;
843 if ((size_t) (p
- start
) > __tzname_cur_max
)
844 __tzname_cur_max
= p
- start
;
846 while (++p
< &zone_names
[chars
]);