Fix LD_PROFILE
[platform/upstream/glibc.git] / time / tzfile.c
1 /* Copyright (C) 1991-2015 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 #define NOID
30 #include <timezone/tzfile.h>
31
32 int __use_tzfile;
33 static dev_t tzfile_dev;
34 static ino64_t tzfile_ino;
35 static time_t tzfile_mtime;
36
37 struct ttinfo
38   {
39     long int offset;            /* Seconds east of GMT.  */
40     unsigned char isdst;        /* Used to set tm_isdst.  */
41     unsigned char idx;          /* Index into `zone_names'.  */
42     unsigned char isstd;        /* Transition times are in standard time.  */
43     unsigned char isgmt;        /* Transition times are in GMT.  */
44   };
45
46 struct leap
47   {
48     time_t transition;          /* Time the transition takes effect.  */
49     long int change;            /* Seconds of correction to apply.  */
50   };
51
52 static void compute_tzname_max (size_t) internal_function;
53
54 static size_t num_transitions;
55 libc_freeres_ptr (static time_t *transitions);
56 static unsigned char *type_idxs;
57 static size_t num_types;
58 static struct ttinfo *types;
59 static char *zone_names;
60 static long int rule_stdoff;
61 static long int rule_dstoff;
62 static size_t num_leaps;
63 static struct leap *leaps;
64 static char *tzspec;
65
66 #include <endian.h>
67 #include <byteswap.h>
68
69 /* Decode the four bytes at PTR as a signed integer in network byte order.  */
70 static inline int
71 __attribute ((always_inline))
72 decode (const void *ptr)
73 {
74   if (BYTE_ORDER == BIG_ENDIAN && sizeof (int) == 4)
75     return *(const int *) ptr;
76   if (sizeof (int) == 4)
77     return bswap_32 (*(const int *) ptr);
78
79   const unsigned char *p = ptr;
80   int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0;
81
82   result = (result << 8) | *p++;
83   result = (result << 8) | *p++;
84   result = (result << 8) | *p++;
85   result = (result << 8) | *p++;
86
87   return result;
88 }
89
90
91 static inline int64_t
92 __attribute ((always_inline))
93 decode64 (const void *ptr)
94 {
95   if ((BYTE_ORDER == BIG_ENDIAN))
96     return *(const int64_t *) ptr;
97
98   return bswap_64 (*(const int64_t *) ptr);
99 }
100
101
102 void
103 __tzfile_read (const char *file, size_t extra, char **extrap)
104 {
105   static const char default_tzdir[] = TZDIR;
106   size_t num_isstd, num_isgmt;
107   FILE *f;
108   struct tzhead tzhead;
109   size_t chars;
110   size_t i;
111   size_t total_size;
112   size_t types_idx;
113   size_t leaps_idx;
114   int was_using_tzfile = __use_tzfile;
115   int trans_width = 4;
116   size_t tzspec_len;
117   char *new = NULL;
118
119   if (sizeof (time_t) != 4 && sizeof (time_t) != 8)
120     abort ();
121
122   __use_tzfile = 0;
123
124   if (file == NULL)
125     /* No user specification; use the site-wide default.  */
126     file = TZDEFAULT;
127   else if (*file == '\0')
128     /* User specified the empty string; use UTC with no leap seconds.  */
129     goto ret_free_transitions;
130   else
131     {
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
137           && ((*file == '/'
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;
144     }
145
146   if (*file != '/')
147     {
148       const char *tzdir;
149
150       tzdir = getenv ("TZDIR");
151       if (tzdir == NULL || *tzdir == '\0')
152         tzdir = default_tzdir;
153       if (__asprintf (&new, "%s/%s", tzdir, file) == -1)
154         goto ret_free_transitions;
155       file = new;
156     }
157
158   /* If we were already using tzfile, check whether the file changed.  */
159   struct stat64 st;
160   if (was_using_tzfile
161       && stat64 (file, &st) == 0
162       && tzfile_ino == st.st_ino && tzfile_dev == st.st_dev
163       && tzfile_mtime == st.st_mtime)
164     goto done;  /* Nothing to do.  */
165
166   /* Note the file is opened with cancellation in the I/O functions
167      disabled and if available FD_CLOEXEC set.  */
168   f = fopen (file, "rce");
169   if (f == NULL)
170     goto ret_free_transitions;
171
172   /* Get information about the file we are actually using.  */
173   if (fstat64 (__fileno (f), &st) != 0)
174     {
175       fclose (f);
176       goto ret_free_transitions;
177     }
178
179   free ((void *) transitions);
180   transitions = NULL;
181
182   /* Remember the inode and device number and modification time.  */
183   tzfile_dev = st.st_dev;
184   tzfile_ino = st.st_ino;
185   tzfile_mtime = st.st_mtime;
186
187   /* No threads reading this stream.  */
188   __fsetlocking (f, FSETLOCKING_BYCALLER);
189
190  read_again:
191   if (__builtin_expect (__fread_unlocked ((void *) &tzhead, sizeof (tzhead),
192                                           1, f) != 1, 0)
193       || memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic)) != 0)
194     goto lose;
195
196   num_transitions = (size_t) decode (tzhead.tzh_timecnt);
197   num_types = (size_t) decode (tzhead.tzh_typecnt);
198   chars = (size_t) decode (tzhead.tzh_charcnt);
199   num_leaps = (size_t) decode (tzhead.tzh_leapcnt);
200   num_isstd = (size_t) decode (tzhead.tzh_ttisstdcnt);
201   num_isgmt = (size_t) decode (tzhead.tzh_ttisgmtcnt);
202
203   /* For platforms with 64-bit time_t we use the new format if available.  */
204   if (sizeof (time_t) == 8 && trans_width == 4
205       && tzhead.tzh_version[0] != '\0')
206     {
207       /* We use the 8-byte format.  */
208       trans_width = 8;
209
210       /* Position the stream before the second header.  */
211       size_t to_skip = (num_transitions * (4 + 1)
212                         + num_types * 6
213                         + chars
214                         + num_leaps * 8
215                         + num_isstd
216                         + num_isgmt);
217       if (fseek (f, to_skip, SEEK_CUR) != 0)
218         goto lose;
219
220       goto read_again;
221     }
222
223   if (__builtin_expect (num_transitions
224                         > ((SIZE_MAX - (__alignof__ (struct ttinfo) - 1))
225                            / (sizeof (time_t) + 1)), 0))
226     goto lose;
227   total_size = num_transitions * (sizeof (time_t) + 1);
228   total_size = ((total_size + __alignof__ (struct ttinfo) - 1)
229                 & ~(__alignof__ (struct ttinfo) - 1));
230   types_idx = total_size;
231   if (__builtin_expect (num_types
232                         > (SIZE_MAX - total_size) / sizeof (struct ttinfo), 0))
233     goto lose;
234   total_size += num_types * sizeof (struct ttinfo);
235   if (__glibc_unlikely (chars > SIZE_MAX - total_size))
236     goto lose;
237   total_size += chars;
238   if (__builtin_expect (__alignof__ (struct leap) - 1
239                         > SIZE_MAX - total_size, 0))
240     goto lose;
241   total_size = ((total_size + __alignof__ (struct leap) - 1)
242                 & ~(__alignof__ (struct leap) - 1));
243   leaps_idx = total_size;
244   if (__builtin_expect (num_leaps
245                         > (SIZE_MAX - total_size) / sizeof (struct leap), 0))
246     goto lose;
247   total_size += num_leaps * sizeof (struct leap);
248   tzspec_len = 0;
249   if (sizeof (time_t) == 8 && trans_width == 8)
250     {
251       off_t rem = st.st_size - __ftello (f);
252       if (__builtin_expect (rem < 0
253                             || (size_t) rem < (num_transitions * (8 + 1)
254                                                + num_types * 6
255                                                + chars), 0))
256         goto lose;
257       tzspec_len = (size_t) rem - (num_transitions * (8 + 1)
258                                    + num_types * 6
259                                    + chars);
260       if (__builtin_expect (num_leaps > SIZE_MAX / 12
261                             || tzspec_len < num_leaps * 12, 0))
262         goto lose;
263       tzspec_len -= num_leaps * 12;
264       if (__glibc_unlikely (tzspec_len < num_isstd))
265         goto lose;
266       tzspec_len -= num_isstd;
267       if (__glibc_unlikely (tzspec_len == 0 || tzspec_len - 1 < num_isgmt))
268         goto lose;
269       tzspec_len -= num_isgmt + 1;
270       if (__glibc_unlikely (SIZE_MAX - total_size < tzspec_len))
271         goto lose;
272     }
273   if (__glibc_unlikely (SIZE_MAX - total_size - tzspec_len < extra))
274     goto lose;
275
276   /* Allocate enough memory including the extra block requested by the
277      caller.  */
278   transitions = (time_t *) malloc (total_size + tzspec_len + extra);
279   if (transitions == NULL)
280     goto lose;
281
282   type_idxs = (unsigned char *) transitions + (num_transitions
283                                                * sizeof (time_t));
284   types = (struct ttinfo *) ((char *) transitions + types_idx);
285   zone_names = (char *) types + num_types * sizeof (struct ttinfo);
286   leaps = (struct leap *) ((char *) transitions + leaps_idx);
287   if (sizeof (time_t) == 8 && trans_width == 8)
288     tzspec = (char *) leaps + num_leaps * sizeof (struct leap) + extra;
289   else
290     tzspec = NULL;
291   if (extra > 0)
292     *extrap = (char *) &leaps[num_leaps];
293
294   if (sizeof (time_t) == 4 || __builtin_expect (trans_width == 8, 1))
295     {
296       if (__builtin_expect (__fread_unlocked (transitions, trans_width + 1,
297                                               num_transitions, f)
298                             != num_transitions, 0))
299         goto lose;
300     }
301   else
302     {
303       if (__builtin_expect (__fread_unlocked (transitions, 4,
304                                               num_transitions, f)
305                             != num_transitions, 0)
306           || __builtin_expect (__fread_unlocked (type_idxs, 1, num_transitions,
307                                                  f) != num_transitions, 0))
308         goto lose;
309     }
310
311   /* Check for bogus indices in the data file, so we can hereafter
312      safely use type_idxs[T] as indices into `types' and never crash.  */
313   for (i = 0; i < num_transitions; ++i)
314     if (__glibc_unlikely (type_idxs[i] >= num_types))
315       goto lose;
316
317   if ((BYTE_ORDER != BIG_ENDIAN && (sizeof (time_t) == 4 || trans_width == 4))
318       || (BYTE_ORDER == BIG_ENDIAN && sizeof (time_t) == 8
319           && trans_width == 4))
320     {
321       /* Decode the transition times, stored as 4-byte integers in
322          network (big-endian) byte order.  We work from the end of
323          the array so as not to clobber the next element to be
324          processed when sizeof (time_t) > 4.  */
325       i = num_transitions;
326       while (i-- > 0)
327         transitions[i] = decode ((char *) transitions + i * 4);
328     }
329   else if (BYTE_ORDER != BIG_ENDIAN && sizeof (time_t) == 8)
330     {
331       /* Decode the transition times, stored as 8-byte integers in
332          network (big-endian) byte order.  */
333       for (i = 0; i < num_transitions; ++i)
334         transitions[i] = decode64 ((char *) transitions + i * 8);
335     }
336
337   for (i = 0; i < num_types; ++i)
338     {
339       unsigned char x[4];
340       int c;
341       if (__builtin_expect (__fread_unlocked (x, 1,
342                                               sizeof (x), f) != sizeof (x),
343                             0))
344         goto lose;
345       c = getc_unlocked (f);
346       if (__glibc_unlikely ((unsigned int) c > 1u))
347         goto lose;
348       types[i].isdst = c;
349       c = getc_unlocked (f);
350       if (__glibc_unlikely ((size_t) c > chars))
351         /* Bogus index in data file.  */
352         goto lose;
353       types[i].idx = c;
354       types[i].offset = (long int) decode (x);
355     }
356
357   if (__glibc_unlikely (__fread_unlocked (zone_names, 1, chars, f) != chars))
358     goto lose;
359
360   for (i = 0; i < num_leaps; ++i)
361     {
362       unsigned char x[8];
363       if (__builtin_expect (__fread_unlocked (x, 1, trans_width, f)
364                             != trans_width, 0))
365         goto lose;
366       if (sizeof (time_t) == 4 || trans_width == 4)
367         leaps[i].transition = (time_t) decode (x);
368       else
369         leaps[i].transition = (time_t) decode64 (x);
370
371       if (__glibc_unlikely (__fread_unlocked (x, 1, 4, f) != 4))
372         goto lose;
373       leaps[i].change = (long int) decode (x);
374     }
375
376   for (i = 0; i < num_isstd; ++i)
377     {
378       int c = getc_unlocked (f);
379       if (__glibc_unlikely (c == EOF))
380         goto lose;
381       types[i].isstd = c != 0;
382     }
383   while (i < num_types)
384     types[i++].isstd = 0;
385
386   for (i = 0; i < num_isgmt; ++i)
387     {
388       int c = getc_unlocked (f);
389       if (__glibc_unlikely (c == EOF))
390         goto lose;
391       types[i].isgmt = c != 0;
392     }
393   while (i < num_types)
394     types[i++].isgmt = 0;
395
396   /* Read the POSIX TZ-style information if possible.  */
397   if (sizeof (time_t) == 8 && tzspec != NULL)
398     {
399       /* Skip over the newline first.  */
400       if (getc_unlocked (f) != '\n'
401           || (__fread_unlocked (tzspec, 1, tzspec_len - 1, f)
402               != tzspec_len - 1))
403         tzspec = NULL;
404       else
405         tzspec[tzspec_len - 1] = '\0';
406     }
407   else if (sizeof (time_t) == 4 && tzhead.tzh_version[0] != '\0')
408     {
409       /* Get the TZ string.  */
410       if (__builtin_expect (__fread_unlocked ((void *) &tzhead,
411                                               sizeof (tzhead), 1, f) != 1, 0)
412           || (memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic))
413               != 0))
414         goto lose;
415
416       size_t num_transitions2 = (size_t) decode (tzhead.tzh_timecnt);
417       size_t num_types2 = (size_t) decode (tzhead.tzh_typecnt);
418       size_t chars2 = (size_t) decode (tzhead.tzh_charcnt);
419       size_t num_leaps2 = (size_t) decode (tzhead.tzh_leapcnt);
420       size_t num_isstd2 = (size_t) decode (tzhead.tzh_ttisstdcnt);
421       size_t num_isgmt2 = (size_t) decode (tzhead.tzh_ttisgmtcnt);
422
423       /* Position the stream before the second header.  */
424       size_t to_skip = (num_transitions2 * (8 + 1)
425                         + num_types2 * 6
426                         + chars2
427                         + num_leaps2 * 12
428                         + num_isstd2
429                         + num_isgmt2);
430       off_t off;
431       if (fseek (f, to_skip, SEEK_CUR) != 0
432           || (off = __ftello (f)) < 0
433           || st.st_size < off + 2)
434         goto lose;
435
436       tzspec_len = st.st_size - off - 1;
437       char *tzstr = alloca (tzspec_len);
438       if (getc_unlocked (f) != '\n'
439           || (__fread_unlocked (tzstr, 1, tzspec_len - 1, f)
440               != tzspec_len - 1))
441         goto lose;
442       tzstr[tzspec_len - 1] = '\0';
443       tzspec = __tzstring (tzstr);
444     }
445
446   /* Don't use an empty TZ string.  */
447   if (tzspec != NULL && tzspec[0] == '\0')
448     tzspec = NULL;
449
450   fclose (f);
451
452   /* First "register" all timezone names.  */
453   for (i = 0; i < num_types; ++i)
454     (void) __tzstring (&zone_names[types[i].idx]);
455
456   /* Find the standard and daylight time offsets used by the rule file.
457      We choose the offsets in the types of each flavor that are
458      transitioned to earliest in time.  */
459   __tzname[0] = NULL;
460   __tzname[1] = NULL;
461   for (i = num_transitions; i > 0; )
462     {
463       int type = type_idxs[--i];
464       int dst = types[type].isdst;
465
466       if (__tzname[dst] == NULL)
467         {
468           int idx = types[type].idx;
469
470           __tzname[dst] = __tzstring (&zone_names[idx]);
471
472           if (__tzname[1 - dst] != NULL)
473             break;
474         }
475     }
476   if (__tzname[0] == NULL)
477     {
478       /* This should only happen if there are no transition rules.
479          In this case there should be only one single type.  */
480       assert (num_types == 1);
481       __tzname[0] = __tzstring (zone_names);
482     }
483   if (__tzname[1] == NULL)
484     __tzname[1] = __tzname[0];
485
486   compute_tzname_max (chars);
487
488   if (num_transitions == 0)
489     /* Use the first rule (which should also be the only one).  */
490     rule_stdoff = rule_dstoff = types[0].offset;
491   else
492     {
493       int stdoff_set = 0, dstoff_set = 0;
494       rule_stdoff = rule_dstoff = 0;
495       i = num_transitions - 1;
496       do
497         {
498           if (!stdoff_set && !types[type_idxs[i]].isdst)
499             {
500               stdoff_set = 1;
501               rule_stdoff = types[type_idxs[i]].offset;
502             }
503           else if (!dstoff_set && types[type_idxs[i]].isdst)
504             {
505               dstoff_set = 1;
506               rule_dstoff = types[type_idxs[i]].offset;
507             }
508           if (stdoff_set && dstoff_set)
509             break;
510         }
511       while (i-- > 0);
512
513       if (!dstoff_set)
514         rule_dstoff = rule_stdoff;
515     }
516
517   __daylight = rule_stdoff != rule_dstoff;
518   __timezone = -rule_stdoff;
519
520  done:
521   __use_tzfile = 1;
522   free (new);
523   return;
524
525  lose:
526   fclose (f);
527  ret_free_transitions:
528   free (new);
529   free ((void *) transitions);
530   transitions = NULL;
531 }
532 \f
533 /* The user specified a hand-made timezone, but not its DST rules.
534    We will use the names and offsets from the user, and the rules
535    from the TZDEFRULES file.  */
536
537 void
538 __tzfile_default (const char *std, const char *dst,
539                   long int stdoff, long int dstoff)
540 {
541   size_t stdlen = strlen (std) + 1;
542   size_t dstlen = strlen (dst) + 1;
543   size_t i;
544   int isdst;
545   char *cp;
546
547   __tzfile_read (TZDEFRULES, stdlen + dstlen, &cp);
548   if (!__use_tzfile)
549     return;
550
551   if (num_types < 2)
552     {
553       __use_tzfile = 0;
554       return;
555     }
556
557   /* Ignore the zone names read from the file and use the given ones
558      instead.  */
559   __mempcpy (__mempcpy (cp, std, stdlen), dst, dstlen);
560   zone_names = cp;
561
562   /* Now there are only two zones, regardless of what the file contained.  */
563   num_types = 2;
564
565   /* Now correct the transition times for the user-specified standard and
566      daylight offsets from GMT.  */
567   isdst = 0;
568   for (i = 0; i < num_transitions; ++i)
569     {
570       struct ttinfo *trans_type = &types[type_idxs[i]];
571
572       /* We will use only types 0 (standard) and 1 (daylight).
573          Fix up this transition to point to whichever matches
574          the flavor of its original type.  */
575       type_idxs[i] = trans_type->isdst;
576
577       if (trans_type->isgmt)
578         /* The transition time is in GMT.  No correction to apply.  */ ;
579       else if (isdst && !trans_type->isstd)
580         /* The type says this transition is in "local wall clock time", and
581            wall clock time as of the previous transition was DST.  Correct
582            for the difference between the rule's DST offset and the user's
583            DST offset.  */
584         transitions[i] += dstoff - rule_dstoff;
585       else
586         /* This transition is in "local wall clock time", and wall clock
587            time as of this iteration is non-DST.  Correct for the
588            difference between the rule's standard offset and the user's
589            standard offset.  */
590         transitions[i] += stdoff - rule_stdoff;
591
592       /* The DST state of "local wall clock time" for the next iteration is
593          as specified by this transition.  */
594       isdst = trans_type->isdst;
595     }
596
597   /* Now that we adjusted the transitions to the requested offsets,
598      reset the rule_stdoff and rule_dstoff values appropriately.  They
599      are used elsewhere.  */
600   rule_stdoff = stdoff;
601   rule_dstoff = dstoff;
602
603   /* Reset types 0 and 1 to describe the user's settings.  */
604   types[0].idx = 0;
605   types[0].offset = stdoff;
606   types[0].isdst = 0;
607   types[1].idx = stdlen;
608   types[1].offset = dstoff;
609   types[1].isdst = 1;
610
611   /* Reset the zone names to point to the user's names.  */
612   __tzname[0] = (char *) std;
613   __tzname[1] = (char *) dst;
614
615   /* Set the timezone.  */
616   __timezone = -types[0].offset;
617
618   compute_tzname_max (stdlen + dstlen);
619 }
620 \f
621 void
622 __tzfile_compute (time_t timer, int use_localtime,
623                   long int *leap_correct, int *leap_hit,
624                   struct tm *tp)
625 {
626   size_t i;
627
628   if (use_localtime)
629     {
630       __tzname[0] = NULL;
631       __tzname[1] = NULL;
632
633       if (__glibc_unlikely (num_transitions == 0 || timer < transitions[0]))
634         {
635           /* TIMER is before any transition (or there are no transitions).
636              Choose the first non-DST type
637              (or the first if they're all DST types).  */
638           i = 0;
639           while (i < num_types && types[i].isdst)
640             {
641               if (__tzname[1] == NULL)
642                 __tzname[1] = __tzstring (&zone_names[types[i].idx]);
643
644               ++i;
645             }
646
647           if (i == num_types)
648             i = 0;
649           __tzname[0] = __tzstring (&zone_names[types[i].idx]);
650           if (__tzname[1] == NULL)
651             {
652               size_t j = i;
653               while (j < num_types)
654                 if (types[j].isdst)
655                   {
656                     __tzname[1] = __tzstring (&zone_names[types[j].idx]);
657                     break;
658                   }
659                 else
660                   ++j;
661             }
662         }
663       else if (__glibc_unlikely (timer >= transitions[num_transitions - 1]))
664         {
665           if (__glibc_unlikely (tzspec == NULL))
666             {
667             use_last:
668               i = num_transitions;
669               goto found;
670             }
671
672           /* Parse the POSIX TZ-style string.  */
673           __tzset_parse_tz (tzspec);
674
675           /* Convert to broken down structure.  If this fails do not
676              use the string.  */
677           if (__glibc_unlikely (! __offtime (&timer, 0, tp)))
678             goto use_last;
679
680           /* Use the rules from the TZ string to compute the change.  */
681           __tz_compute (timer, tp, 1);
682
683           /* If tzspec comes from posixrules loaded by __tzfile_default,
684              override the STD and DST zone names with the ones user
685              requested in TZ envvar.  */
686           if (__glibc_unlikely (zone_names == (char *) &leaps[num_leaps]))
687             {
688               assert (num_types == 2);
689               __tzname[0] = __tzstring (zone_names);
690               __tzname[1] = __tzstring (&zone_names[strlen (zone_names) + 1]);
691             }
692
693           goto leap;
694         }
695       else
696         {
697           /* Find the first transition after TIMER, and
698              then pick the type of the transition before it.  */
699           size_t lo = 0;
700           size_t hi = num_transitions - 1;
701           /* Assume that DST is changing twice a year and guess initial
702              search spot from it.
703              Half of a gregorian year has on average 365.2425 * 86400 / 2
704              = 15778476 seconds.  */
705           i = (transitions[num_transitions - 1] - timer) / 15778476;
706           if (i < num_transitions)
707             {
708               i = num_transitions - 1 - i;
709               if (timer < transitions[i])
710                 {
711                   if (i < 10 || timer >= transitions[i - 10])
712                     {
713                       /* Linear search.  */
714                       while (timer < transitions[i - 1])
715                         --i;
716                       goto found;
717                     }
718                   hi = i - 10;
719                 }
720               else
721                 {
722                   if (i + 10 >= num_transitions || timer < transitions[i + 10])
723                     {
724                       /* Linear search.  */
725                       while (timer >= transitions[i])
726                         ++i;
727                       goto found;
728                     }
729                   lo = i + 10;
730                 }
731             }
732
733           /* Binary search.  */
734           /* assert (timer >= transitions[lo] && timer < transitions[hi]); */
735           while (lo + 1 < hi)
736             {
737               i = (lo + hi) / 2;
738               if (timer < transitions[i])
739                 hi = i;
740               else
741                 lo = i;
742             }
743           i = hi;
744
745         found:
746           /* assert (timer >= transitions[i - 1]
747              && (i == num_transitions || timer < transitions[i])); */
748           __tzname[types[type_idxs[i - 1]].isdst]
749             = __tzstring (&zone_names[types[type_idxs[i - 1]].idx]);
750           size_t j = i;
751           while (j < num_transitions)
752             {
753               int type = type_idxs[j];
754               int dst = types[type].isdst;
755               int idx = types[type].idx;
756
757               if (__tzname[dst] == NULL)
758                 {
759                   __tzname[dst] = __tzstring (&zone_names[idx]);
760
761                   if (__tzname[1 - dst] != NULL)
762                     break;
763                 }
764
765               ++j;
766             }
767
768           if (__glibc_unlikely (__tzname[0] == NULL))
769             __tzname[0] = __tzname[1];
770
771           i = type_idxs[i - 1];
772         }
773
774       struct ttinfo *info = &types[i];
775       __daylight = rule_stdoff != rule_dstoff;
776       __timezone = -rule_stdoff;
777
778       if (__tzname[0] == NULL)
779         {
780           /* This should only happen if there are no transition rules.
781              In this case there should be only one single type.  */
782           assert (num_types == 1);
783           __tzname[0] = __tzstring (zone_names);
784         }
785       if (__tzname[1] == NULL)
786         /* There is no daylight saving time.  */
787         __tzname[1] = __tzname[0];
788       tp->tm_isdst = info->isdst;
789       assert (strcmp (&zone_names[info->idx], __tzname[tp->tm_isdst]) == 0);
790       tp->tm_zone = __tzname[tp->tm_isdst];
791       tp->tm_gmtoff = info->offset;
792     }
793
794  leap:
795   *leap_correct = 0L;
796   *leap_hit = 0;
797
798   /* Find the last leap second correction transition time before TIMER.  */
799   i = num_leaps;
800   do
801     if (i-- == 0)
802       return;
803   while (timer < leaps[i].transition);
804
805   /* Apply its correction.  */
806   *leap_correct = leaps[i].change;
807
808   if (timer == leaps[i].transition && /* Exactly at the transition time.  */
809       ((i == 0 && leaps[i].change > 0) ||
810        leaps[i].change > leaps[i - 1].change))
811     {
812       *leap_hit = 1;
813       while (i > 0
814              && leaps[i].transition == leaps[i - 1].transition + 1
815              && leaps[i].change == leaps[i - 1].change + 1)
816         {
817           ++*leap_hit;
818           --i;
819         }
820     }
821 }
822 \f
823 static void
824 internal_function
825 compute_tzname_max (size_t chars)
826 {
827   const char *p;
828
829   p = zone_names;
830   do
831     {
832       const char *start = p;
833       while (*p != '\0')
834         ++p;
835       if ((size_t) (p - start) > __tzname_cur_max)
836         __tzname_cur_max = p - start;
837     }
838   while (++p < &zone_names[chars]);
839 }