Does zic currently compile time zone abbreviations correctly?

Olson, Arthur David (NIH/NCI) [E] olsona at dc37a.nci.nih.gov
Fri Jul 27 15:29:03 UTC 2007


The typescript below seems to indicate that there's nothing amiss with Europe/London; do you get different results if you run "tzhead"?

			--ado

Script started on Fri 27 Jul 2007 11:24:37 AM EDT
lecserver$ cat tzhead.c
#include "private.h"

struct tzhead {
	char	tzh_magic[4];		/* TZ_MAGIC */
	char	tzh_version[1];		/* '\0' or '2' as of 2005 */
	char	tzh_reserved[15];	/* reserved--must be zero */
	char	tzh_ttisgmtcnt[4];	/* coded number of trans. time flags */
	char	tzh_ttisstdcnt[4];	/* coded number of trans. time flags */
	char	tzh_leapcnt[4];		/* coded number of leap seconds */
	char	tzh_timecnt[4];		/* coded number of transition times */
	char	tzh_typecnt[4];		/* coded number of local time types */
	char	tzh_charcnt[4];		/* coded number of abbr. chars */
};

static char *	progname;

static long long
detzcode64(codep)
const char * const	codep;
{
	register long long	result;
	register int		i;

	result = (codep[0] & 0x80) ? ~0L : 0L;
	for (i = 0; i < 8; ++i)
		result = result * 256 + (codep[i] & 0xff);
	return result;
}

static long long
detzcode(codep)
const char * const	codep;
{
	register long	result;
	register int	i;

	result = (codep[0] & 0x80) ? ~0L : 0L;
	for (i = 0; i < 4; ++i)
		result = (result << 8) | (codep[i] & 0xff);
	return result;
}

static void
wild2exit(cp, dp)
{
	(void) fprintf(stderr, "%s: wild result %s %s\n", progname, cp, dp);
	exit(1);
}

static void
handle(filename)
char *	filename;
{
	FILE *		fp;
	struct tzhead	tzh;
	long long	ll;
	char		c;
	int		i;
	int		pass;
	long		ttisgmtcnt;
	long		ttisstdcnt;
	long		leapcnt;
	long		timecnt;
	long		typecnt;
	long		charcnt;
	char		buf[8];
	struct tm	tm;

	fp = fopen(filename, "r");
	if (fp == NULL)
		wild2exit("result opening", filename);
	for (pass = 1; pass <= 2; ++pass) {
		if (fread(&tzh, sizeof tzh, 1, fp) != 1)
			wild2exit("result reading", filename);
		(void) printf("%s\tversion\t", filename);
		c = tzh.tzh_version[0];
		if (isascii(c) && isprint(c))
			(void) putchar(c);
		else	(void) printf("\\%o", c);
		(void) putchar('\n');
		ttisgmtcnt = detzcode(tzh.tzh_ttisgmtcnt);
		ttisstdcnt = detzcode(tzh.tzh_ttisstdcnt);
		leapcnt = detzcode(tzh.tzh_leapcnt);
		timecnt = detzcode(tzh.tzh_timecnt);
		typecnt = detzcode(tzh.tzh_typecnt);
		charcnt = detzcode(tzh.tzh_charcnt);
		(void) printf("%s\tttisgmtcnt\t%ld\n", filename, ttisgmtcnt);
		(void) printf("%s\tttisstdcnt\t%ld\n", filename, ttisstdcnt);
		(void) printf("%s\tleapcnt\t%ld\n", filename, leapcnt);
		(void) printf("%s\ttimecnt\t%ld\n", filename, timecnt);
		(void) printf("%s\ttypecnt\t%ld\n", filename, typecnt);
		(void) printf("%s\tcharcnt\t%ld\n", filename, charcnt);
		for (i = 0; i < timecnt; ++i) {
			if (fread(buf, pass * 4, 1, fp) != 1)
				wild2exit("result reading", filename);
			ll = (pass == 1) ? detzcode(buf) : detzcode64(buf);
			{
				time_t	l;

				l = ll;
				tm = *gmtime(&l);
			}
			(void) printf("%s\ttime[%d]\t%lld\t%s",
				filename, i, ll, asctime(&tm));
		}
		for (i = 0; i < timecnt; ++i) {
			if (fread(buf, 1, 1, fp) != 1)
				wild2exit("result reading", filename);
			(void) printf("%s\ttype[%d]\t%d\n",
				filename, i, buf[0]);
		}
		for (i = 0; i < typecnt; ++i) {
			long	l;

			if (fread(buf, 4, 1, fp) != 1)
				wild2exit("result reading", filename);
			l = detzcode(buf);
			(void) printf("%s\ttype[%d].offset\t%ld\n",
				filename, i, l);
			if (fread(buf, 1, 1, fp) != 1)
				wild2exit("result reading", filename);
			(void) printf("%s\ttype[%d].isdst\t%ld\n",
				filename, i, buf[0]);
			if (fread(buf, 1, 1, fp) != 1)
				wild2exit("result reading", filename);
			(void) printf("%s\ttype[%d].abbrind\t%ld\n",
				filename, i, buf[0]);
		}
		for (i = 0; i < charcnt; ++i) {
			if (fread(buf, 1, 1, fp) != 1)
				wild2exit("result reading", filename);
			(void) printf("%s\tabbr[%d]\t", filename, i);
			if (isascii(buf[0]) && isprint(buf[0]))
				(void) printf("%c", buf[0]);
			else if (buf[0] == '\0')
				(void) printf("\\0");
			else	(void) printf("\%03o", buf[0]);
			(void) printf("\n");
		}
		for (i = 0; i < ttisstdcnt; ++i) {
			if (fread(buf, 1, 1, fp) != 1)
				wild2exit("result reading", filename);
			(void) printf("%s\tisstd[%d]\t%d\n",
				filename, i, buf[0]);
		}
		for (i = 0; i < ttisgmtcnt; ++i) {
			if (fread(buf, 1, 1, fp) != 1)
				wild2exit("result reading", filename);
			(void) printf("%s\tisgmt[%d]\t%d\n",
				filename, i, buf[0]);
		}
		if (tzh.tzh_version[0] != '2')
			break;
	}
	if (fclose(fp) != 0) {
		(void) fprintf(stderr, "%s: wild result closing %s\n",
			progname, filename);
		exit(1);
	}
}

int
main(argc, argv)
int	argc;
char *	argv[];
{
	int	i;

	progname = argv[0];
	for (i = 1; i < argc; ++i)
		handle(argv[i]);
	exit(0);
}
lecserver$ make tzhead
cc -DTZDIR=\"/usr/local/etc/zoneinfo\"     tzhead.c   -o tzhead
lecserver$ tzhead tmp/etc/zoneinfo/Europe/London | grep abbr
tmp/etc/zoneinfo/Europe/London	type[0].abbrind	0
tmp/etc/zoneinfo/Europe/London	type[1].abbrind	4
tmp/etc/zoneinfo/Europe/London	type[2].abbrind	8
tmp/etc/zoneinfo/Europe/London	type[3].abbrind	0
tmp/etc/zoneinfo/Europe/London	type[4].abbrind	0
tmp/etc/zoneinfo/Europe/London	type[5].abbrind	4
tmp/etc/zoneinfo/Europe/London	type[6].abbrind	4
tmp/etc/zoneinfo/Europe/London	abbr[0]	B
tmp/etc/zoneinfo/Europe/London	abbr[1]	S
tmp/etc/zoneinfo/Europe/London	abbr[2]	T
tmp/etc/zoneinfo/Europe/London	abbr[3]	\0
tmp/etc/zoneinfo/Europe/London	abbr[4]	G
tmp/etc/zoneinfo/Europe/London	abbr[5]	M
tmp/etc/zoneinfo/Europe/London	abbr[6]	T
tmp/etc/zoneinfo/Europe/London	abbr[7]	\0
tmp/etc/zoneinfo/Europe/London	abbr[8]	B
tmp/etc/zoneinfo/Europe/London	abbr[9]	D
tmp/etc/zoneinfo/Europe/London	abbr[10]	S
tmp/etc/zoneinfo/Europe/London	abbr[11]	T
tmp/etc/zoneinfo/Europe/London	abbr[12]	\0
tmp/etc/zoneinfo/Europe/London	type[0].abbrind	0
tmp/etc/zoneinfo/Europe/London	type[1].abbrind	4
tmp/etc/zoneinfo/Europe/London	type[2].abbrind	8
tmp/etc/zoneinfo/Europe/London	type[3].abbrind	12
tmp/etc/zoneinfo/Europe/London	type[4].abbrind	4
tmp/etc/zoneinfo/Europe/London	type[5].abbrind	4
tmp/etc/zoneinfo/Europe/London	type[6].abbrind	8
tmp/etc/zoneinfo/Europe/London	type[7].abbrind	8
tmp/etc/zoneinfo/Europe/London	abbr[0]	L
tmp/etc/zoneinfo/Europe/London	abbr[1]	M
tmp/etc/zoneinfo/Europe/London	abbr[2]	T
tmp/etc/zoneinfo/Europe/London	abbr[3]	\0
tmp/etc/zoneinfo/Europe/London	abbr[4]	B
tmp/etc/zoneinfo/Europe/London	abbr[5]	S
tmp/etc/zoneinfo/Europe/London	abbr[6]	T
tmp/etc/zoneinfo/Europe/London	abbr[7]	\0
tmp/etc/zoneinfo/Europe/London	abbr[8]	G
tmp/etc/zoneinfo/Europe/London	abbr[9]	M
tmp/etc/zoneinfo/Europe/London	abbr[10]	T
tmp/etc/zoneinfo/Europe/London	abbr[11]	\0
tmp/etc/zoneinfo/Europe/London	abbr[12]	B
tmp/etc/zoneinfo/Europe/London	abbr[13]	D
tmp/etc/zoneinfo/Europe/London	abbr[14]	S
tmp/etc/zoneinfo/Europe/London	abbr[15]	T
tmp/etc/zoneinfo/Europe/London	abbr[16]	\0
lecserver$ exit

script done on Fri 27 Jul 2007 11:25:04 AM EDT



From: John B. Morrow [mailto:jmorrow at sendwordnow.com] 
Sent: Friday, July 27, 2007 2:29 AM
To: tz at lecserver.nci.nih.gov
Subject: Does zic currently compile time zone abbreviations correctly?

In the process of extracting time zone information from the zoneinfo database, I noticed that the abbreviation pointer break for quite a few time zones including Europe/London, Asia/Dubai, and quite a few others.  The problem seems to be in the compiled time zone files so I spent some time looking at zic.  What seems to be happening is that zic uses some criteria to determine of the abbreviation (and other info for types) is used and won't write it if it thinks it isn't needed.  The problem is that it doesn't adjust the indexes (tt_abbrind) that reference those abbreviations, so they'll point to bad data or empty strings.  My quick (and admittedly heavy handed fix) was to force zic to write all of the abbreviations, whether they are necessary or not.  If this really is a problem, it should probably be fixed at some point.  Please note that the data in our fairly recently updated Linux server has abbreviations that don't seem to work.
If I'm missing something or there is some other way more correct way to reference the abbreviations, please let me know.  I'm using tt_abbrind as per the tzfile man page and the tzcode2007f.tar.gz sources. 
John Morrow



More information about the tz mailing list