I have posted the attached message to comp.unix.solaris, so replies
should probably be posted there. I wanted to notify this mailing list
since the bug affects those who use multiple time zones in their
programs.
-------- Original Message --------
Subject: BUG: Solaris mktime with multiple timezones
Date: Fri, 06 Nov 1998 18:09:17 +0000
From: Scott Harrington <seh4(a)ix.netcom.com>
Newsgroups: comp.unix.solaris
I have uncovered a bug in the mktime() routine found in libc.so.1 and
libc.a on my SunOS 5.5.1 Generic_103640-12 sun4u sparc SUNW,Ultra-2
machine:
-rw-r--r-- 1 bin bin 1155756 Jun 23 1997 /usr/lib/libc.a
-rwxr-xr-x 1 bin bin 664760 Jun 23 1997 /usr/lib/libc.so.1
The error is that mktime() returns WRONG values when you're switching
between multiple time zones in a single program.
I have attached a small program which should determine if your system
has the bug or not. I make a mktime call in GB timezone, and then in
GMT timezone. The second lookup returns incorrect values. If you have
the bug, your output will be:
TZ=GB 892162800 0 0 0 10 3 98 5 99 1 should be
TZ=GB 892162800 0 0 0 10 3 98 5 99 1
TZ=GMT 892162800 0 0 23 9 3 98 4 98 0 should be
TZ=GMT 892166400 0 0 0 10 3 98 5 99 0
On systems which implement mktime correctly, the output will be:
TZ=GB 892162800 0 0 0 10 3 98 5 99 1 should be
TZ=GB 892162800 0 0 0 10 3 98 5 99 1
TZ=GMT 892166400 0 0 0 10 3 98 5 99 0 should be
TZ=GMT 892166400 0 0 0 10 3 98 5 99 0
I am curious to find out on which systems this bug exists. (2.6?
/opt/SUNWspro/lib/libc.so.1?) The public Sunsolve patch list apropos
'libc' only led me to patch 103612-46 (I already had 103612-30) and
applying this patch did not fix the problem.
I have a crude LD_PRELOAD workaround (using the implementation of mktime
from GNU glibc-2.0.7) for existing executables, if anyone is interested
let me know and I will mail it or post it to this newsgroup.
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
time_t t;
{
struct tm tmBuf = {0, 0, 0, 10, 3, 98, 0, 0, -1};
putenv("TZ=GB");
t = mktime(&tmBuf);
printf("TZ=GB %ld %d %d %d %d %d %d %d %d %d", t,
tmBuf.tm_sec, tmBuf.tm_min, tmBuf.tm_hour,
tmBuf.tm_mday, tmBuf.tm_mon, tmBuf.tm_year,
tmBuf.tm_wday, tmBuf.tm_yday, tmBuf.tm_isdst);
printf(" should be\n");
printf("TZ=GB 892162800 0 0 0 10 3 98 5 99 1\n");
}
printf("\n");
{
struct tm tmBuf = {0, 0, 0, 10, 3, 98, 0, 0, -1};
putenv("TZ=GMT");
t = mktime(&tmBuf);
printf("TZ=GMT %ld %d %d %d %d %d %d %d %d %d", t,
tmBuf.tm_sec, tmBuf.tm_min, tmBuf.tm_hour,
tmBuf.tm_mday, tmBuf.tm_mon, tmBuf.tm_year,
tmBuf.tm_wday, tmBuf.tm_yday, tmBuf.tm_isdst);
printf(" should be\n");
printf("TZ=GMT 892166400 0 0 0 10 3 98 5 99 0\n");
}
exit(0);
}