Back to index

glibc  2.9
tzfile.c
Go to the documentation of this file.
00001 /* Copyright (C) 1991-1993,1995-2001,2003,2004,2006, 2007
00002    Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <assert.h>
00021 #include <limits.h>
00022 #include <stdio.h>
00023 #include <stdio_ext.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <time.h>
00027 #include <unistd.h>
00028 #include <sys/stat.h>
00029 
00030 #define       NOID
00031 #include <timezone/tzfile.h>
00032 
00033 int __use_tzfile;
00034 static dev_t tzfile_dev;
00035 static ino64_t tzfile_ino;
00036 static time_t tzfile_mtime;
00037 
00038 struct ttinfo
00039   {
00040     long int offset;        /* Seconds east of GMT.  */
00041     unsigned char isdst;    /* Used to set tm_isdst.  */
00042     unsigned char idx;             /* Index into `zone_names'.  */
00043     unsigned char isstd;    /* Transition times are in standard time.  */
00044     unsigned char isgmt;    /* Transition times are in GMT.  */
00045   };
00046 
00047 struct leap
00048   {
00049     time_t transition;             /* Time the transition takes effect.  */
00050     long int change;        /* Seconds of correction to apply.  */
00051   };
00052 
00053 static void compute_tzname_max (size_t) internal_function;
00054 
00055 static size_t num_transitions;
00056 libc_freeres_ptr (static time_t *transitions);
00057 static unsigned char *type_idxs;
00058 static size_t num_types;
00059 static struct ttinfo *types;
00060 static char *zone_names;
00061 static long int rule_stdoff;
00062 static long int rule_dstoff;
00063 static size_t num_leaps;
00064 static struct leap *leaps;
00065 static char *tzspec;
00066 
00067 #include <endian.h>
00068 #include <byteswap.h>
00069 
00070 /* Decode the four bytes at PTR as a signed integer in network byte order.  */
00071 static inline int
00072 __attribute ((always_inline))
00073 decode (const void *ptr)
00074 {
00075   if (BYTE_ORDER == BIG_ENDIAN && sizeof (int) == 4)
00076     return *(const int *) ptr;
00077   if (sizeof (int) == 4)
00078     return bswap_32 (*(const int *) ptr);
00079 
00080   const unsigned char *p = ptr;
00081   int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0;
00082 
00083   result = (result << 8) | *p++;
00084   result = (result << 8) | *p++;
00085   result = (result << 8) | *p++;
00086   result = (result << 8) | *p++;
00087 
00088   return result;
00089 }
00090 
00091 
00092 static inline int64_t
00093 __attribute ((always_inline))
00094 decode64 (const void *ptr)
00095 {
00096   if ((BYTE_ORDER == BIG_ENDIAN))
00097     return *(const int64_t *) ptr;
00098 
00099   return bswap_64 (*(const int64_t *) ptr);
00100 }
00101 
00102 
00103 void
00104 __tzfile_read (const char *file, size_t extra, char **extrap)
00105 {
00106   static const char default_tzdir[] = TZDIR;
00107   size_t num_isstd, num_isgmt;
00108   register FILE *f;
00109   struct tzhead tzhead;
00110   size_t chars;
00111   register size_t i;
00112   size_t total_size;
00113   size_t types_idx;
00114   size_t leaps_idx;
00115   int was_using_tzfile = __use_tzfile;
00116   int trans_width = 4;
00117   size_t tzspec_len;
00118 
00119   if (sizeof (time_t) != 4 && sizeof (time_t) != 8)
00120     abort ();
00121 
00122   __use_tzfile = 0;
00123 
00124   if (file == NULL)
00125     /* No user specification; use the site-wide default.  */
00126     file = TZDEFAULT;
00127   else if (*file == '\0')
00128     /* User specified the empty string; use UTC with no leap seconds.  */
00129     goto ret_free_transitions;
00130   else
00131     {
00132       /* We must not allow to read an arbitrary file in a setuid
00133         program.  So we fail for any file which is not in the
00134         directory hierachy starting at TZDIR
00135         and which is not the system wide default TZDEFAULT.  */
00136       if (__libc_enable_secure
00137          && ((*file == '/'
00138               && memcmp (file, TZDEFAULT, sizeof TZDEFAULT)
00139               && memcmp (file, default_tzdir, sizeof (default_tzdir) - 1))
00140              || strstr (file, "../") != NULL))
00141        /* This test is certainly a bit too restrictive but it should
00142           catch all critical cases.  */
00143        goto ret_free_transitions;
00144     }
00145 
00146   if (*file != '/')
00147     {
00148       const char *tzdir;
00149       unsigned int len, tzdir_len;
00150       char *new, *tmp;
00151 
00152       tzdir = getenv ("TZDIR");
00153       if (tzdir == NULL || *tzdir == '\0')
00154        {
00155          tzdir = default_tzdir;
00156          tzdir_len = sizeof (default_tzdir) - 1;
00157        }
00158       else
00159        tzdir_len = strlen (tzdir);
00160       len = strlen (file) + 1;
00161       new = (char *) __alloca (tzdir_len + 1 + len);
00162       tmp = __mempcpy (new, tzdir, tzdir_len);
00163       *tmp++ = '/';
00164       memcpy (tmp, file, len);
00165       file = new;
00166     }
00167 
00168   /* If we were already using tzfile, check whether the file changed.  */
00169   struct stat64 st;
00170   if (was_using_tzfile
00171       && stat64 (file, &st) == 0
00172       && tzfile_ino == st.st_ino && tzfile_dev == st.st_dev
00173       && tzfile_mtime == st.st_mtime)
00174     {
00175       /* Nothing to do.  */
00176       __use_tzfile = 1;
00177       return;
00178     }
00179 
00180   /* Note the file is opened with cancellation in the I/O functions
00181      disabled.  */
00182   f = fopen (file, "rc");
00183   if (f == NULL)
00184     goto ret_free_transitions;
00185 
00186   /* Get information about the file we are actually using.  */
00187   if (fstat64 (fileno (f), &st) != 0)
00188     {
00189       fclose (f);
00190       goto ret_free_transitions;
00191     }
00192 
00193   free ((void *) transitions);
00194   transitions = NULL;
00195 
00196   /* Remember the inode and device number and modification time.  */
00197   tzfile_dev = st.st_dev;
00198   tzfile_ino = st.st_ino;
00199   tzfile_mtime = st.st_mtime;
00200 
00201   /* No threads reading this stream.  */
00202   __fsetlocking (f, FSETLOCKING_BYCALLER);
00203 
00204  read_again:
00205   if (__builtin_expect (fread_unlocked ((void *) &tzhead, sizeof (tzhead),
00206                                    1, f) != 1, 0)
00207       || memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic)) != 0)
00208     goto lose;
00209 
00210   num_transitions = (size_t) decode (tzhead.tzh_timecnt);
00211   num_types = (size_t) decode (tzhead.tzh_typecnt);
00212   chars = (size_t) decode (tzhead.tzh_charcnt);
00213   num_leaps = (size_t) decode (tzhead.tzh_leapcnt);
00214   num_isstd = (size_t) decode (tzhead.tzh_ttisstdcnt);
00215   num_isgmt = (size_t) decode (tzhead.tzh_ttisgmtcnt);
00216 
00217   /* For platforms with 64-bit time_t we use the new format if available.  */
00218   if (sizeof (time_t) == 8 && trans_width == 4
00219       && tzhead.tzh_version[0] != '\0')
00220     {
00221       /* We use the 8-byte format.  */
00222       trans_width = 8;
00223 
00224       /* Position the stream before the second header.  */
00225       size_t to_skip = (num_transitions * (4 + 1)
00226                      + num_types * 6
00227                      + chars
00228                      + num_leaps * 8
00229                      + num_isstd
00230                      + num_isgmt);
00231       if (fseek (f, to_skip, SEEK_CUR) != 0)
00232        goto lose;
00233 
00234       goto read_again;
00235     }
00236 
00237   total_size = num_transitions * (sizeof (time_t) + 1);
00238   total_size = ((total_size + __alignof__ (struct ttinfo) - 1)
00239               & ~(__alignof__ (struct ttinfo) - 1));
00240   types_idx = total_size;
00241   total_size += num_types * sizeof (struct ttinfo) + chars;
00242   total_size = ((total_size + __alignof__ (struct leap) - 1)
00243               & ~(__alignof__ (struct leap) - 1));
00244   leaps_idx = total_size;
00245   total_size += num_leaps * sizeof (struct leap);
00246   tzspec_len = (sizeof (time_t) == 8 && trans_width == 8
00247               ? st.st_size - (ftello (f)
00248                             + num_transitions * (8 + 1)
00249                             + num_types * 6
00250                             + chars
00251                             + num_leaps * 8
00252                             + num_isstd
00253                             + num_isgmt) - 1 : 0);
00254 
00255   /* Allocate enough memory including the extra block requested by the
00256      caller.  */
00257   transitions = (time_t *) malloc (total_size + tzspec_len + extra);
00258   if (transitions == NULL)
00259     goto lose;
00260 
00261   type_idxs = (unsigned char *) transitions + (num_transitions
00262                                           * sizeof (time_t));
00263   types = (struct ttinfo *) ((char *) transitions + types_idx);
00264   zone_names = (char *) types + num_types * sizeof (struct ttinfo);
00265   leaps = (struct leap *) ((char *) transitions + leaps_idx);
00266   if (sizeof (time_t) == 8 && trans_width == 8)
00267     tzspec = (char *) leaps + num_leaps * sizeof (struct leap) + extra;
00268   else
00269     tzspec = NULL;
00270   if (extra > 0)
00271     *extrap = (char *) &leaps[num_leaps];
00272 
00273   if (sizeof (time_t) == 4 || __builtin_expect (trans_width == 8, 1))
00274     {
00275       if (__builtin_expect (fread_unlocked (transitions, trans_width + 1,
00276                                        num_transitions, f)
00277                          != num_transitions, 0))
00278        goto lose;
00279     }
00280   else
00281     {
00282       if (__builtin_expect (fread_unlocked (transitions, 4, num_transitions, f)
00283                          != num_transitions, 0)
00284          || __builtin_expect (fread_unlocked (type_idxs, 1, num_transitions,
00285                                           f) != num_transitions, 0))
00286        goto lose;
00287     }
00288 
00289   /* Check for bogus indices in the data file, so we can hereafter
00290      safely use type_idxs[T] as indices into `types' and never crash.  */
00291   for (i = 0; i < num_transitions; ++i)
00292     if (__builtin_expect (type_idxs[i] >= num_types, 0))
00293       goto lose;
00294 
00295   if ((BYTE_ORDER != BIG_ENDIAN && (sizeof (time_t) == 4 || trans_width == 4))
00296       || (BYTE_ORDER == BIG_ENDIAN && sizeof (time_t) == 8
00297          && trans_width == 4))
00298     {
00299       /* Decode the transition times, stored as 4-byte integers in
00300         network (big-endian) byte order.  We work from the end of
00301         the array so as not to clobber the next element to be
00302         processed when sizeof (time_t) > 4.  */
00303       i = num_transitions;
00304       while (i-- > 0)
00305        transitions[i] = decode ((char *) transitions + i * 4);
00306     }
00307   else if (BYTE_ORDER != BIG_ENDIAN && sizeof (time_t) == 8)
00308     {
00309       /* Decode the transition times, stored as 8-byte integers in
00310         network (big-endian) byte order.  */
00311       for (i = 0; i < num_transitions; ++i)
00312        transitions[i] = decode64 ((char *) transitions + i * 8);
00313     }
00314 
00315   for (i = 0; i < num_types; ++i)
00316     {
00317       unsigned char x[4];
00318       int c;
00319       if (__builtin_expect (fread_unlocked (x, 1, sizeof (x), f) != sizeof (x),
00320                          0))
00321        goto lose;
00322       c = getc_unlocked (f);
00323       if (__builtin_expect ((unsigned int) c > 1u, 0))
00324        goto lose;
00325       types[i].isdst = c;
00326       c = getc_unlocked (f);
00327       if (__builtin_expect ((size_t) c > chars, 0))
00328        /* Bogus index in data file.  */
00329        goto lose;
00330       types[i].idx = c;
00331       types[i].offset = (long int) decode (x);
00332     }
00333 
00334   if (__builtin_expect (fread_unlocked (zone_names, 1, chars, f) != chars, 0))
00335     goto lose;
00336 
00337   for (i = 0; i < num_leaps; ++i)
00338     {
00339       unsigned char x[8];
00340       if (__builtin_expect (fread_unlocked (x, 1, trans_width, f)
00341                          != trans_width, 0))
00342        goto lose;
00343       if (sizeof (time_t) == 4 || trans_width == 4)
00344        leaps[i].transition = (time_t) decode (x);
00345       else
00346        leaps[i].transition = (time_t) decode64 (x);
00347 
00348       if (__builtin_expect (fread_unlocked (x, 1, 4, f) != 4, 0))
00349        goto lose;
00350       leaps[i].change = (long int) decode (x);
00351     }
00352 
00353   for (i = 0; i < num_isstd; ++i)
00354     {
00355       int c = getc_unlocked (f);
00356       if (__builtin_expect (c == EOF, 0))
00357        goto lose;
00358       types[i].isstd = c != 0;
00359     }
00360   while (i < num_types)
00361     types[i++].isstd = 0;
00362 
00363   for (i = 0; i < num_isgmt; ++i)
00364     {
00365       int c = getc_unlocked (f);
00366       if (__builtin_expect (c == EOF, 0))
00367        goto lose;
00368       types[i].isgmt = c != 0;
00369     }
00370   while (i < num_types)
00371     types[i++].isgmt = 0;
00372 
00373   /* Read the POSIX TZ-style information if possible.  */
00374   if (sizeof (time_t) == 8 && tzspec != NULL)
00375     {
00376       /* Skip over the newline first.  */
00377       if (getc_unlocked (f) != '\n'
00378          || (fread_unlocked (tzspec, 1, tzspec_len - 1, f)
00379              != tzspec_len - 1))
00380        tzspec = NULL;
00381       else
00382        tzspec[tzspec_len - 1] = '\0';
00383     }
00384   else if (sizeof (time_t) == 4 && tzhead.tzh_version[0] != '\0')
00385     {
00386       /* Get the TZ string.  */
00387       if (__builtin_expect (fread_unlocked ((void *) &tzhead, sizeof (tzhead),
00388                                        1, f) != 1, 0)
00389          || (memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic))
00390              != 0))
00391        goto lose;
00392 
00393       size_t num_transitions2 = (size_t) decode (tzhead.tzh_timecnt);
00394       size_t num_types2 = (size_t) decode (tzhead.tzh_typecnt);
00395       size_t chars2 = (size_t) decode (tzhead.tzh_charcnt);
00396       size_t num_leaps2 = (size_t) decode (tzhead.tzh_leapcnt);
00397       size_t num_isstd2 = (size_t) decode (tzhead.tzh_ttisstdcnt);
00398       size_t num_isgmt2 = (size_t) decode (tzhead.tzh_ttisgmtcnt);
00399 
00400       /* Position the stream before the second header.  */
00401       size_t to_skip = (num_transitions2 * (8 + 1)
00402                      + num_types2 * 6
00403                      + chars2
00404                      + num_leaps2 * 12
00405                      + num_isstd2
00406                      + num_isgmt2);
00407       off_t off;
00408       if (fseek (f, to_skip, SEEK_CUR) != 0
00409          || (off = ftello (f)) < 0
00410          || st.st_size < off + 2)
00411        goto lose;
00412 
00413       tzspec_len = st.st_size - off - 1;
00414       char *tzstr = alloca (tzspec_len);
00415       if (getc_unlocked (f) != '\n'
00416          || (fread_unlocked (tzstr, 1, tzspec_len - 1, f) != tzspec_len - 1))
00417        goto lose;
00418       tzstr[tzspec_len - 1] = '\0';
00419       tzspec = __tzstring (tzstr);
00420     }
00421 
00422   fclose (f);
00423 
00424   /* First "register" all timezone names.  */
00425   for (i = 0; i < num_types; ++i)
00426     (void) __tzstring (&zone_names[types[i].idx]);
00427 
00428   /* Find the standard and daylight time offsets used by the rule file.
00429      We choose the offsets in the types of each flavor that are
00430      transitioned to earliest in time.  */
00431   __tzname[0] = NULL;
00432   __tzname[1] = NULL;
00433   for (i = num_transitions; i > 0; )
00434     {
00435       int type = type_idxs[--i];
00436       int dst = types[type].isdst;
00437 
00438       if (__tzname[dst] == NULL)
00439        {
00440          int idx = types[type].idx;
00441 
00442          __tzname[dst] = __tzstring (&zone_names[idx]);
00443 
00444          if (__tzname[1 - dst] != NULL)
00445            break;
00446        }
00447     }
00448   if (__tzname[0] == NULL)
00449     {
00450       /* This should only happen if there are no transition rules.
00451         In this case there should be only one single type.  */
00452       assert (num_types == 1);
00453       __tzname[0] = __tzstring (zone_names);
00454     }
00455   if (__tzname[1] == NULL)
00456     __tzname[1] = __tzname[0];
00457 
00458   compute_tzname_max (chars);
00459 
00460   if (num_transitions == 0)
00461     /* Use the first rule (which should also be the only one).  */
00462     rule_stdoff = rule_dstoff = types[0].offset;
00463   else
00464     {
00465       int stdoff_set = 0, dstoff_set = 0;
00466       rule_stdoff = rule_dstoff = 0;
00467       i = num_transitions - 1;
00468       do
00469        {
00470          if (!stdoff_set && !types[type_idxs[i]].isdst)
00471            {
00472              stdoff_set = 1;
00473              rule_stdoff = types[type_idxs[i]].offset;
00474            }
00475          else if (!dstoff_set && types[type_idxs[i]].isdst)
00476            {
00477              dstoff_set = 1;
00478              rule_dstoff = types[type_idxs[i]].offset;
00479            }
00480          if (stdoff_set && dstoff_set)
00481            break;
00482        }
00483       while (i-- > 0);
00484 
00485       if (!dstoff_set)
00486        rule_dstoff = rule_stdoff;
00487     }
00488 
00489   __daylight = rule_stdoff != rule_dstoff;
00490   __timezone = -rule_stdoff;
00491 
00492   __use_tzfile = 1;
00493   return;
00494 
00495  lose:
00496   fclose (f);
00497  ret_free_transitions:
00498   free ((void *) transitions);
00499   transitions = NULL;
00500 }
00501 
00502 /* The user specified a hand-made timezone, but not its DST rules.
00503    We will use the names and offsets from the user, and the rules
00504    from the TZDEFRULES file.  */
00505 
00506 void
00507 __tzfile_default (const char *std, const char *dst,
00508                 long int stdoff, long int dstoff)
00509 {
00510   size_t stdlen = strlen (std) + 1;
00511   size_t dstlen = strlen (dst) + 1;
00512   size_t i;
00513   int isdst;
00514   char *cp;
00515 
00516   __tzfile_read (TZDEFRULES, stdlen + dstlen, &cp);
00517   if (!__use_tzfile)
00518     return;
00519 
00520   if (num_types < 2)
00521     {
00522       __use_tzfile = 0;
00523       return;
00524     }
00525 
00526   /* Ignore the zone names read from the file and use the given ones
00527      instead.  */
00528   __mempcpy (__mempcpy (cp, std, stdlen), dst, dstlen);
00529   zone_names = cp;
00530 
00531   /* Now there are only two zones, regardless of what the file contained.  */
00532   num_types = 2;
00533 
00534   /* Now correct the transition times for the user-specified standard and
00535      daylight offsets from GMT.  */
00536   isdst = 0;
00537   for (i = 0; i < num_transitions; ++i)
00538     {
00539       struct ttinfo *trans_type = &types[type_idxs[i]];
00540 
00541       /* We will use only types 0 (standard) and 1 (daylight).
00542         Fix up this transition to point to whichever matches
00543         the flavor of its original type.  */
00544       type_idxs[i] = trans_type->isdst;
00545 
00546       if (trans_type->isgmt)
00547        /* The transition time is in GMT.  No correction to apply.  */ ;
00548       else if (isdst && !trans_type->isstd)
00549        /* The type says this transition is in "local wall clock time", and
00550           wall clock time as of the previous transition was DST.  Correct
00551           for the difference between the rule's DST offset and the user's
00552           DST offset.  */
00553        transitions[i] += dstoff - rule_dstoff;
00554       else
00555        /* This transition is in "local wall clock time", and wall clock
00556           time as of this iteration is non-DST.  Correct for the
00557           difference between the rule's standard offset and the user's
00558           standard offset.  */
00559        transitions[i] += stdoff - rule_stdoff;
00560 
00561       /* The DST state of "local wall clock time" for the next iteration is
00562         as specified by this transition.  */
00563       isdst = trans_type->isdst;
00564     }
00565 
00566   /* Now that we adjusted the transitions to the requested offsets,
00567      reset the rule_stdoff and rule_dstoff values appropriately.  They
00568      are used elsewhere.  */
00569   rule_stdoff = stdoff;
00570   rule_dstoff = dstoff;
00571 
00572   /* Reset types 0 and 1 to describe the user's settings.  */
00573   types[0].idx = 0;
00574   types[0].offset = stdoff;
00575   types[0].isdst = 0;
00576   types[1].idx = stdlen;
00577   types[1].offset = dstoff;
00578   types[1].isdst = 1;
00579 
00580   /* Reset the zone names to point to the user's names.  */
00581   __tzname[0] = (char *) std;
00582   __tzname[1] = (char *) dst;
00583 
00584   /* Set the timezone.  */
00585   __timezone = -types[0].offset;
00586 
00587   compute_tzname_max (stdlen + dstlen);
00588 }
00589 
00590 void
00591 __tzfile_compute (time_t timer, int use_localtime,
00592                 long int *leap_correct, int *leap_hit,
00593                 struct tm *tp)
00594 {
00595   register size_t i;
00596 
00597   if (use_localtime)
00598     {
00599       __tzname[0] = NULL;
00600       __tzname[1] = NULL;
00601 
00602       if (__builtin_expect (num_transitions == 0 || timer < transitions[0], 0))
00603        {
00604          /* TIMER is before any transition (or there are no transitions).
00605             Choose the first non-DST type
00606             (or the first if they're all DST types).  */
00607          i = 0;
00608          while (i < num_types && types[i].isdst)
00609            {
00610              if (__tzname[1] == NULL)
00611               __tzname[1] = __tzstring (&zone_names[types[i].idx]);
00612 
00613              ++i;
00614            }
00615 
00616          if (i == num_types)
00617            i = 0;
00618          __tzname[0] = __tzstring (&zone_names[types[i].idx]);
00619          if (__tzname[1] == NULL)
00620            {
00621              size_t j = i;
00622              while (j < num_types)
00623               if (types[j].isdst)
00624                 {
00625                   __tzname[1] = __tzstring (&zone_names[types[j].idx]);
00626                   break;
00627                 }
00628               else
00629                 ++j;
00630            }
00631        }
00632       else if (__builtin_expect (timer >= transitions[num_transitions - 1], 0))
00633        {
00634          if (__builtin_expect (tzspec == NULL, 0))
00635            {
00636            use_last:
00637              i = num_transitions;
00638              goto found;
00639            }
00640 
00641          /* Parse the POSIX TZ-style string.  */
00642          __tzset_parse_tz (tzspec);
00643 
00644          /* Convert to broken down structure.  If this fails do not
00645             use the string.  */
00646          if (__builtin_expect (! __offtime (&timer, 0, tp), 0))
00647            goto use_last;
00648 
00649          /* Use the rules from the TZ string to compute the change.  */
00650          __tz_compute (timer, tp, 1);
00651 
00652          /* If tzspec comes from posixrules loaded by __tzfile_default,
00653             override the STD and DST zone names with the ones user
00654             requested in TZ envvar.  */
00655          if (__builtin_expect (zone_names == (char *) &leaps[num_leaps], 0))
00656            {
00657              assert (num_types == 2);
00658              __tzname[0] = __tzstring (zone_names);
00659              __tzname[1] = __tzstring (&zone_names[strlen (zone_names) + 1]);
00660            }
00661 
00662          *leap_correct = 0L;
00663          *leap_hit = 0;
00664          return;
00665        }
00666       else
00667        {
00668          /* Find the first transition after TIMER, and
00669             then pick the type of the transition before it.  */
00670          size_t lo = 0;
00671          size_t hi = num_transitions - 1;
00672          /* Assume that DST is changing twice a year and guess initial
00673             search spot from it.
00674             Half of a gregorian year has on average 365.2425 * 86400 / 2
00675             = 15778476 seconds.  */
00676          i = (transitions[num_transitions - 1] - timer) / 15778476;
00677          if (i < num_transitions)
00678            {
00679              i = num_transitions - 1 - i;
00680              if (timer < transitions[i])
00681               {
00682                 if (i < 10 || timer >= transitions[i - 10])
00683                   {
00684                     /* Linear search.  */
00685                     while (timer < transitions[i - 1])
00686                      --i;
00687                     goto found;
00688                   }
00689                 hi = i - 10;
00690               }
00691              else
00692               {
00693                 if (i + 10 >= num_transitions || timer < transitions[i + 10])
00694                   {
00695                     /* Linear search.  */
00696                     while (timer >= transitions[i])
00697                      ++i;
00698                     goto found;
00699                   }
00700                 lo = i + 10;
00701               }
00702            }
00703 
00704          /* Binary search.  */
00705          /* assert (timer >= transitions[lo] && timer < transitions[hi]); */
00706          while (lo + 1 < hi)
00707            {
00708              i = (lo + hi) / 2;
00709              if (timer < transitions[i])
00710               hi = i;
00711              else
00712               lo = i;
00713            }
00714          i = hi;
00715 
00716        found:
00717          /* assert (timer >= transitions[i - 1]
00718             && (i == num_transitions || timer < transitions[i])); */
00719          __tzname[types[type_idxs[i - 1]].isdst]
00720            = __tzstring (&zone_names[types[type_idxs[i - 1]].idx]);
00721          size_t j = i;
00722          while (j < num_transitions)
00723            {
00724              int type = type_idxs[j];
00725              int dst = types[type].isdst;
00726              int idx = types[type].idx;
00727 
00728              if (__tzname[dst] == NULL)
00729               {
00730                 __tzname[dst] = __tzstring (&zone_names[idx]);
00731 
00732                 if (__tzname[1 - dst] != NULL)
00733                   break;
00734               }
00735 
00736              ++j;
00737            }
00738 
00739          if (__builtin_expect (__tzname[0] == NULL, 0))
00740            __tzname[0] = __tzname[1];
00741 
00742          i = type_idxs[i - 1];
00743        }
00744 
00745       struct ttinfo *info = &types[i];
00746       __daylight = rule_stdoff != rule_dstoff;
00747       __timezone = -rule_stdoff;
00748 
00749       if (__tzname[0] == NULL)
00750        {
00751          /* This should only happen if there are no transition rules.
00752             In this case there should be only one single type.  */
00753          assert (num_types == 1);
00754          __tzname[0] = __tzstring (zone_names);
00755        }
00756       if (__tzname[1] == NULL)
00757        /* There is no daylight saving time.  */
00758        __tzname[1] = __tzname[0];
00759       tp->tm_isdst = info->isdst;
00760       assert (strcmp (&zone_names[info->idx], __tzname[tp->tm_isdst]) == 0);
00761       tp->tm_zone = __tzname[tp->tm_isdst];
00762       tp->tm_gmtoff = info->offset;
00763     }
00764 
00765   *leap_correct = 0L;
00766   *leap_hit = 0;
00767 
00768   /* Find the last leap second correction transition time before TIMER.  */
00769   i = num_leaps;
00770   do
00771     if (i-- == 0)
00772       return;
00773   while (timer < leaps[i].transition);
00774 
00775   /* Apply its correction.  */
00776   *leap_correct = leaps[i].change;
00777 
00778   if (timer == leaps[i].transition && /* Exactly at the transition time.  */
00779       ((i == 0 && leaps[i].change > 0) ||
00780        leaps[i].change > leaps[i - 1].change))
00781     {
00782       *leap_hit = 1;
00783       while (i > 0
00784             && leaps[i].transition == leaps[i - 1].transition + 1
00785             && leaps[i].change == leaps[i - 1].change + 1)
00786        {
00787          ++*leap_hit;
00788          --i;
00789        }
00790     }
00791 }
00792 
00793 static void
00794 internal_function
00795 compute_tzname_max (size_t chars)
00796 {
00797   const char *p;
00798 
00799   p = zone_names;
00800   do
00801     {
00802       const char *start = p;
00803       while (*p != '\0')
00804        ++p;
00805       if ((size_t) (p - start) > __tzname_cur_max)
00806        __tzname_cur_max = p - start;
00807     }
00808   while (++p < &zone_names[chars]);
00809 }