(root)/
glibc-2.38/
time/
tzfile.c
       1  /* Copyright (C) 1991-2023 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     <https://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  #include <alloc_buffer.h>
      29  #include <set-freeres.h>
      30  
      31  #include <timezone/tzfile.h>
      32  
      33  int __use_tzfile;
      34  static dev_t tzfile_dev;
      35  static ino64_t tzfile_ino;
      36  static __time64_t tzfile_mtime;
      37  
      38  struct ttinfo
      39    {
      40      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.  */
      45    };
      46  
      47  struct leap
      48    {
      49      __time64_t transition;	/* Time the transition takes effect.  */
      50      long int change;		/* Seconds of correction to apply.  */
      51    };
      52  
      53  static size_t num_transitions;
      54  static __time64_t *transitions;
      55  static unsigned char *type_idxs;
      56  static size_t num_types;
      57  static struct ttinfo *types;
      58  static char *zone_names;
      59  static long int rule_stdoff;
      60  static long int rule_dstoff;
      61  static size_t num_leaps;
      62  static struct leap *leaps;
      63  static char *tzspec;
      64  
      65  /* Used to restore the daylight variable during time conversion, as if
      66     tzset had been called.  */
      67  static int daylight_saved;
      68  
      69  #include <endian.h>
      70  #include <byteswap.h>
      71  
      72  /* Decode the four bytes at PTR as a signed integer in network byte order.  */
      73  static inline int
      74  __attribute ((always_inline))
      75  decode (const void *ptr)
      76  {
      77    if (BYTE_ORDER == BIG_ENDIAN && sizeof (int) == 4)
      78      return *(const int *) ptr;
      79    if (sizeof (int) == 4)
      80      return bswap_32 (*(const int *) ptr);
      81  
      82    const unsigned char *p = ptr;
      83    int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0;
      84  
      85    result = (result << 8) | *p++;
      86    result = (result << 8) | *p++;
      87    result = (result << 8) | *p++;
      88    result = (result << 8) | *p++;
      89  
      90    return result;
      91  }
      92  
      93  
      94  static inline int64_t
      95  __attribute ((always_inline))
      96  decode64 (const void *ptr)
      97  {
      98    if ((BYTE_ORDER == BIG_ENDIAN))
      99      return *(const int64_t *) ptr;
     100  
     101    return bswap_64 (*(const int64_t *) ptr);
     102  }
     103  
     104  
     105  void
     106  __tzfile_read (const char *file, size_t extra, char **extrap)
     107  {
     108    static const char default_tzdir[] = TZDIR;
     109    size_t num_isstd, num_isgmt;
     110    FILE *f;
     111    struct tzhead tzhead;
     112    size_t chars;
     113    size_t i;
     114    int was_using_tzfile = __use_tzfile;
     115    int trans_width = 4;
     116    char *new = NULL;
     117  
     118    _Static_assert (sizeof (__time64_t) == 8,
     119  		  "__time64_t must be eight bytes");
     120  
     121    __use_tzfile = 0;
     122  
     123    if (file == NULL)
     124      /* No user specification; use the site-wide default.  */
     125      file = TZDEFAULT;
     126    else if (*file == '\0')
     127      /* User specified the empty string; use UTC with no leap seconds.  */
     128      goto ret_free_transitions;
     129    else
     130      {
     131        /* We must not allow to read an arbitrary file in a setuid
     132  	 program.  So we fail for any file which is not in the
     133  	 directory hierarchy starting at TZDIR
     134  	 and which is not the system wide default TZDEFAULT.  */
     135        if (__libc_enable_secure
     136  	  && ((*file == '/'
     137  	       && memcmp (file, TZDEFAULT, sizeof TZDEFAULT)
     138  	       && memcmp (file, default_tzdir, sizeof (default_tzdir) - 1))
     139  	      || strstr (file, "../") != NULL))
     140  	/* This test is certainly a bit too restrictive but it should
     141  	   catch all critical cases.  */
     142  	goto ret_free_transitions;
     143      }
     144  
     145    if (*file != '/')
     146      {
     147        const char *tzdir;
     148  
     149        tzdir = getenv ("TZDIR");
     150        if (tzdir == NULL || *tzdir == '\0')
     151  	tzdir = default_tzdir;
     152        if (__asprintf (&new, "%s/%s", tzdir, file) == -1)
     153  	goto ret_free_transitions;
     154        file = new;
     155      }
     156  
     157    /* If we were already using tzfile, check whether the file changed.  */
     158    struct __stat64_t64 st;
     159    if (was_using_tzfile
     160        && __stat64_time64 (file, &st) == 0
     161        && tzfile_ino == st.st_ino && tzfile_dev == st.st_dev
     162        && tzfile_mtime == st.st_mtime)
     163      goto done;  /* Nothing to do.  */
     164  
     165    /* Note the file is opened with cancellation in the I/O functions
     166       disabled and if available FD_CLOEXEC set.  */
     167    f = fopen (file, "rce");
     168    if (f == NULL)
     169      goto ret_free_transitions;
     170  
     171    /* Get information about the file we are actually using.  */
     172    if (__fstat64_time64 (__fileno (f), &st) != 0)
     173      goto lose;
     174  
     175    free ((void *) transitions);
     176    transitions = NULL;
     177  
     178    /* Remember the inode and device number and modification time.  */
     179    tzfile_dev = st.st_dev;
     180    tzfile_ino = st.st_ino;
     181    tzfile_mtime = st.st_mtime;
     182  
     183    /* No threads reading this stream.  */
     184    __fsetlocking (f, FSETLOCKING_BYCALLER);
     185  
     186   read_again:
     187    if (__builtin_expect (__fread_unlocked ((void *) &tzhead, sizeof (tzhead),
     188  					  1, f) != 1, 0)
     189        || memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic)) != 0)
     190      goto lose;
     191  
     192    num_transitions = (size_t) decode (tzhead.tzh_timecnt);
     193    num_types = (size_t) decode (tzhead.tzh_typecnt);
     194    chars = (size_t) decode (tzhead.tzh_charcnt);
     195    num_leaps = (size_t) decode (tzhead.tzh_leapcnt);
     196    num_isstd = (size_t) decode (tzhead.tzh_ttisstdcnt);
     197    num_isgmt = (size_t) decode (tzhead.tzh_ttisutcnt);
     198  
     199    if (__glibc_unlikely (num_isstd > num_types || num_isgmt > num_types))
     200      goto lose;
     201  
     202    if (trans_width == 4 && tzhead.tzh_version[0] != '\0')
     203      {
     204        /* We use the 8-byte format.  */
     205        trans_width = 8;
     206  
     207        /* Position the stream before the second header.  */
     208        size_t to_skip = (num_transitions * (4 + 1)
     209  			+ num_types * 6
     210  			+ chars
     211  			+ num_leaps * 8
     212  			+ num_isstd
     213  			+ num_isgmt);
     214        if (fseek (f, to_skip, SEEK_CUR) != 0)
     215  	goto lose;
     216  
     217        goto read_again;
     218      }
     219  
     220    /* Compute the size of the POSIX time zone specification in the
     221       file.  */
     222    size_t tzspec_len;
     223    if (trans_width == 8)
     224      {
     225        off_t rem = st.st_size - __ftello (f);
     226        if (__builtin_expect (rem < 0
     227  			    || (size_t) rem < (num_transitions * (8 + 1)
     228  					       + num_types * 6
     229  					       + chars), 0))
     230  	goto lose;
     231        tzspec_len = (size_t) rem - (num_transitions * (8 + 1)
     232  				   + num_types * 6
     233  				   + chars);
     234        if (__builtin_expect (num_leaps > SIZE_MAX / 12
     235  			    || tzspec_len < num_leaps * 12, 0))
     236  	goto lose;
     237        tzspec_len -= num_leaps * 12;
     238        if (__glibc_unlikely (tzspec_len < num_isstd))
     239  	goto lose;
     240        tzspec_len -= num_isstd;
     241        if (__glibc_unlikely (tzspec_len == 0 || tzspec_len - 1 < num_isgmt))
     242  	goto lose;
     243        tzspec_len -= num_isgmt + 1;
     244        if (tzspec_len == 0)
     245  	goto lose;
     246      }
     247    else
     248      tzspec_len = 0;
     249  
     250    /* The file is parsed into a single heap allocation, comprising of
     251       the following arrays:
     252  
     253       __time64_t transitions[num_transitions];
     254       struct leap leaps[num_leaps];
     255       struct ttinfo types[num_types];
     256       unsigned char type_idxs[num_types];
     257       char zone_names[chars];
     258       char tzspec[tzspec_len];
     259       char extra_array[extra]; // Stored into *pextras if requested.
     260  
     261       The piece-wise allocations from buf below verify that no
     262       overflow/wraparound occurred in these computations.
     263  
     264       The order of the suballocations is important for alignment
     265       purposes.  __time64_t outside a struct may require more alignment
     266       then inside a struct on some architectures, so it must come
     267       first. */
     268    _Static_assert (__alignof (__time64_t) >= __alignof (struct leap),
     269  		  "alignment of __time64_t");
     270    _Static_assert (__alignof (struct leap) >= __alignof (struct ttinfo),
     271  		  "alignment of struct leap");
     272    struct alloc_buffer buf;
     273    {
     274      size_t total_size = (num_transitions * sizeof (__time64_t)
     275  			 + num_leaps * sizeof (struct leap)
     276  			 + num_types * sizeof (struct ttinfo)
     277  			 + num_transitions /* type_idxs */
     278  			 + chars /* zone_names */
     279  			 + tzspec_len + extra);
     280      transitions = malloc (total_size);
     281      if (transitions == NULL)
     282        goto lose;
     283      buf = alloc_buffer_create (transitions, total_size);
     284    }
     285  
     286    /* The address of the first allocation is already stored in the
     287       pointer transitions.  */
     288    (void) alloc_buffer_alloc_array (&buf, __time64_t, num_transitions);
     289    leaps = alloc_buffer_alloc_array (&buf, struct leap, num_leaps);
     290    types = alloc_buffer_alloc_array (&buf, struct ttinfo, num_types);
     291    type_idxs = alloc_buffer_alloc_array (&buf, unsigned char, num_transitions);
     292    zone_names = alloc_buffer_alloc_array (&buf, char, chars);
     293    if (trans_width == 8)
     294      tzspec = alloc_buffer_alloc_array (&buf, char, tzspec_len);
     295    else
     296      tzspec = NULL;
     297    if (extra > 0)
     298      *extrap = alloc_buffer_alloc_array (&buf, char, extra);
     299    if (alloc_buffer_has_failed (&buf))
     300      goto lose;
     301  
     302    if (__glibc_unlikely (__fread_unlocked (transitions, trans_width,
     303  					  num_transitions, f)
     304  			!= num_transitions)
     305        || __glibc_unlikely (__fread_unlocked (type_idxs, 1, num_transitions, f)
     306  			   != num_transitions))
     307  	goto lose;
     308  
     309    /* Check for bogus indices in the data file, so we can hereafter
     310       safely use type_idxs[T] as indices into `types' and never crash.  */
     311    for (i = 0; i < num_transitions; ++i)
     312      if (__glibc_unlikely (type_idxs[i] >= num_types))
     313        goto lose;
     314  
     315    if (trans_width == 4)
     316      {
     317        /* Decode the transition times, stored as 4-byte integers in
     318  	 network (big-endian) byte order.  We work from the end of the
     319  	 array so as not to clobber the next element to be
     320  	 processed.  */
     321        i = num_transitions;
     322        while (i-- > 0)
     323  	transitions[i] = decode ((char *) transitions + i * 4);
     324      }
     325    else if (BYTE_ORDER != BIG_ENDIAN)
     326      {
     327        /* Decode the transition times, stored as 8-byte integers in
     328  	 network (big-endian) byte order.  */
     329        for (i = 0; i < num_transitions; ++i)
     330  	transitions[i] = decode64 ((char *) transitions + i * 8);
     331      }
     332  
     333    for (i = 0; i < num_types; ++i)
     334      {
     335        unsigned char x[4];
     336        int c;
     337        if (__builtin_expect (__fread_unlocked (x, 1,
     338  					      sizeof (x), f) != sizeof (x),
     339  			    0))
     340  	goto lose;
     341        c = __getc_unlocked (f);
     342        if (__glibc_unlikely ((unsigned int) c > 1u))
     343  	goto lose;
     344        types[i].isdst = c;
     345        c = __getc_unlocked (f);
     346        if (__glibc_unlikely ((size_t) c > chars))
     347  	/* Bogus index in data file.  */
     348  	goto lose;
     349        types[i].idx = c;
     350        types[i].offset = decode (x);
     351      }
     352  
     353    if (__glibc_unlikely (__fread_unlocked (zone_names, 1, chars, f) != chars))
     354      goto lose;
     355  
     356    for (i = 0; i < num_leaps; ++i)
     357      {
     358        unsigned char x[8];
     359        if (__builtin_expect (__fread_unlocked (x, 1, trans_width, f)
     360  			    != trans_width, 0))
     361  	goto lose;
     362        if (trans_width == 4)
     363  	leaps[i].transition = decode (x);
     364        else
     365  	leaps[i].transition = decode64 (x);
     366  
     367        if (__glibc_unlikely (__fread_unlocked (x, 1, 4, f) != 4))
     368  	goto lose;
     369        leaps[i].change = (long int) decode (x);
     370      }
     371  
     372    for (i = 0; i < num_isstd; ++i)
     373      {
     374        int c = __getc_unlocked (f);
     375        if (__glibc_unlikely (c == EOF))
     376  	goto lose;
     377        types[i].isstd = c != 0;
     378      }
     379    while (i < num_types)
     380      types[i++].isstd = 0;
     381  
     382    for (i = 0; i < num_isgmt; ++i)
     383      {
     384        int c = __getc_unlocked (f);
     385        if (__glibc_unlikely (c == EOF))
     386  	goto lose;
     387        types[i].isgmt = c != 0;
     388      }
     389    while (i < num_types)
     390      types[i++].isgmt = 0;
     391  
     392    /* Read the POSIX TZ-style information if possible.  */
     393    if (tzspec != NULL)
     394      {
     395        assert (tzspec_len > 0);
     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 time zone abbreviations.  */
     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's usually only one single type, unless
     440  	 e.g. the data file has a truncated time-range.  */
     441        __tzname[0] = __tzstring (zone_names);
     442      }
     443    if (__tzname[1] == NULL)
     444      __tzname[1] = __tzname[0];
     445  
     446    daylight_saved = 0;
     447    if (num_transitions == 0)
     448      /* Use the first rule (which should also be the only one).  */
     449      rule_stdoff = rule_dstoff = types[0].offset;
     450    else
     451      {
     452        rule_stdoff = 0;
     453  
     454        /* Search for the last rule with a standard time offset.  This
     455  	 will be used for the global timezone variable.  */
     456        i = num_transitions - 1;
     457        do
     458  	if (!types[type_idxs[i]].isdst)
     459  	  {
     460  	    rule_stdoff = types[type_idxs[i]].offset;
     461  	    break;
     462  	  }
     463  	else
     464  	  daylight_saved = 1;
     465        while (i-- > 0);
     466  
     467        /* Keep searching to see if there is a DST rule.  This
     468  	 information will be used to set the global daylight
     469  	 variable.  */
     470        while (i-- > 0 && !daylight_saved)
     471  	daylight_saved = types[type_idxs[i]].isdst;
     472      }
     473  
     474    __daylight = daylight_saved;
     475    __timezone = -rule_stdoff;
     476  
     477   done:
     478    __use_tzfile = 1;
     479    free (new);
     480    return;
     481  
     482   lose:
     483    fclose (f);
     484   ret_free_transitions:
     485    free (new);
     486    free ((void *) transitions);
     487    transitions = NULL;
     488  }
     489  
     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.  */
     493  
     494  void
     495  __tzfile_default (const char *std, const char *dst,
     496  		  int stdoff, int dstoff)
     497  {
     498    size_t stdlen = strlen (std) + 1;
     499    size_t dstlen = strlen (dst) + 1;
     500    size_t i;
     501    int isdst;
     502    char *cp;
     503  
     504    __tzfile_read (TZDEFRULES, stdlen + dstlen, &cp);
     505    if (!__use_tzfile)
     506      return;
     507  
     508    if (num_types < 2)
     509      {
     510        __use_tzfile = 0;
     511        return;
     512      }
     513  
     514    /* Ignore the zone names read from the file and use the given ones
     515       instead.  */
     516    __mempcpy (__mempcpy (cp, std, stdlen), dst, dstlen);
     517    zone_names = cp;
     518  
     519    /* Now there are only two zones, regardless of what the file contained.  */
     520    num_types = 2;
     521  
     522    /* Now correct the transition times for the user-specified standard and
     523       daylight offsets from GMT.  */
     524    isdst = 0;
     525    for (i = 0; i < num_transitions; ++i)
     526      {
     527        struct ttinfo *trans_type = &types[type_idxs[i]];
     528  
     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;
     533  
     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
     540  	   DST offset.  */
     541  	transitions[i] += dstoff - rule_dstoff;
     542        else
     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
     546  	   standard offset.  */
     547  	transitions[i] += stdoff - rule_stdoff;
     548  
     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;
     552      }
     553  
     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;
     559  
     560    /* Reset types 0 and 1 to describe the user's settings.  */
     561    types[0].idx = 0;
     562    types[0].offset = stdoff;
     563    types[0].isdst = 0;
     564    types[1].idx = stdlen;
     565    types[1].offset = dstoff;
     566    types[1].isdst = 1;
     567  
     568    /* Reset time zone abbreviations to point to the user's abbreviations.  */
     569    __tzname[0] = (char *) std;
     570    __tzname[1] = (char *) dst;
     571  
     572    /* Set the timezone.  */
     573    __timezone = -types[0].offset;
     574  
     575    /* Invalidate the tzfile attribute cache to force rereading
     576       TZDEFRULES the next time it is used.  */
     577    tzfile_dev = 0;
     578    tzfile_ino = 0;
     579    tzfile_mtime = 0;
     580  }
     581  
     582  void
     583  __tzfile_compute (__time64_t timer, int use_localtime,
     584  		  long int *leap_correct, int *leap_hit,
     585  		  struct tm *tp)
     586  {
     587    size_t i;
     588  
     589    if (use_localtime)
     590      {
     591        __tzname[0] = NULL;
     592        __tzname[1] = NULL;
     593  
     594        if (__glibc_unlikely (num_transitions == 0 || timer < transitions[0]))
     595  	{
     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).  */
     599  	  i = 0;
     600  	  while (i < num_types && types[i].isdst)
     601  	    {
     602  	      if (__tzname[1] == NULL)
     603  		__tzname[1] = __tzstring (&zone_names[types[i].idx]);
     604  
     605  	      ++i;
     606  	    }
     607  
     608  	  if (i == num_types)
     609  	    i = 0;
     610  	  __tzname[0] = __tzstring (&zone_names[types[i].idx]);
     611  	  if (__tzname[1] == NULL)
     612  	    {
     613  	      size_t j = i;
     614  	      while (j < num_types)
     615  		if (types[j].isdst)
     616  		  {
     617  		    __tzname[1] = __tzstring (&zone_names[types[j].idx]);
     618  		    break;
     619  		  }
     620  		else
     621  		  ++j;
     622  	    }
     623  	}
     624        else if (__glibc_unlikely (timer >= transitions[num_transitions - 1]))
     625  	{
     626  	  if (__glibc_unlikely (tzspec == NULL))
     627  	    {
     628  	    use_last:
     629  	      i = num_transitions;
     630  	      goto found;
     631  	    }
     632  
     633  	  /* Parse the POSIX TZ-style string.  */
     634  	  __tzset_parse_tz (tzspec);
     635  
     636  	  /* Convert to broken down structure.  If this fails do not
     637  	     use the string.  */
     638  	  if (__glibc_unlikely (! __offtime (timer, 0, tp)))
     639  	    goto use_last;
     640  
     641  	  /* Use the rules from the TZ string to compute the change.  */
     642  	  __tz_compute (timer, tp, 1);
     643  
     644  	  /* If tzspec comes from posixrules loaded by __tzfile_default,
     645  	     override the STD and DST zone names with the ones user
     646  	     requested in TZ envvar.  */
     647  	  if (__glibc_unlikely (zone_names == (char *) &leaps[num_leaps]))
     648  	    {
     649  	      assert (num_types == 2);
     650  	      __tzname[0] = __tzstring (zone_names);
     651  	      __tzname[1] = __tzstring (&zone_names[strlen (zone_names) + 1]);
     652  	    }
     653  
     654  	  goto leap;
     655  	}
     656        else
     657  	{
     658  	  /* Find the first transition after TIMER, and
     659  	     then pick the type of the transition before it.  */
     660  	  size_t lo = 0;
     661  	  size_t hi = num_transitions - 1;
     662  	  /* Assume that DST is changing twice a year and guess
     663  	     initial search spot from it.  Half of a gregorian year
     664  	     has on average 365.2425 * 86400 / 2 = 15778476 seconds.
     665  	     The value i can be truncated if size_t is smaller than
     666  	     __time64_t, but this is harmless because it is just
     667  	     a guess.  */
     668  	  i = (transitions[num_transitions - 1] - timer) / 15778476;
     669  	  if (i < num_transitions)
     670  	    {
     671  	      i = num_transitions - 1 - i;
     672  	      if (timer < transitions[i])
     673  		{
     674  		  if (i < 10 || timer >= transitions[i - 10])
     675  		    {
     676  		      /* Linear search.  */
     677  		      while (timer < transitions[i - 1])
     678  			--i;
     679  		      goto found;
     680  		    }
     681  		  hi = i - 10;
     682  		}
     683  	      else
     684  		{
     685  		  if (i + 10 >= num_transitions || timer < transitions[i + 10])
     686  		    {
     687  		      /* Linear search.  */
     688  		      while (timer >= transitions[i])
     689  			++i;
     690  		      goto found;
     691  		    }
     692  		  lo = i + 10;
     693  		}
     694  	    }
     695  
     696  	  /* Binary search.  */
     697  	  /* assert (timer >= transitions[lo] && timer < transitions[hi]); */
     698  	  while (lo + 1 < hi)
     699  	    {
     700  	      i = (lo + hi) / 2;
     701  	      if (timer < transitions[i])
     702  		hi = i;
     703  	      else
     704  		lo = i;
     705  	    }
     706  	  i = hi;
     707  
     708  	found:
     709  	  /* assert (timer >= transitions[i - 1]
     710  	     && (i == num_transitions || timer < transitions[i])); */
     711  	  __tzname[types[type_idxs[i - 1]].isdst]
     712  	    = __tzstring (&zone_names[types[type_idxs[i - 1]].idx]);
     713  	  size_t j = i;
     714  	  while (j < num_transitions)
     715  	    {
     716  	      int type = type_idxs[j];
     717  	      int dst = types[type].isdst;
     718  	      int idx = types[type].idx;
     719  
     720  	      if (__tzname[dst] == NULL)
     721  		{
     722  		  __tzname[dst] = __tzstring (&zone_names[idx]);
     723  
     724  		  if (__tzname[1 - dst] != NULL)
     725  		    break;
     726  		}
     727  
     728  	      ++j;
     729  	    }
     730  
     731  	  if (__glibc_unlikely (__tzname[0] == NULL))
     732  	    __tzname[0] = __tzname[1];
     733  
     734  	  i = type_idxs[i - 1];
     735  	}
     736  
     737        struct ttinfo *info = &types[i];
     738        __daylight = daylight_saved;
     739        __timezone = -rule_stdoff;
     740  
     741        if (__tzname[0] == NULL)
     742  	{
     743  	  /* This should only happen if there are no transition rules.
     744  	     In this case there should be only one single type.  */
     745  	  assert (num_types == 1);
     746  	  __tzname[0] = __tzstring (zone_names);
     747  	}
     748        if (__tzname[1] == NULL)
     749  	/* There is no daylight saving time.  */
     750  	__tzname[1] = __tzname[0];
     751        tp->tm_isdst = info->isdst;
     752        assert (strcmp (&zone_names[info->idx], __tzname[tp->tm_isdst]) == 0);
     753        tp->tm_zone = __tzname[tp->tm_isdst];
     754        tp->tm_gmtoff = info->offset;
     755      }
     756  
     757   leap:
     758    *leap_correct = 0L;
     759    *leap_hit = 0;
     760  
     761    /* Find the last leap second correction transition time before TIMER.  */
     762    i = num_leaps;
     763    do
     764      if (i-- == 0)
     765        return;
     766    while (timer < leaps[i].transition);
     767  
     768    /* Apply its correction.  */
     769    *leap_correct = leaps[i].change;
     770  
     771    if (timer == leaps[i].transition /* Exactly at the transition time.  */
     772        && (leaps[i].change > (i == 0 ? 0 : leaps[i - 1].change)))
     773      {
     774        *leap_hit = 1;
     775        while (i > 0
     776  	     && leaps[i].transition == leaps[i - 1].transition + 1
     777  	     && leaps[i].change == leaps[i - 1].change + 1)
     778  	{
     779  	  ++*leap_hit;
     780  	  --i;
     781  	}
     782      }
     783  }
     784  
     785  weak_alias (transitions, __libc_tzfile_freemem_ptr)