* include/time.h: Declare __tzset_parse_tz and __tzset_compute.
authorUlrich Drepper <drepper@redhat.com>
Sun, 14 Oct 2007 09:15:45 +0000 (09:15 +0000)
committerUlrich Drepper <drepper@redhat.com>
Sun, 14 Oct 2007 09:15:45 +0000 (09:15 +0000)
* time/tzset.c (tzset_internal): Break TZ string parsing out into
__tzset_parse_tz and updating of daylight, timezone, tzname into
update_vars.
(__tz_compute): Renamed from tz_compute.  Take additional parameters.
(__tz_convert): Updating of tm_isdst, tm_zone, and tm_gmtoff now
happens in __tz_compute.
* time/tzfile.c (__tzfile_read): Also read TZ string.
(find_transition): Fold into __tzfile_compute.
(__tzfile_compute): For times beyond the last transition try to
use the TZ string.
* timezone/tst-timezone.c: Information in daylight and tzname does
change for Asia/Tokyo timezone with more concrete information.
Remove the test.

* include/stdio.h: Add libc_hidden_proto for ftello.
* libio/ftello.c: Add libc_hidden_def.

ChangeLog
include/stdio.h
include/time.h
libio/ftello.c
nscd/nscd_getgr_r.c
time/tzfile.c
time/tzset.c
timezone/tst-timezone.c

index 433860e5bde5739f8c1a20cb4d0268d06715335b..c16c6ed0fa2cacb6524ae5fe43a5d753605a62fc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
 2007-10-14  Ulrich Drepper  <drepper@redhat.com>
 
+       * include/time.h: Declare __tzset_parse_tz and __tzset_compute.
+       * time/tzset.c (tzset_internal): Break TZ string parsing out into
+       __tzset_parse_tz and updating of daylight, timezone, tzname into
+       update_vars.
+       (__tz_compute): Renamed from tz_compute.  Take additional parameters.
+       (__tz_convert): Updating of tm_isdst, tm_zone, and tm_gmtoff now
+       happens in __tz_compute.
+       * time/tzfile.c (__tzfile_read): Also read TZ string.
+       (find_transition): Fold into __tzfile_compute.
+       (__tzfile_compute): For times beyond the last transition try to
+       use the TZ string.
+       * timezone/tst-timezone.c: Information in daylight and tzname does
+       change for Asia/Tokyo timezone with more concrete information.
+       Remove the test.
+
+       * include/stdio.h: Add libc_hidden_proto for ftello.
+       * libio/ftello.c: Add libc_hidden_def.
+
        [BZ #1140]
        * time/tzfile.c (__tzfile_compute): Compute tzname[] values based
        on the specified time and not the last entries in the file.  Move
index 084c02ea1e72d39f9d3c036f290c216fa5d80415..3c110374905f2ae22843f18641a5c1fa31641b62 100644 (file)
@@ -138,6 +138,7 @@ libc_hidden_proto (rewind)
 libc_hidden_proto (fileno)
 libc_hidden_proto (fwrite)
 libc_hidden_proto (fseek)
+libc_hidden_proto (ftello)
 libc_hidden_proto (fflush_unlocked)
 libc_hidden_proto (fread_unlocked)
 libc_hidden_proto (fwrite_unlocked)
index ed6cb3669f0129c1b141a11d8d15f25a57eb39e1..e896406db4a5c77f5588542a54772acc9aaa16b0 100644 (file)
@@ -46,6 +46,9 @@ extern void __tzfile_compute (time_t timer, int use_localtime,
                              struct tm *tp);
 extern void __tzfile_default (const char *std, const char *dst,
                              long int stdoff, long int dstoff);
+extern void __tzset_parse_tz (const char *tz);
+extern void __tz_compute (time_t timer, struct tm *tm, int use_localtime)
+     __THROW internal_function;
 
 /* Subroutine of `mktime'.  Return the `time_t' representation of TP and
    normalize TP, given that a `struct tm *' maps to a `time_t' as performed
index e58daacad417c81edb9bed6c2bc65f6e26e7df44..d250e55c04a7931c67839cafc139b5de6b054482 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995-2001, 2002, 2003, 2004
+/* Copyright (C) 1993, 1995-2001, 2002, 2003, 2004, 2007
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -63,3 +63,4 @@ ftello (fp)
     }
   return pos;
 }
+libc_hidden_def (ftello)
index a277a1d355d70e95120e1907dac8457435b8260a..afb4d204352776680e5b1669a2745298a188f09d 100644 (file)
@@ -264,9 +264,9 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
       retval = 0;
 
       /* If there are no group members TOTAL_LEN is zero.  */
-      if (total_len > 0)
+      if (gr_name == NULL)
        {
-         if (gr_name == NULL)
+         if (total_len > 0)
            {
              size_t n = __readall (sock, resultbuf->gr_mem[0], total_len);
              if (__builtin_expect (n != total_len, 0))
@@ -278,26 +278,26 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
              else
                *result = resultbuf;
            }
-         else
+       }
+      else
+       {
+         /* Copy the group member names.  */
+         memcpy (resultbuf->gr_mem[0], gr_name + gr_name_len, total_len);
+
+         /* Try to detect corrupt databases.  */
+         if (resultbuf->gr_name[gr_name_len - 1] != '\0'
+             || resultbuf->gr_passwd[gr_resp.gr_passwd_len - 1] != '\0'
+             || ({for (cnt = 0; cnt < gr_resp.gr_mem_cnt; ++cnt)
+                   if (resultbuf->gr_mem[cnt][len[cnt] - 1] != '\0')
+                     break;
+                 cnt < gr_resp.gr_mem_cnt; }))
            {
-             /* Copy the group member names.  */
-             memcpy (resultbuf->gr_mem[0], gr_name + gr_name_len, total_len);
-
-             /* Try to detect corrupt databases.  */
-             if (resultbuf->gr_name[gr_name_len - 1] != '\0'
-                 || resultbuf->gr_passwd[gr_resp.gr_passwd_len - 1] != '\0'
-                 || ({for (cnt = 0; cnt < gr_resp.gr_mem_cnt; ++cnt)
-                       if (resultbuf->gr_mem[cnt][len[cnt] - 1] != '\0')
-                         break;
-                     cnt < gr_resp.gr_mem_cnt; }))
-               {
-                 /* We cannot use the database.  */
-                 retval = mapped->head->gc_cycle != gc_cycle ? -2 : -1;
-                 goto out_close;
-               }
-
-             *result = resultbuf;
+             /* We cannot use the database.  */
+             retval = mapped->head->gc_cycle != gc_cycle ? -2 : -1;
+             goto out_close;
            }
+
+         *result = resultbuf;
        }
     }
   else
index a872e283a2eea64a67240b1391e2778a2a6ce6ac..44d66147718219ab8570f6a27d8a83695a36bfd0 100644 (file)
@@ -62,6 +62,7 @@ static long int rule_stdoff;
 static long int rule_dstoff;
 static size_t num_leaps;
 static struct leap *leaps;
+static char *tzspec;
 
 #include <endian.h>
 #include <byteswap.h>
@@ -113,6 +114,7 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
   size_t leaps_idx;
   int was_using_tzfile = __use_tzfile;
   int trans_width = 4;
+  size_t tzspec_len;
 
   if (sizeof (time_t) != 4 && sizeof (time_t) != 8)
     abort ();
@@ -241,10 +243,18 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
                & ~(__alignof__ (struct leap) - 1));
   leaps_idx = total_size;
   total_size += num_leaps * sizeof (struct leap);
+  tzspec_len = (trans_width == 8
+               ? st.st_size - (ftello (f)
+                               + num_transitions * (8 + 1)
+                               + num_types * 6
+                               + chars
+                               + num_leaps * 8
+                               + num_isstd
+                               + num_isgmt) - 1 : 0);
 
   /* Allocate enough memory including the extra block requested by the
      caller.  */
-  transitions = (time_t *) malloc (total_size + extra);
+  transitions = (time_t *) malloc (total_size + tzspec_len + extra);
   if (transitions == NULL)
     goto lose;
 
@@ -253,6 +263,10 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
   types = (struct ttinfo *) ((char *) transitions + types_idx);
   zone_names = (char *) types + num_types * sizeof (struct ttinfo);
   leaps = (struct leap *) ((char *) transitions + leaps_idx);
+  if (trans_width == 8)
+    tzspec = (char *) leaps + num_leaps * sizeof (struct leap);
+  else
+    tzspec = NULL;
   if (extra > 0)
     *extrap = (char *) &leaps[num_leaps];
 
@@ -356,11 +370,16 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
   while (i < num_types)
     types[i++].isgmt = 0;
 
-  /* XXX When a version 2 file is available it can contain a POSIX TZ-style
-     formatted string which specifies how times past the last one specified
-     are supposed to be handled.  We might want to handle this at some
-     point.  But it might be overhead since most/all? files have an
-     open-ended last entry.  */
+  /* Read the POSIX TZ-style information if possible.  */
+  if (tzspec != NULL)
+    {
+      /* Skip over the newline first.  */
+      if (getc_unlocked (f) != '\n'
+         || fread_unlocked (tzspec, 1, tzspec_len - 1, f) != tzspec_len - 1)
+       tzspec = NULL;
+      else
+       tzspec[tzspec_len - 1] = '\0';
+    }
 
   fclose (f);
 
@@ -530,138 +549,148 @@ __tzfile_default (const char *std, const char *dst,
   compute_tzname_max (stdlen + dstlen);
 }
 \f
-static struct ttinfo *
-internal_function
-find_transition (time_t timer)
+void
+__tzfile_compute (time_t timer, int use_localtime,
+                 long int *leap_correct, int *leap_hit,
+                 struct tm *tp)
 {
-  size_t i;
-
-  __tzname[0] = NULL;
-  __tzname[1] = NULL;
+  register size_t i;
 
-  if (num_transitions == 0 || timer < transitions[0])
+  if (use_localtime)
     {
-      /* TIMER is before any transition (or there are no transitions).
-        Choose the first non-DST type
-        (or the first if they're all DST types).  */
-      i = 0;
-      while (i < num_types && types[i].isdst)
+      __tzname[0] = NULL;
+      __tzname[1] = NULL;
+
+      if (num_transitions == 0 || timer < transitions[0])
        {
-         if (__tzname[1] == NULL)
-           __tzname[1] = __tzstring (&zone_names[types[i].idx]);
+         /* TIMER is before any transition (or there are no transitions).
+            Choose the first non-DST type
+            (or the first if they're all DST types).  */
+         i = 0;
+         while (i < num_types && types[i].isdst)
+           {
+             if (__tzname[1] == NULL)
+               __tzname[1] = __tzstring (&zone_names[types[i].idx]);
 
-         ++i;
-       }
+             ++i;
+           }
 
-      if (i == num_types)
-       i = 0;
-      __tzname[0] = __tzstring (&zone_names[types[i].idx]);
-      if (__tzname[1] == NULL)
+         if (i == num_types)
+           i = 0;
+         __tzname[0] = __tzstring (&zone_names[types[i].idx]);
+         if (__tzname[1] == NULL)
+           {
+             size_t j = i;
+             while (j < num_types)
+               if (types[j].isdst)
+                 {
+                   __tzname[1] = __tzstring (&zone_names[types[j].idx]);
+                   break;
+                 }
+               else
+                 ++j;
+           }
+       }
+      else if (timer >= transitions[num_transitions - 1])
        {
-         size_t j = i;
-         while (j < num_types)
-           if (types[j].isdst)
-             {
-               __tzname[1] = __tzstring (&zone_names[types[j].idx]);
-               break;
-             }
-           else
-             ++j;
+         if (tzspec == NULL)
+           {
+           use_last:
+             i = num_transitions - 1;
+             goto found;
+           }
+
+         /* Parse the POSIX TZ-style string.  */
+         __tzset_parse_tz (tzspec);
+
+         /* Convert to broken down structure.  If this fails do not
+            use the string.  */
+         if (! __offtime (&timer, 0, tp))
+           goto use_last;
+
+         /* Use the rules from the TZ string to compute the change.  */
+         __tz_compute (timer, tp, 1);
+
+         *leap_correct = 0L;
+         *leap_hit = 0;
+         return;
        }
-    }
-  else if (timer >= transitions[num_transitions - 1])
-    {
-      i = num_transitions - 1;
-      goto found;
-    }
-  else
-    {
-      /* Find the first transition after TIMER, and
-        then pick the type of the transition before it.  */
-      size_t lo = 0;
-      size_t hi = num_transitions - 1;
-      /* Assume that DST is changing twice a year and guess initial
-        search spot from it.
-        Half of a gregorian year has on average 365.2425 * 86400 / 2
-        = 15778476 seconds.  */
-      i = (transitions[num_transitions - 1] - timer) / 15778476;
-      if (i < num_transitions)
+      else
        {
-         i = num_transitions - 1 - i;
-         if (timer < transitions[i])
+         /* Find the first transition after TIMER, and
+            then pick the type of the transition before it.  */
+         size_t lo = 0;
+         size_t hi = num_transitions - 1;
+         /* Assume that DST is changing twice a year and guess initial
+            search spot from it.
+            Half of a gregorian year has on average 365.2425 * 86400 / 2
+            = 15778476 seconds.  */
+         i = (transitions[num_transitions - 1] - timer) / 15778476;
+         if (i < num_transitions)
            {
-             if (i < 10 || timer >= transitions[i - 10])
+             i = num_transitions - 1 - i;
+             if (timer < transitions[i])
                {
-                 /* Linear search.  */
-                 while (timer < transitions[i - 1])
-                   --i;
-                 goto found;
+                 if (i < 10 || timer >= transitions[i - 10])
+                   {
+                     /* Linear search.  */
+                     while (timer < transitions[i - 1])
+                       --i;
+                     goto found;
+                   }
+                 hi = i - 10;
                }
-             hi = i - 10;
-           }
-         else
-           {
-             if (i + 10 >= num_transitions || timer < transitions[i + 10])
+             else
                {
-                 /* Linear search.  */
-                 while (timer >= transitions[i])
-                   ++i;
-                 goto found;
+                 if (i + 10 >= num_transitions || timer < transitions[i + 10])
+                   {
+                     /* Linear search.  */
+                     while (timer >= transitions[i])
+                       ++i;
+                     goto found;
+                   }
+                 lo = i + 10;
                }
-             lo = i + 10;
            }
-       }
 
-      /* Binary search.  */
-      /* assert (timer >= transitions[lo] && timer < transitions[hi]); */
-      while (lo + 1 < hi)
-       {
-         i = (lo + hi) / 2;
-         if (timer < transitions[i])
-           hi = i;
-         else
-           lo = i;
-       }
-      i = hi;
-
-    found:
-      /* assert (timer >= transitions[i - 1] && timer < transitions[i]); */
-      __tzname[types[type_idxs[i - 1]].isdst]
-       = __tzstring (&zone_names[types[type_idxs[i - 1]].idx]);
-      size_t j = i;
-      while (j < num_transitions)
-       {
-         int type = type_idxs[j];
-         int dst = types[type].isdst;
-         int idx = types[type].idx;
+         /* Binary search.  */
+         /* assert (timer >= transitions[lo] && timer < transitions[hi]); */
+         while (lo + 1 < hi)
+           {
+             i = (lo + hi) / 2;
+             if (timer < transitions[i])
+               hi = i;
+             else
+               lo = i;
+           }
+         i = hi;
 
-         if (__tzname[dst] == NULL)
+       found:
+         /* assert (timer >= transitions[i - 1] && timer < transitions[i]); */
+         __tzname[types[type_idxs[i - 1]].isdst]
+           = __tzstring (&zone_names[types[type_idxs[i - 1]].idx]);
+         size_t j = i;
+         while (j < num_transitions)
            {
-             __tzname[dst] = __tzstring (&zone_names[idx]);
+             int type = type_idxs[j];
+             int dst = types[type].isdst;
+             int idx = types[type].idx;
 
-             if (__tzname[1 - dst] != NULL)
-               break;
-           }
+             if (__tzname[dst] == NULL)
+               {
+                 __tzname[dst] = __tzstring (&zone_names[idx]);
 
-         ++j;
-       }
+                 if (__tzname[1 - dst] != NULL)
+                   break;
+               }
 
-      i = type_idxs[i - 1];
-    }
+             ++j;
+           }
 
-  return &types[i];
-}
-\f
-void
-__tzfile_compute (time_t timer, int use_localtime,
-                 long int *leap_correct, int *leap_hit,
-                 struct tm *tp)
-{
-  register size_t i;
+         i = type_idxs[i - 1];
+       }
 
-  if (use_localtime)
-    {
-      struct ttinfo *info = find_transition (timer);
+      struct ttinfo *info = &types[i];
       __daylight = rule_stdoff != rule_dstoff;
       __timezone = -rule_stdoff;
 
index 0479abb38a4ffc7e9160193a9c32b675227264b2..27efef0f7a2fc7ba420c77492f2b32033c4bec5b 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2002,2003,2004 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2002,2003,2004,2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -70,7 +70,6 @@ static tz_rule tz_rules[2];
 
 
 static void compute_change (tz_rule *rule, int year) __THROW internal_function;
-static void tz_compute (const struct tm *tm) __THROW internal_function;
 static void tzset_internal (int always, int explicit)
      __THROW internal_function;
 \f
@@ -92,7 +91,7 @@ __tzstring (const char *s)
 {
   char *p;
   struct tzstring_l *t, *u, *new;
-  size_t len = strlen(s);
+  size_t len = strlen (s);
 
   /* Walk the list and look for a match.  If this string is the same
      as the end of an already-allocated string, it can share space. */
@@ -140,80 +139,34 @@ __tzname_max ()
 \f
 static char *old_tz;
 
-/* Interpret the TZ envariable.  */
 static void
 internal_function
-tzset_internal (always, explicit)
-     int always;
-     int explicit;
+update_vars (void)
+{
+  __daylight = tz_rules[0].offset != tz_rules[1].offset;
+  __timezone = -tz_rules[0].offset;
+  __tzname[0] = (char *) tz_rules[0].name;
+  __tzname[1] = (char *) tz_rules[1].name;
+
+  /* Keep __tzname_cur_max up to date.  */
+  size_t len0 = strlen (__tzname[0]);
+  size_t len1 = strlen (__tzname[1]);
+  if (len0 > __tzname_cur_max)
+    __tzname_cur_max = len0;
+  if (len1 > __tzname_cur_max)
+    __tzname_cur_max = len1;
+}
+
+/* Parse the POSIX TZ-style string.  */
+void
+__tzset_parse_tz (tz)
+     const char *tz;
 {
-  static int is_initialized;
-  register const char *tz;
   register size_t l;
   char *tzbuf;
   unsigned short int hh, mm, ss;
   unsigned short int whichrule;
 
-  if (is_initialized && !always)
-    return;
-  is_initialized = 1;
-
-  /* Examine the TZ environment variable.  */
-  tz = getenv ("TZ");
-  if (tz == NULL && !explicit)
-    /* Use the site-wide default.  This is a file name which means we
-       would not see changes to the file if we compare only the file
-       name for change.  We want to notice file changes if tzset() has
-       been called explicitly.  Leave TZ as NULL in this case.  */
-    tz = TZDEFAULT;
-  if (tz && *tz == '\0')
-    /* User specified the empty string; use UTC explicitly.  */
-    tz = "Universal";
-
-  /* A leading colon means "implementation defined syntax".
-     We ignore the colon and always use the same algorithm:
-     try a data file, and if none exists parse the 1003.1 syntax.  */
-  if (tz && *tz == ':')
-    ++tz;
-
-  /* Check whether the value changes since the last run.  */
-  if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0)
-    /* No change, simply return.  */
-    return;
-
-  if (tz == NULL)
-    /* No user specification; use the site-wide default.  */
-    tz = TZDEFAULT;
-
-  tz_rules[0].name = NULL;
-  tz_rules[1].name = NULL;
-
-  /* Save the value of `tz'.  */
-  if (old_tz != NULL)
-    free (old_tz);
-  old_tz = tz ? __strdup (tz) : NULL;
-
-  /* Try to read a data file.  */
-  __tzfile_read (tz, 0, NULL);
-  if (__use_tzfile)
-    return;
-
-  /* No data file found.  Default to UTC if nothing specified.  */
-
-  if (tz == NULL || *tz == '\0'
-      || (TZDEFAULT != NULL && strcmp (tz, TZDEFAULT) == 0))
-    {
-      tz_rules[0].name = tz_rules[1].name = "UTC";
-      tz_rules[0].type = tz_rules[1].type = J0;
-      tz_rules[0].m = tz_rules[0].n = tz_rules[0].d = 0;
-      tz_rules[1].m = tz_rules[1].n = tz_rules[1].d = 0;
-      tz_rules[0].secs = tz_rules[1].secs = 0;
-      tz_rules[0].offset = tz_rules[1].offset = 0L;
-      tz_rules[0].change = tz_rules[1].change = (time_t) -1;
-      tz_rules[0].computed_for = tz_rules[1].computed_for = 0;
-      goto out;
-    }
-
   /* Clear out old state and reset to unnamed UTC.  */
   memset (tz_rules, 0, sizeof tz_rules);
   tz_rules[0].name = tz_rules[1].name = "";
@@ -413,20 +366,81 @@ tzset_internal (always, explicit)
     }
 
  out:
-  __daylight = tz_rules[0].offset != tz_rules[1].offset;
-  __timezone = -tz_rules[0].offset;
-  __tzname[0] = (char *) tz_rules[0].name;
-  __tzname[1] = (char *) tz_rules[1].name;
+  update_vars ();
+}
 
-  {
-    /* Keep __tzname_cur_max up to date.  */
-    size_t len0 = strlen (__tzname[0]);
-    size_t len1 = strlen (__tzname[1]);
-    if (len0 > __tzname_cur_max)
-      __tzname_cur_max = len0;
-    if (len1 > __tzname_cur_max)
-      __tzname_cur_max = len1;
-  }
+/* Interpret the TZ envariable.  */
+static void
+internal_function
+tzset_internal (always, explicit)
+     int always;
+     int explicit;
+{
+  static int is_initialized;
+  register const char *tz;
+
+  if (is_initialized && !always)
+    return;
+  is_initialized = 1;
+
+  /* Examine the TZ environment variable.  */
+  tz = getenv ("TZ");
+  if (tz == NULL && !explicit)
+    /* Use the site-wide default.  This is a file name which means we
+       would not see changes to the file if we compare only the file
+       name for change.  We want to notice file changes if tzset() has
+       been called explicitly.  Leave TZ as NULL in this case.  */
+    tz = TZDEFAULT;
+  if (tz && *tz == '\0')
+    /* User specified the empty string; use UTC explicitly.  */
+    tz = "Universal";
+
+  /* A leading colon means "implementation defined syntax".
+     We ignore the colon and always use the same algorithm:
+     try a data file, and if none exists parse the 1003.1 syntax.  */
+  if (tz && *tz == ':')
+    ++tz;
+
+  /* Check whether the value changes since the last run.  */
+  if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0)
+    /* No change, simply return.  */
+    return;
+
+  if (tz == NULL)
+    /* No user specification; use the site-wide default.  */
+    tz = TZDEFAULT;
+
+  tz_rules[0].name = NULL;
+  tz_rules[1].name = NULL;
+
+  /* Save the value of `tz'.  */
+  if (old_tz != NULL)
+    free (old_tz);
+  old_tz = tz ? __strdup (tz) : NULL;
+
+  /* Try to read a data file.  */
+  __tzfile_read (tz, 0, NULL);
+  if (__use_tzfile)
+    return;
+
+  /* No data file found.  Default to UTC if nothing specified.  */
+
+  if (tz == NULL || *tz == '\0'
+      || (TZDEFAULT != NULL && strcmp (tz, TZDEFAULT) == 0))
+    {
+      tz_rules[0].name = tz_rules[1].name = "UTC";
+      tz_rules[0].type = tz_rules[1].type = J0;
+      tz_rules[0].m = tz_rules[0].n = tz_rules[0].d = 0;
+      tz_rules[1].m = tz_rules[1].n = tz_rules[1].d = 0;
+      tz_rules[0].secs = tz_rules[1].secs = 0;
+      tz_rules[0].offset = tz_rules[1].offset = 0L;
+      tz_rules[0].change = tz_rules[1].change = (time_t) -1;
+      tz_rules[0].computed_for = tz_rules[1].computed_for = 0;
+      update_vars ();
+      return;
+    }
+
+  __tzset_parse_tz (tz);
 }
 \f
 /* Figure out the exact time (as a time_t) in YEAR
@@ -523,13 +537,34 @@ compute_change (rule, year)
 
 /* Figure out the correct timezone for TM and set `__tzname',
    `__timezone', and `__daylight' accordingly.  */
-static void
+void
 internal_function
-tz_compute (tm)
-     const struct tm *tm;
+__tz_compute (timer, tm, use_localtime)
+     time_t timer;
+     struct tm *tm;
+     int use_localtime;
 {
   compute_change (&tz_rules[0], 1900 + tm->tm_year);
   compute_change (&tz_rules[1], 1900 + tm->tm_year);
+
+  if (use_localtime)
+    {
+      int isdst;
+
+      /* We have to distinguish between northern and southern
+        hemisphere.  For the latter the daylight saving time
+        ends in the next year.  */
+      if (__builtin_expect (tz_rules[0].change
+                           > tz_rules[1].change, 0))
+       isdst = (timer < tz_rules[1].change
+                || timer >= tz_rules[0].change);
+      else
+       isdst = (timer >= tz_rules[0].change
+                && timer < tz_rules[1].change);
+      tm->tm_isdst = isdst;
+      tm->tm_zone = __tzname[isdst];
+      tm->tm_gmtoff = tz_rules[isdst].offset;
+    }
 }
 \f
 /* Reinterpret the TZ environment variable and set `tzname'.  */
@@ -583,35 +618,14 @@ __tz_convert (const time_t *timer, int use_localtime, struct tm *tp)
       if (! __offtime (timer, 0, tp))
        tp = NULL;
       else
-       tz_compute (tp);
+       __tz_compute (*timer, tp, use_localtime);
       leap_correction = 0L;
       leap_extra_secs = 0;
     }
 
   if (tp)
     {
-      if (use_localtime)
-       {
-         if (!__use_tzfile)
-           {
-             int isdst;
-
-             /* We have to distinguish between northern and southern
-                hemisphere.  For the latter the daylight saving time
-                ends in the next year.  */
-             if (__builtin_expect (tz_rules[0].change
-                                   > tz_rules[1].change, 0))
-               isdst = (*timer < tz_rules[1].change
-                        || *timer >= tz_rules[0].change);
-             else
-               isdst = (*timer >= tz_rules[0].change
-                        && *timer < tz_rules[1].change);
-             tp->tm_isdst = isdst;
-             tp->tm_zone = __tzname[isdst];
-             tp->tm_gmtoff = tz_rules[isdst].offset;
-           }
-       }
-      else
+      if (! use_localtime)
        {
          tp->tm_isdst = 0;
          tp->tm_zone = "GMT";
index 4c879163cf828e2f0d8a9fac97024809b623d0ad..00f899b85133de55205b3849f048b1dadf85b1f2 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999, 2000, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999, 2000, 2005, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Andreas Jaeger <aj@suse.de>, 1998.
 
@@ -44,7 +44,6 @@ static const struct test_times tests[] =
   { "America/Chicago", 1, 21600, {"CST", "CDT" }},
   { "America/Indiana/Indianapolis", 1, 18000, {"EST", "EDT" }},
   { "America/Los_Angeles", 1, 28800, {"PST", "PDT" }},
-  { "Asia/Tokyo", 1, -32400, {"JST", "JDT" }},
   { "Pacific/Auckland", 1, -43200, { "NZST", "NZDT" }},
   { NULL, 0, 0 }
 };