On Thu, Sep 25, 2008 at 03:48:37PM -0500, Aran Cox wrote:
> It seems that if the TZ environment is set (I tested America/Chicago and
> GMT) the c/python/perl programs all work.  If unset, (even though
> localtime exists, and corresponds to America/Chicago) all three
> programs fail to call mtime.  
> 
> I think may have been setting TZ and confused the issue slightly when
> testing the c and perl programs.  

My timezone is set to JST and TZ is usually unset.  And in fact
if I run the script with TZ set to America/Chicago, mktime() returned -1.
So I tried the C version with TZ=America/Chicago on a few machines which
also have the timezone set to JST:

  FreeBSD 4.9-RELEASE: NG
  FreeBSD 5.4-RELEASE: OK

According to FreeBSD CVSweb, FreeBSD 5.4-RELEASE has experienced
a vendor import of tzcode:
  
http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/stdtime/localtime.c?sortby=date#rev1.39

I think the essential part of the change that fixes mktime() is something
like attached to this message.  I'm using patched libc on my -DEVELOPMENT
machine and it seems to work with TZ=America/Chicago now.  But probably we
want to catch other fixes from FreeBSD.

Cheers.
--- localtime.c.orig    2008-08-28 12:26:09 +0900
+++ localtime.c 2008-09-26 12:52:26 +0900
@@ -1349,9 +1349,9 @@
 }
 
 static time_t
-time2(struct tm * const tmp,
+time2sub(struct tm * const tmp,
       void (* const funcp)(const time_t *, long, struct tm *),
-      const long offset, int * const okayp)
+      const long offset, int * const okayp, const int do_norm_secs)
 {
        const struct state *    sp;
        int                     dir;
@@ -1364,6 +1364,12 @@
 
        *okayp = FALSE;
        yourtm = *tmp;
+       if (do_norm_secs) {
+               if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
+                   SECSPERMIN)) {
+                       return WRONG;
+               }
+       }
        if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
                return WRONG;
        if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
@@ -1493,6 +1499,23 @@
 }
 
 static time_t
+time2(struct tm * const tmp,
+      void (* const funcp)(const time_t *, long, struct tm *),
+      const long offset, int * const okayp)
+{
+       time_t  t;
+
+       /*
+       ** First try without normalization of seconds
+       ** (in case tm_sec contains a value associated with a leap second).
+       ** If that fails, try with normalization of seconds.
+       */
+       t = time2sub(tmp, funcp, offset, okayp, FALSE);
+       return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);
+}
+
+
+static time_t
 time1(struct tm * const tmp,
       void (* const funcp)(const time_t *, long, struct tm *),
       const long offset)

Reply via email to