1 /* Compile .zi time zone data into TZif binary files.  */
2 
3 /*
4  * This file is in the public domain, so clarified as of
5  * 2006-07-17 by Arthur David Olson.
6  *
7  * IDENTIFICATION
8  *	  src/timezone/zic.c
9  */
10 
11 #include "postgres_fe.h"
12 
13 #include <fcntl.h>
14 #include <sys/stat.h>
15 #include <time.h>
16 
17 #include "pg_getopt.h"
18 
19 #include "private.h"
20 #include "tzfile.h"
21 
22 #define	ZIC_VERSION_PRE_2013 '2'
23 #define	ZIC_VERSION	'3'
24 
25 typedef int64 zic_t;
26 #define ZIC_MIN PG_INT64_MIN
27 #define ZIC_MAX PG_INT64_MAX
28 
29 #ifndef ZIC_MAX_ABBR_LEN_WO_WARN
30 #define ZIC_MAX_ABBR_LEN_WO_WARN	6
31 #endif							/* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
32 
33 #ifndef WIN32
34 #ifdef S_IRUSR
35 #define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
36 #else
37 #define MKDIR_UMASK 0755
38 #endif
39 #endif
40 /* Port to native MS-Windows and to ancient UNIX.  */
41 #if !defined S_ISDIR && defined S_IFDIR && defined S_IFMT
42 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
43 #endif
44 
45 /* The maximum ptrdiff_t value, for pre-C99 platforms.  */
46 #ifndef PTRDIFF_MAX
47 static ptrdiff_t const PTRDIFF_MAX = MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t));
48 #endif
49 
50 /*
51  * The type for line numbers.  In Postgres, use %d to format them; upstream
52  * uses PRIdMAX but we prefer not to rely on that, not least because it
53  * results in platform-dependent strings to be translated.
54  */
55 typedef int lineno_t;
56 
57 struct rule
58 {
59 	const char *r_filename;
60 	lineno_t	r_linenum;
61 	const char *r_name;
62 
63 	zic_t		r_loyear;		/* for example, 1986 */
64 	zic_t		r_hiyear;		/* for example, 1986 */
65 	bool		r_lowasnum;
66 	bool		r_hiwasnum;
67 
68 	int			r_month;		/* 0..11 */
69 
70 	int			r_dycode;		/* see below */
71 	int			r_dayofmonth;
72 	int			r_wday;
73 
74 	zic_t		r_tod;			/* time from midnight */
75 	bool		r_todisstd;		/* is r_tod standard time? */
76 	bool		r_todisut;		/* is r_tod UT? */
77 	bool		r_isdst;		/* is this daylight saving time? */
78 	zic_t		r_save;			/* offset from standard time */
79 	const char *r_abbrvar;		/* variable part of abbreviation */
80 
81 	bool		r_todo;			/* a rule to do (used in outzone) */
82 	zic_t		r_temp;			/* used in outzone */
83 };
84 
85 /*
86  *	r_dycode		r_dayofmonth	r_wday
87  */
88 
89 #define DC_DOM		0	/* 1..31 */ /* unused */
90 #define DC_DOWGEQ	1	/* 1..31 */ /* 0..6 (Sun..Sat) */
91 #define DC_DOWLEQ	2	/* 1..31 */ /* 0..6 (Sun..Sat) */
92 
93 struct zone
94 {
95 	const char *z_filename;
96 	lineno_t	z_linenum;
97 
98 	const char *z_name;
99 	zic_t		z_stdoff;
100 	char	   *z_rule;
101 	const char *z_format;
102 	char		z_format_specifier;
103 
104 	bool		z_isdst;
105 	zic_t		z_save;
106 
107 	struct rule *z_rules;
108 	ptrdiff_t	z_nrules;
109 
110 	struct rule z_untilrule;
111 	zic_t		z_untiltime;
112 };
113 
114 extern int	link(const char *target, const char *linkname);
115 #ifndef AT_SYMLINK_FOLLOW
116 #define linkat(targetdir, target, linknamedir, linkname, flag) \
117 	(itssymlink(target) ? (errno = ENOTSUP, -1) : link(target, linkname))
118 #endif
119 
120 static void memory_exhausted(const char *msg) pg_attribute_noreturn();
121 static void verror(const char *string, va_list args) pg_attribute_printf(1, 0);
122 static void error(const char *string,...) pg_attribute_printf(1, 2);
123 static void warning(const char *string,...) pg_attribute_printf(1, 2);
124 static void usage(FILE *stream, int status) pg_attribute_noreturn();
125 static void addtt(zic_t starttime, int type);
126 static int	addtype(zic_t, char const *, bool, bool, bool);
127 static void leapadd(zic_t, int, int);
128 static void adjleap(void);
129 static void associate(void);
130 static void dolink(const char *, const char *, bool);
131 static char **getfields(char *buf);
132 static zic_t gethms(const char *string, const char *errstring);
133 static zic_t getsave(char *, bool *);
134 static void inexpires(char **, int);
135 static void infile(const char *filename);
136 static void inleap(char **fields, int nfields);
137 static void inlink(char **fields, int nfields);
138 static void inrule(char **fields, int nfields);
139 static bool inzcont(char **fields, int nfields);
140 static bool inzone(char **fields, int nfields);
141 static bool inzsub(char **, int, bool);
142 static bool itsdir(char const *);
143 static bool itssymlink(char const *);
144 static bool is_alpha(char a);
145 static char lowerit(char);
146 static void mkdirs(char const *, bool);
147 static void newabbr(const char *abbr);
148 static zic_t oadd(zic_t t1, zic_t t2);
149 static void outzone(const struct zone *zp, ptrdiff_t ntzones);
150 static zic_t rpytime(const struct rule *rp, zic_t wantedy);
151 static void rulesub(struct rule *rp,
152 					const char *loyearp, const char *hiyearp,
153 					const char *typep, const char *monthp,
154 					const char *dayp, const char *timep);
155 static zic_t tadd(zic_t t1, zic_t t2);
156 
157 /* Bound on length of what %z can expand to.  */
158 enum
159 {
160 PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1};
161 
162 /* If true, work around a bug in Qt 5.6.1 and earlier, which mishandles
163    TZif files whose POSIX-TZ-style strings contain '<'; see
164    QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>.  This
165    workaround will no longer be needed when Qt 5.6.1 and earlier are
166    obsolete, say in the year 2021.  */
167 #ifndef WORK_AROUND_QTBUG_53071
168 enum
169 {
170 WORK_AROUND_QTBUG_53071 = true};
171 #endif
172 
173 static int	charcnt;
174 static bool errors;
175 static bool warnings;
176 static const char *filename;
177 static int	leapcnt;
178 static bool leapseen;
179 static zic_t leapminyear;
180 static zic_t leapmaxyear;
181 static lineno_t linenum;
182 static int	max_abbrvar_len = PERCENT_Z_LEN_BOUND;
183 static int	max_format_len;
184 static zic_t max_year;
185 static zic_t min_year;
186 static bool noise;
187 static bool print_abbrevs;
188 static zic_t print_cutoff;
189 static const char *rfilename;
190 static lineno_t rlinenum;
191 static const char *progname;
192 static ptrdiff_t timecnt;
193 static ptrdiff_t timecnt_alloc;
194 static int	typecnt;
195 
196 /*
197  * Line codes.
198  */
199 
200 #define LC_RULE		0
201 #define LC_ZONE		1
202 #define LC_LINK		2
203 #define LC_LEAP		3
204 #define LC_EXPIRES	4
205 
206 /*
207  * Which fields are which on a Zone line.
208  */
209 
210 #define ZF_NAME		1
211 #define ZF_STDOFF	2
212 #define ZF_RULE		3
213 #define ZF_FORMAT	4
214 #define ZF_TILYEAR	5
215 #define ZF_TILMONTH	6
216 #define ZF_TILDAY	7
217 #define ZF_TILTIME	8
218 #define ZONE_MINFIELDS	5
219 #define ZONE_MAXFIELDS	9
220 
221 /*
222  * Which fields are which on a Zone continuation line.
223  */
224 
225 #define ZFC_STDOFF	0
226 #define ZFC_RULE	1
227 #define ZFC_FORMAT	2
228 #define ZFC_TILYEAR	3
229 #define ZFC_TILMONTH	4
230 #define ZFC_TILDAY	5
231 #define ZFC_TILTIME	6
232 #define ZONEC_MINFIELDS	3
233 #define ZONEC_MAXFIELDS	7
234 
235 /*
236  * Which files are which on a Rule line.
237  */
238 
239 #define RF_NAME		1
240 #define RF_LOYEAR	2
241 #define RF_HIYEAR	3
242 #define RF_COMMAND	4
243 #define RF_MONTH	5
244 #define RF_DAY		6
245 #define RF_TOD		7
246 #define RF_SAVE		8
247 #define RF_ABBRVAR	9
248 #define RULE_FIELDS	10
249 
250 /*
251  * Which fields are which on a Link line.
252  */
253 
254 #define LF_TARGET	1
255 #define LF_LINKNAME	2
256 #define LINK_FIELDS	3
257 
258 /*
259  * Which fields are which on a Leap line.
260  */
261 
262 #define LP_YEAR		1
263 #define LP_MONTH	2
264 #define LP_DAY		3
265 #define LP_TIME		4
266 #define LP_CORR		5
267 #define LP_ROLL		6
268 #define LEAP_FIELDS	7
269 
270 /* Expires lines are like Leap lines, except without CORR and ROLL fields.  */
271 #define EXPIRES_FIELDS	5
272 
273 /*
274  * Year synonyms.
275  */
276 
277 #define YR_MINIMUM	0
278 #define YR_MAXIMUM	1
279 #define YR_ONLY		2
280 
281 static struct rule *rules;
282 static ptrdiff_t nrules;		/* number of rules */
283 static ptrdiff_t nrules_alloc;
284 
285 static struct zone *zones;
286 static ptrdiff_t nzones;		/* number of zones */
287 static ptrdiff_t nzones_alloc;
288 
289 struct link
290 {
291 	const char *l_filename;
292 	lineno_t	l_linenum;
293 	const char *l_target;
294 	const char *l_linkname;
295 };
296 
297 static struct link *links;
298 static ptrdiff_t nlinks;
299 static ptrdiff_t nlinks_alloc;
300 
301 struct lookup
302 {
303 	const char *l_word;
304 	const int	l_value;
305 };
306 
307 static struct lookup const *byword(const char *string,
308 								   const struct lookup *lp);
309 
310 static struct lookup const zi_line_codes[] = {
311 	{"Rule", LC_RULE},
312 	{"Zone", LC_ZONE},
313 	{"Link", LC_LINK},
314 	{NULL, 0}
315 };
316 static struct lookup const leap_line_codes[] = {
317 	{"Leap", LC_LEAP},
318 	{"Expires", LC_EXPIRES},
319 	{NULL, 0}
320 };
321 
322 static struct lookup const mon_names[] = {
323 	{"January", TM_JANUARY},
324 	{"February", TM_FEBRUARY},
325 	{"March", TM_MARCH},
326 	{"April", TM_APRIL},
327 	{"May", TM_MAY},
328 	{"June", TM_JUNE},
329 	{"July", TM_JULY},
330 	{"August", TM_AUGUST},
331 	{"September", TM_SEPTEMBER},
332 	{"October", TM_OCTOBER},
333 	{"November", TM_NOVEMBER},
334 	{"December", TM_DECEMBER},
335 	{NULL, 0}
336 };
337 
338 static struct lookup const wday_names[] = {
339 	{"Sunday", TM_SUNDAY},
340 	{"Monday", TM_MONDAY},
341 	{"Tuesday", TM_TUESDAY},
342 	{"Wednesday", TM_WEDNESDAY},
343 	{"Thursday", TM_THURSDAY},
344 	{"Friday", TM_FRIDAY},
345 	{"Saturday", TM_SATURDAY},
346 	{NULL, 0}
347 };
348 
349 static struct lookup const lasts[] = {
350 	{"last-Sunday", TM_SUNDAY},
351 	{"last-Monday", TM_MONDAY},
352 	{"last-Tuesday", TM_TUESDAY},
353 	{"last-Wednesday", TM_WEDNESDAY},
354 	{"last-Thursday", TM_THURSDAY},
355 	{"last-Friday", TM_FRIDAY},
356 	{"last-Saturday", TM_SATURDAY},
357 	{NULL, 0}
358 };
359 
360 static struct lookup const begin_years[] = {
361 	{"minimum", YR_MINIMUM},
362 	{"maximum", YR_MAXIMUM},
363 	{NULL, 0}
364 };
365 
366 static struct lookup const end_years[] = {
367 	{"minimum", YR_MINIMUM},
368 	{"maximum", YR_MAXIMUM},
369 	{"only", YR_ONLY},
370 	{NULL, 0}
371 };
372 
373 static struct lookup const leap_types[] = {
374 	{"Rolling", true},
375 	{"Stationary", false},
376 	{NULL, 0}
377 };
378 
379 static const int len_months[2][MONSPERYEAR] = {
380 	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
381 	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
382 };
383 
384 static const int len_years[2] = {
385 	DAYSPERNYEAR, DAYSPERLYEAR
386 };
387 
388 static struct attype
389 {
390 	zic_t		at;
391 	bool		dontmerge;
392 	unsigned char type;
393 }		   *attypes;
394 static zic_t utoffs[TZ_MAX_TYPES];
395 static char isdsts[TZ_MAX_TYPES];
396 static unsigned char desigidx[TZ_MAX_TYPES];
397 static bool ttisstds[TZ_MAX_TYPES];
398 static bool ttisuts[TZ_MAX_TYPES];
399 static char chars[TZ_MAX_CHARS];
400 static zic_t trans[TZ_MAX_LEAPS];
401 static zic_t corr[TZ_MAX_LEAPS];
402 static char roll[TZ_MAX_LEAPS];
403 
404 /*
405  * Memory allocation.
406  */
407 
408 static void
memory_exhausted(const char * msg)409 memory_exhausted(const char *msg)
410 {
411 	fprintf(stderr, _("%s: Memory exhausted: %s\n"), progname, msg);
412 	exit(EXIT_FAILURE);
413 }
414 
415 static size_t
size_product(size_t nitems,size_t itemsize)416 size_product(size_t nitems, size_t itemsize)
417 {
418 	if (SIZE_MAX / itemsize < nitems)
419 		memory_exhausted(_("size overflow"));
420 	return nitems * itemsize;
421 }
422 
423 static void *
memcheck(void * ptr)424 memcheck(void *ptr)
425 {
426 	if (ptr == NULL)
427 		memory_exhausted(strerror(errno));
428 	return ptr;
429 }
430 
431 static void *
emalloc(size_t size)432 emalloc(size_t size)
433 {
434 	return memcheck(malloc(size));
435 }
436 
437 static void *
erealloc(void * ptr,size_t size)438 erealloc(void *ptr, size_t size)
439 {
440 	return memcheck(realloc(ptr, size));
441 }
442 
443 static char *
ecpyalloc(char const * str)444 ecpyalloc(char const *str)
445 {
446 	return memcheck(strdup(str));
447 }
448 
449 static void *
growalloc(void * ptr,size_t itemsize,ptrdiff_t nitems,ptrdiff_t * nitems_alloc)450 growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
451 {
452 	if (nitems < *nitems_alloc)
453 		return ptr;
454 	else
455 	{
456 		ptrdiff_t	nitems_max = PTRDIFF_MAX - WORK_AROUND_QTBUG_53071;
457 		ptrdiff_t	amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX;
458 
459 		if ((amax - 1) / 3 * 2 < *nitems_alloc)
460 			memory_exhausted(_("integer overflow"));
461 		*nitems_alloc += (*nitems_alloc >> 1) + 1;
462 		return erealloc(ptr, size_product(*nitems_alloc, itemsize));
463 	}
464 }
465 
466 /*
467  * Error handling.
468  */
469 
470 static void
eats(char const * name,lineno_t num,char const * rname,lineno_t rnum)471 eats(char const *name, lineno_t num, char const *rname, lineno_t rnum)
472 {
473 	filename = name;
474 	linenum = num;
475 	rfilename = rname;
476 	rlinenum = rnum;
477 }
478 
479 static void
eat(char const * name,lineno_t num)480 eat(char const *name, lineno_t num)
481 {
482 	eats(name, num, NULL, -1);
483 }
484 
485 static void
verror(const char * string,va_list args)486 verror(const char *string, va_list args)
487 {
488 	/*
489 	 * Match the format of "cc" to allow sh users to zic ... 2>&1 | error -t
490 	 * "*" -v on BSD systems.
491 	 */
492 	if (filename)
493 		fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
494 	vfprintf(stderr, string, args);
495 	if (rfilename != NULL)
496 		fprintf(stderr, _(" (rule from \"%s\", line %d)"),
497 				rfilename, rlinenum);
498 	fprintf(stderr, "\n");
499 }
500 
501 static void
error(const char * string,...)502 error(const char *string,...)
503 {
504 	va_list		args;
505 
506 	va_start(args, string);
507 	verror(string, args);
508 	va_end(args);
509 	errors = true;
510 }
511 
512 static void
warning(const char * string,...)513 warning(const char *string,...)
514 {
515 	va_list		args;
516 
517 	fprintf(stderr, _("warning: "));
518 	va_start(args, string);
519 	verror(string, args);
520 	va_end(args);
521 	warnings = true;
522 }
523 
524 static void
close_file(FILE * stream,char const * dir,char const * name)525 close_file(FILE *stream, char const *dir, char const *name)
526 {
527 	char const *e = (ferror(stream) ? _("I/O error")
528 					 : fclose(stream) != 0 ? strerror(errno) : NULL);
529 
530 	if (e)
531 	{
532 		fprintf(stderr, "%s: %s%s%s%s%s\n", progname,
533 				dir ? dir : "", dir ? "/" : "",
534 				name ? name : "", name ? ": " : "",
535 				e);
536 		exit(EXIT_FAILURE);
537 	}
538 }
539 
540 static void
usage(FILE * stream,int status)541 usage(FILE *stream, int status)
542 {
543 	fprintf(stream,
544 			_("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -P ] \\\n"
545 			  "\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]"
546 			  " [ -L leapseconds ] \\\n"
547 			  "\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -t localtime-link ] \\\n"
548 			  "\t[ filename ... ]\n\n"
549 			  "Report bugs to %s.\n"),
550 			progname, progname, PACKAGE_BUGREPORT);
551 	if (status == EXIT_SUCCESS)
552 		close_file(stream, NULL, NULL);
553 	exit(status);
554 }
555 
556 /* Change the working directory to DIR, possibly creating DIR and its
557    ancestors.  After this is done, all files are accessed with names
558    relative to DIR.  */
559 static void
change_directory(char const * dir)560 change_directory(char const *dir)
561 {
562 	if (chdir(dir) != 0)
563 	{
564 		int			chdir_errno = errno;
565 
566 		if (chdir_errno == ENOENT)
567 		{
568 			mkdirs(dir, false);
569 			chdir_errno = chdir(dir) == 0 ? 0 : errno;
570 		}
571 		if (chdir_errno != 0)
572 		{
573 			fprintf(stderr, _("%s: Can't chdir to %s: %s\n"),
574 					progname, dir, strerror(chdir_errno));
575 			exit(EXIT_FAILURE);
576 		}
577 	}
578 }
579 
580 #define TIME_T_BITS_IN_FILE 64
581 
582 /* The minimum and maximum values representable in a TZif file.  */
583 static zic_t const min_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
584 static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
585 
586 /* The minimum, and one less than the maximum, values specified by
587    the -r option.  These default to MIN_TIME and MAX_TIME.  */
588 static zic_t lo_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
589 static zic_t hi_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
590 
591 /* The time specified by an Expires line, or negative if no such line.  */
592 static zic_t leapexpires = -1;
593 
594 /* The time specified by an #expires comment, or negative if no such line.  */
595 static zic_t comment_leapexpires = -1;
596 
597 /* Set the time range of the output to TIMERANGE.
598    Return true if successful.  */
599 static bool
timerange_option(char * timerange)600 timerange_option(char *timerange)
601 {
602 	int64		lo = min_time,
603 				hi = max_time;
604 	char	   *lo_end = timerange,
605 			   *hi_end;
606 
607 	if (*timerange == '@')
608 	{
609 		errno = 0;
610 		lo = strtoimax(timerange + 1, &lo_end, 10);
611 		if (lo_end == timerange + 1 || (lo == PG_INT64_MAX && errno == ERANGE))
612 			return false;
613 	}
614 	hi_end = lo_end;
615 	if (lo_end[0] == '/' && lo_end[1] == '@')
616 	{
617 		errno = 0;
618 		hi = strtoimax(lo_end + 2, &hi_end, 10);
619 		if (hi_end == lo_end + 2 || hi == PG_INT64_MIN)
620 			return false;
621 		hi -= !(hi == PG_INT64_MAX && errno == ERANGE);
622 	}
623 	if (*hi_end || hi < lo || max_time < lo || hi < min_time)
624 		return false;
625 	lo_time = lo < min_time ? min_time : lo;
626 	hi_time = max_time < hi ? max_time : hi;
627 	return true;
628 }
629 
630 static const char *psxrules;
631 static const char *lcltime;
632 static const char *directory;
633 static const char *leapsec;
634 static const char *tzdefault;
635 
636 /* -1 if the TZif output file should be slim, 0 if default, 1 if the
637    output should be fat for backward compatibility.  ZIC_BLOAT_DEFAULT
638    determines the default.  */
639 static int	bloat;
640 
641 static bool
want_bloat(void)642 want_bloat(void)
643 {
644 	return 0 <= bloat;
645 }
646 
647 #ifndef ZIC_BLOAT_DEFAULT
648 #define ZIC_BLOAT_DEFAULT "slim"
649 #endif
650 
651 int
main(int argc,char ** argv)652 main(int argc, char **argv)
653 {
654 	int			c,
655 				k;
656 	ptrdiff_t	i,
657 				j;
658 	bool		timerange_given = false;
659 
660 #ifndef WIN32
661 	umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
662 #endif
663 	progname = argv[0];
664 	if (TYPE_BIT(zic_t) < 64)
665 	{
666 		fprintf(stderr, "%s: %s\n", progname,
667 				_("wild compilation-time specification of zic_t"));
668 		return EXIT_FAILURE;
669 	}
670 	for (k = 1; k < argc; k++)
671 		if (strcmp(argv[k], "--version") == 0)
672 		{
673 			printf("zic %s\n", PG_VERSION);
674 			close_file(stdout, NULL, NULL);
675 			return EXIT_SUCCESS;
676 		}
677 		else if (strcmp(argv[k], "--help") == 0)
678 		{
679 			usage(stdout, EXIT_SUCCESS);
680 		}
681 	while ((c = getopt(argc, argv, "b:d:l:L:p:Pr:st:vy:")) != EOF && c != -1)
682 		switch (c)
683 		{
684 			default:
685 				usage(stderr, EXIT_FAILURE);
686 			case 'b':
687 				if (strcmp(optarg, "slim") == 0)
688 				{
689 					if (0 < bloat)
690 						error(_("incompatible -b options"));
691 					bloat = -1;
692 				}
693 				else if (strcmp(optarg, "fat") == 0)
694 				{
695 					if (bloat < 0)
696 						error(_("incompatible -b options"));
697 					bloat = 1;
698 				}
699 				else
700 					error(_("invalid option: -b '%s'"), optarg);
701 				break;
702 			case 'd':
703 				if (directory == NULL)
704 					directory = strdup(optarg);
705 				else
706 				{
707 					fprintf(stderr,
708 							_("%s: More than one -d option specified\n"),
709 							progname);
710 					return EXIT_FAILURE;
711 				}
712 				break;
713 			case 'l':
714 				if (lcltime == NULL)
715 					lcltime = strdup(optarg);
716 				else
717 				{
718 					fprintf(stderr,
719 							_("%s: More than one -l option specified\n"),
720 							progname);
721 					return EXIT_FAILURE;
722 				}
723 				break;
724 			case 'p':
725 				if (psxrules == NULL)
726 					psxrules = strdup(optarg);
727 				else
728 				{
729 					fprintf(stderr,
730 							_("%s: More than one -p option specified\n"),
731 							progname);
732 					return EXIT_FAILURE;
733 				}
734 				break;
735 			case 't':
736 				if (tzdefault != NULL)
737 				{
738 					fprintf(stderr,
739 							_("%s: More than one -t option"
740 							  " specified\n"),
741 							progname);
742 					return EXIT_FAILURE;
743 				}
744 				tzdefault = optarg;
745 				break;
746 			case 'y':
747 				warning(_("-y ignored"));
748 				break;
749 			case 'L':
750 				if (leapsec == NULL)
751 					leapsec = strdup(optarg);
752 				else
753 				{
754 					fprintf(stderr,
755 							_("%s: More than one -L option specified\n"),
756 							progname);
757 					return EXIT_FAILURE;
758 				}
759 				break;
760 			case 'v':
761 				noise = true;
762 				break;
763 			case 'P':
764 				print_abbrevs = true;
765 				print_cutoff = time(NULL);
766 				break;
767 			case 'r':
768 				if (timerange_given)
769 				{
770 					fprintf(stderr,
771 							_("%s: More than one -r option specified\n"),
772 							progname);
773 					return EXIT_FAILURE;
774 				}
775 				if (!timerange_option(optarg))
776 				{
777 					fprintf(stderr,
778 							_("%s: invalid time range: %s\n"),
779 							progname, optarg);
780 					return EXIT_FAILURE;
781 				}
782 				timerange_given = true;
783 				break;
784 			case 's':
785 				warning(_("-s ignored"));
786 				break;
787 		}
788 	if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
789 		usage(stderr, EXIT_FAILURE);	/* usage message by request */
790 	if (bloat == 0)
791 	{
792 		static char const bloat_default[] = ZIC_BLOAT_DEFAULT;
793 
794 		if (strcmp(bloat_default, "slim") == 0)
795 			bloat = -1;
796 		else if (strcmp(bloat_default, "fat") == 0)
797 			bloat = 1;
798 		else
799 			abort();			/* Configuration error.  */
800 	}
801 	if (directory == NULL)
802 		directory = "data";
803 	if (tzdefault == NULL)
804 		tzdefault = TZDEFAULT;
805 
806 	if (optind < argc && leapsec != NULL)
807 	{
808 		infile(leapsec);
809 		adjleap();
810 	}
811 
812 	for (k = optind; k < argc; k++)
813 		infile(argv[k]);
814 	if (errors)
815 		return EXIT_FAILURE;
816 	associate();
817 	change_directory(directory);
818 	for (i = 0; i < nzones; i = j)
819 	{
820 		/*
821 		 * Find the next non-continuation zone entry.
822 		 */
823 		for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
824 			continue;
825 		outzone(&zones[i], j - i);
826 	}
827 
828 	/*
829 	 * Make links.
830 	 */
831 	for (i = 0; i < nlinks; ++i)
832 	{
833 		eat(links[i].l_filename, links[i].l_linenum);
834 		dolink(links[i].l_target, links[i].l_linkname, false);
835 		if (noise)
836 			for (j = 0; j < nlinks; ++j)
837 				if (strcmp(links[i].l_linkname,
838 						   links[j].l_target) == 0)
839 					warning(_("link to link"));
840 	}
841 	if (lcltime != NULL)
842 	{
843 		eat(_("command line"), 1);
844 		dolink(lcltime, tzdefault, true);
845 	}
846 	if (psxrules != NULL)
847 	{
848 		eat(_("command line"), 1);
849 		dolink(psxrules, TZDEFRULES, true);
850 	}
851 	if (warnings && (ferror(stderr) || fclose(stderr) != 0))
852 		return EXIT_FAILURE;
853 	return errors ? EXIT_FAILURE : EXIT_SUCCESS;
854 }
855 
856 static bool
componentcheck(char const * name,char const * component,char const * component_end)857 componentcheck(char const *name, char const *component,
858 			   char const *component_end)
859 {
860 	enum
861 	{
862 	component_len_max = 14};
863 	ptrdiff_t	component_len = component_end - component;
864 
865 	if (component_len == 0)
866 	{
867 		if (!*name)
868 			error(_("empty file name"));
869 		else
870 			error(_(component == name
871 					? "file name '%s' begins with '/'"
872 					: *component_end
873 					? "file name '%s' contains '//'"
874 					: "file name '%s' ends with '/'"),
875 				  name);
876 		return false;
877 	}
878 	if (0 < component_len && component_len <= 2
879 		&& component[0] == '.' && component_end[-1] == '.')
880 	{
881 		int			len = component_len;
882 
883 		error(_("file name '%s' contains '%.*s' component"),
884 			  name, len, component);
885 		return false;
886 	}
887 	if (noise)
888 	{
889 		if (0 < component_len && component[0] == '-')
890 			warning(_("file name '%s' component contains leading '-'"),
891 					name);
892 		if (component_len_max < component_len)
893 			warning(_("file name '%s' contains overlength component"
894 					  " '%.*s...'"),
895 					name, component_len_max, component);
896 	}
897 	return true;
898 }
899 
900 static bool
namecheck(const char * name)901 namecheck(const char *name)
902 {
903 	char const *cp;
904 
905 	/* Benign characters in a portable file name.  */
906 	static char const benign[] =
907 	"-/_"
908 	"abcdefghijklmnopqrstuvwxyz"
909 	"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
910 
911 	/*
912 	 * Non-control chars in the POSIX portable character set, excluding the
913 	 * benign characters.
914 	 */
915 	static char const printable_and_not_benign[] =
916 	" !\"#$%&'()*+,.0123456789:;<=>?@[\\]^`{|}~";
917 
918 	char const *component = name;
919 
920 	for (cp = name; *cp; cp++)
921 	{
922 		unsigned char c = *cp;
923 
924 		if (noise && !strchr(benign, c))
925 		{
926 			warning((strchr(printable_and_not_benign, c)
927 					 ? _("file name '%s' contains byte '%c'")
928 					 : _("file name '%s' contains byte '\\%o'")),
929 					name, c);
930 		}
931 		if (c == '/')
932 		{
933 			if (!componentcheck(name, component, cp))
934 				return false;
935 			component = cp + 1;
936 		}
937 	}
938 	return componentcheck(name, component, cp);
939 }
940 
941 /*
942  * Create symlink contents suitable for symlinking FROM to TO, as a
943  * freshly allocated string.  FROM should be a relative file name, and
944  * is relative to the global variable DIRECTORY.  TO can be either
945  * relative or absolute.
946  */
947 #ifdef HAVE_SYMLINK
948 static char *
relname(char const * target,char const * linkname)949 relname(char const *target, char const *linkname)
950 {
951 	size_t		i,
952 				taillen,
953 				dotdotetcsize;
954 	size_t		dir_len = 0,
955 				dotdots = 0,
956 				linksize = SIZE_MAX;
957 	char const *f = target;
958 	char	   *result = NULL;
959 
960 	if (*linkname == '/')
961 	{
962 		/* Make F absolute too.  */
963 		size_t		len = strlen(directory);
964 		bool		needslash = len && directory[len - 1] != '/';
965 
966 		linksize = len + needslash + strlen(target) + 1;
967 		f = result = emalloc(linksize);
968 		strcpy(result, directory);
969 		result[len] = '/';
970 		strcpy(result + len + needslash, target);
971 	}
972 	for (i = 0; f[i] && f[i] == linkname[i]; i++)
973 		if (f[i] == '/')
974 			dir_len = i + 1;
975 	for (; linkname[i]; i++)
976 		dotdots += linkname[i] == '/' && linkname[i - 1] != '/';
977 	taillen = strlen(f + dir_len);
978 	dotdotetcsize = 3 * dotdots + taillen + 1;
979 	if (dotdotetcsize <= linksize)
980 	{
981 		if (!result)
982 			result = emalloc(dotdotetcsize);
983 		for (i = 0; i < dotdots; i++)
984 			memcpy(result + 3 * i, "../", 3);
985 		memmove(result + 3 * dotdots, f + dir_len, taillen + 1);
986 	}
987 	return result;
988 }
989 #endif							/* HAVE_SYMLINK */
990 
991 /* Hard link FROM to TO, following any symbolic links.
992    Return 0 if successful, an error number otherwise.  */
993 static int
hardlinkerr(char const * target,char const * linkname)994 hardlinkerr(char const *target, char const *linkname)
995 {
996 	int			r = linkat(AT_FDCWD, target, AT_FDCWD, linkname, AT_SYMLINK_FOLLOW);
997 
998 	return r == 0 ? 0 : errno;
999 }
1000 
1001 static void
dolink(char const * target,char const * linkname,bool staysymlink)1002 dolink(char const *target, char const *linkname, bool staysymlink)
1003 {
1004 	bool		remove_only = strcmp(target, "-") == 0;
1005 	bool		linkdirs_made = false;
1006 	int			link_errno;
1007 
1008 	/*
1009 	 * We get to be careful here since there's a fair chance of root running
1010 	 * us.
1011 	 */
1012 	if (!remove_only && itsdir(target))
1013 	{
1014 		fprintf(stderr, _("%s: linking target %s/%s failed: %s\n"),
1015 				progname, directory, target, strerror(EPERM));
1016 		exit(EXIT_FAILURE);
1017 	}
1018 	if (staysymlink)
1019 		staysymlink = itssymlink(linkname);
1020 	if (remove(linkname) == 0)
1021 		linkdirs_made = true;
1022 	else if (errno != ENOENT)
1023 	{
1024 		char const *e = strerror(errno);
1025 
1026 		fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"),
1027 				progname, directory, linkname, e);
1028 		exit(EXIT_FAILURE);
1029 	}
1030 	if (remove_only)
1031 		return;
1032 	link_errno = staysymlink ? ENOTSUP : hardlinkerr(target, linkname);
1033 	if (link_errno == ENOENT && !linkdirs_made)
1034 	{
1035 		mkdirs(linkname, true);
1036 		linkdirs_made = true;
1037 		link_errno = hardlinkerr(target, linkname);
1038 	}
1039 	if (link_errno != 0)
1040 	{
1041 #ifdef HAVE_SYMLINK
1042 		bool		absolute = *target == '/';
1043 		char	   *linkalloc = absolute ? NULL : relname(target, linkname);
1044 		char const *contents = absolute ? target : linkalloc;
1045 		int			symlink_errno = symlink(contents, linkname) == 0 ? 0 : errno;
1046 
1047 		if (!linkdirs_made
1048 			&& (symlink_errno == ENOENT || symlink_errno == ENOTSUP))
1049 		{
1050 			mkdirs(linkname, true);
1051 			if (symlink_errno == ENOENT)
1052 				symlink_errno = symlink(contents, linkname) == 0 ? 0 : errno;
1053 		}
1054 		free(linkalloc);
1055 		if (symlink_errno == 0)
1056 		{
1057 			if (link_errno != ENOTSUP)
1058 				warning(_("symbolic link used because hard link failed: %s"),
1059 						strerror(link_errno));
1060 		}
1061 		else
1062 #endif							/* HAVE_SYMLINK */
1063 		{
1064 			FILE	   *fp,
1065 					   *tp;
1066 			int			c;
1067 
1068 			fp = fopen(target, "rb");
1069 			if (!fp)
1070 			{
1071 				char const *e = strerror(errno);
1072 
1073 				fprintf(stderr, _("%s: Can't read %s/%s: %s\n"),
1074 						progname, directory, target, e);
1075 				exit(EXIT_FAILURE);
1076 			}
1077 			tp = fopen(linkname, "wb");
1078 			if (!tp)
1079 			{
1080 				char const *e = strerror(errno);
1081 
1082 				fprintf(stderr, _("%s: Can't create %s/%s: %s\n"),
1083 						progname, directory, linkname, e);
1084 				exit(EXIT_FAILURE);
1085 			}
1086 			while ((c = getc(fp)) != EOF)
1087 				putc(c, tp);
1088 			close_file(fp, directory, target);
1089 			close_file(tp, directory, linkname);
1090 			if (link_errno != ENOTSUP)
1091 				warning(_("copy used because hard link failed: %s"),
1092 						strerror(link_errno));
1093 #ifdef HAVE_SYMLINK
1094 			else if (symlink_errno != ENOTSUP)
1095 				warning(_("copy used because symbolic link failed: %s"),
1096 						strerror(symlink_errno));
1097 #endif
1098 		}
1099 	}
1100 }
1101 
1102 /* Return true if NAME is a directory.  */
1103 static bool
itsdir(char const * name)1104 itsdir(char const *name)
1105 {
1106 	struct stat st;
1107 	int			res = stat(name, &st);
1108 #ifdef S_ISDIR
1109 	if (res == 0)
1110 		return S_ISDIR(st.st_mode) != 0;
1111 #endif
1112 	if (res == 0 || errno == EOVERFLOW)
1113 	{
1114 		size_t		n = strlen(name);
1115 		char	   *nameslashdot = emalloc(n + 3);
1116 		bool		dir;
1117 
1118 		memcpy(nameslashdot, name, n);
1119 		strcpy(&nameslashdot[n], &"/."[!(n && name[n - 1] != '/')]);
1120 		dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW;
1121 		free(nameslashdot);
1122 		return dir;
1123 	}
1124 	return false;
1125 }
1126 
1127 /* Return true if NAME is a symbolic link.  */
1128 static bool
itssymlink(char const * name)1129 itssymlink(char const *name)
1130 {
1131 #ifdef HAVE_SYMLINK
1132 	char		c;
1133 
1134 	return 0 <= readlink(name, &c, 1);
1135 #else
1136 	return false;
1137 #endif
1138 }
1139 
1140 /*
1141  * Associate sets of rules with zones.
1142  */
1143 
1144 /*
1145  * Sort by rule name.
1146  */
1147 
1148 static int
rcomp(const void * cp1,const void * cp2)1149 rcomp(const void *cp1, const void *cp2)
1150 {
1151 	return strcmp(((const struct rule *) cp1)->r_name,
1152 				  ((const struct rule *) cp2)->r_name);
1153 }
1154 
1155 static void
associate(void)1156 associate(void)
1157 {
1158 	struct zone *zp;
1159 	struct rule *rp;
1160 	ptrdiff_t	i,
1161 				j,
1162 				base,
1163 				out;
1164 
1165 	if (nrules != 0)
1166 	{
1167 		qsort(rules, nrules, sizeof *rules, rcomp);
1168 		for (i = 0; i < nrules - 1; ++i)
1169 		{
1170 			if (strcmp(rules[i].r_name,
1171 					   rules[i + 1].r_name) != 0)
1172 				continue;
1173 			if (strcmp(rules[i].r_filename,
1174 					   rules[i + 1].r_filename) == 0)
1175 				continue;
1176 			eat(rules[i].r_filename, rules[i].r_linenum);
1177 			warning(_("same rule name in multiple files"));
1178 			eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);
1179 			warning(_("same rule name in multiple files"));
1180 			for (j = i + 2; j < nrules; ++j)
1181 			{
1182 				if (strcmp(rules[i].r_name,
1183 						   rules[j].r_name) != 0)
1184 					break;
1185 				if (strcmp(rules[i].r_filename,
1186 						   rules[j].r_filename) == 0)
1187 					continue;
1188 				if (strcmp(rules[i + 1].r_filename,
1189 						   rules[j].r_filename) == 0)
1190 					continue;
1191 				break;
1192 			}
1193 			i = j - 1;
1194 		}
1195 	}
1196 	for (i = 0; i < nzones; ++i)
1197 	{
1198 		zp = &zones[i];
1199 		zp->z_rules = NULL;
1200 		zp->z_nrules = 0;
1201 	}
1202 	for (base = 0; base < nrules; base = out)
1203 	{
1204 		rp = &rules[base];
1205 		for (out = base + 1; out < nrules; ++out)
1206 			if (strcmp(rp->r_name, rules[out].r_name) != 0)
1207 				break;
1208 		for (i = 0; i < nzones; ++i)
1209 		{
1210 			zp = &zones[i];
1211 			if (strcmp(zp->z_rule, rp->r_name) != 0)
1212 				continue;
1213 			zp->z_rules = rp;
1214 			zp->z_nrules = out - base;
1215 		}
1216 	}
1217 	for (i = 0; i < nzones; ++i)
1218 	{
1219 		zp = &zones[i];
1220 		if (zp->z_nrules == 0)
1221 		{
1222 			/*
1223 			 * Maybe we have a local standard time offset.
1224 			 */
1225 			eat(zp->z_filename, zp->z_linenum);
1226 			zp->z_save = getsave(zp->z_rule, &zp->z_isdst);
1227 
1228 			/*
1229 			 * Note, though, that if there's no rule, a '%s' in the format is
1230 			 * a bad thing.
1231 			 */
1232 			if (zp->z_format_specifier == 's')
1233 				error("%s", _("%s in ruleless zone"));
1234 		}
1235 	}
1236 	if (errors)
1237 		exit(EXIT_FAILURE);
1238 }
1239 
1240 static void
infile(const char * name)1241 infile(const char *name)
1242 {
1243 	FILE	   *fp;
1244 	char	  **fields;
1245 	char	   *cp;
1246 	const struct lookup *lp;
1247 	int			nfields;
1248 	bool		wantcont;
1249 	lineno_t	num;
1250 	char		buf[BUFSIZ];
1251 
1252 	if (strcmp(name, "-") == 0)
1253 	{
1254 		name = _("standard input");
1255 		fp = stdin;
1256 	}
1257 	else if ((fp = fopen(name, "r")) == NULL)
1258 	{
1259 		const char *e = strerror(errno);
1260 
1261 		fprintf(stderr, _("%s: Cannot open %s: %s\n"),
1262 				progname, name, e);
1263 		exit(EXIT_FAILURE);
1264 	}
1265 	wantcont = false;
1266 	for (num = 1;; ++num)
1267 	{
1268 		eat(name, num);
1269 		if (fgets(buf, sizeof buf, fp) != buf)
1270 			break;
1271 		cp = strchr(buf, '\n');
1272 		if (cp == NULL)
1273 		{
1274 			error(_("line too long"));
1275 			exit(EXIT_FAILURE);
1276 		}
1277 		*cp = '\0';
1278 		fields = getfields(buf);
1279 		nfields = 0;
1280 		while (fields[nfields] != NULL)
1281 		{
1282 			static char nada;
1283 
1284 			if (strcmp(fields[nfields], "-") == 0)
1285 				fields[nfields] = &nada;
1286 			++nfields;
1287 		}
1288 		if (nfields == 0)
1289 		{
1290 			if (name == leapsec && *buf == '#')
1291 			{
1292 				/*
1293 				 * PG: INT64_FORMAT isn't portable for sscanf, so be content
1294 				 * with scanning a "long".  Once we are requiring C99 in all
1295 				 * live branches, it'd be sensible to adopt upstream's
1296 				 * practice of using the <inttypes.h> macros.  But for now, we
1297 				 * don't actually use this code, and it won't overflow before
1298 				 * 2038 anyway.
1299 				 */
1300 				long		cl_tmp;
1301 
1302 				sscanf(buf, "#expires %ld", &cl_tmp);
1303 				comment_leapexpires = cl_tmp;
1304 			}
1305 		}
1306 		else if (wantcont)
1307 		{
1308 			wantcont = inzcont(fields, nfields);
1309 		}
1310 		else
1311 		{
1312 			struct lookup const *line_codes
1313 			= name == leapsec ? leap_line_codes : zi_line_codes;
1314 
1315 			lp = byword(fields[0], line_codes);
1316 			if (lp == NULL)
1317 				error(_("input line of unknown type"));
1318 			else
1319 				switch (lp->l_value)
1320 				{
1321 					case LC_RULE:
1322 						inrule(fields, nfields);
1323 						wantcont = false;
1324 						break;
1325 					case LC_ZONE:
1326 						wantcont = inzone(fields, nfields);
1327 						break;
1328 					case LC_LINK:
1329 						inlink(fields, nfields);
1330 						wantcont = false;
1331 						break;
1332 					case LC_LEAP:
1333 						inleap(fields, nfields);
1334 						wantcont = false;
1335 						break;
1336 					case LC_EXPIRES:
1337 						inexpires(fields, nfields);
1338 						wantcont = false;
1339 						break;
1340 					default:	/* "cannot happen" */
1341 						fprintf(stderr,
1342 								_("%s: panic: Invalid l_value %d\n"),
1343 								progname, lp->l_value);
1344 						exit(EXIT_FAILURE);
1345 				}
1346 		}
1347 		free(fields);
1348 	}
1349 	close_file(fp, NULL, filename);
1350 	if (wantcont)
1351 		error(_("expected continuation line not found"));
1352 }
1353 
1354 /*
1355  * Convert a string of one of the forms
1356  *	h	-h	hh:mm	-hh:mm	hh:mm:ss	-hh:mm:ss
1357  * into a number of seconds.
1358  * A null string maps to zero.
1359  * Call error with errstring and return zero on errors.
1360  */
1361 
1362 static zic_t
gethms(char const * string,char const * errstring)1363 gethms(char const *string, char const *errstring)
1364 {
1365 	/* PG: make hh be int not zic_t to avoid sscanf portability issues */
1366 	int			hh;
1367 	int			sign,
1368 				mm = 0,
1369 				ss = 0;
1370 	char		hhx,
1371 				mmx,
1372 				ssx,
1373 				xr = '0',
1374 				xs;
1375 	int			tenths = 0;
1376 	bool		ok = true;
1377 
1378 	if (string == NULL || *string == '\0')
1379 		return 0;
1380 	if (*string == '-')
1381 	{
1382 		sign = -1;
1383 		++string;
1384 	}
1385 	else
1386 		sign = 1;
1387 	switch (sscanf(string,
1388 				   "%d%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
1389 				   &hh, &hhx, &mm, &mmx, &ss, &ssx, &tenths, &xr, &xs))
1390 	{
1391 		default:
1392 			ok = false;
1393 			break;
1394 		case 8:
1395 			ok = '0' <= xr && xr <= '9';
1396 			/* fallthrough */
1397 		case 7:
1398 			ok &= ssx == '.';
1399 			if (ok && noise)
1400 				warning(_("fractional seconds rejected by"
1401 						  " pre-2018 versions of zic"));
1402 			/* fallthrough */
1403 		case 5:
1404 			ok &= mmx == ':';
1405 			/* fallthrough */
1406 		case 3:
1407 			ok &= hhx == ':';
1408 			/* fallthrough */
1409 		case 1:
1410 			break;
1411 	}
1412 	if (!ok)
1413 	{
1414 		error("%s", errstring);
1415 		return 0;
1416 	}
1417 	if (hh < 0 ||
1418 		mm < 0 || mm >= MINSPERHOUR ||
1419 		ss < 0 || ss > SECSPERMIN)
1420 	{
1421 		error("%s", errstring);
1422 		return 0;
1423 	}
1424 	/* Some compilers warn that this test is unsatisfiable for 32-bit ints */
1425 #if INT_MAX > PG_INT32_MAX
1426 	if (ZIC_MAX / SECSPERHOUR < hh)
1427 	{
1428 		error(_("time overflow"));
1429 		return 0;
1430 	}
1431 #endif
1432 	ss += 5 + ((ss ^ 1) & (xr == '0')) <= tenths;	/* Round to even.  */
1433 	if (noise && (hh > HOURSPERDAY ||
1434 				  (hh == HOURSPERDAY && (mm != 0 || ss != 0))))
1435 		warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
1436 	return oadd(sign * (zic_t) hh * SECSPERHOUR,
1437 				sign * (mm * SECSPERMIN + ss));
1438 }
1439 
1440 static zic_t
getsave(char * field,bool * isdst)1441 getsave(char *field, bool *isdst)
1442 {
1443 	int			dst = -1;
1444 	zic_t		save;
1445 	size_t		fieldlen = strlen(field);
1446 
1447 	if (fieldlen != 0)
1448 	{
1449 		char	   *ep = field + fieldlen - 1;
1450 
1451 		switch (*ep)
1452 		{
1453 			case 'd':
1454 				dst = 1;
1455 				*ep = '\0';
1456 				break;
1457 			case 's':
1458 				dst = 0;
1459 				*ep = '\0';
1460 				break;
1461 		}
1462 	}
1463 	save = gethms(field, _("invalid saved time"));
1464 	*isdst = dst < 0 ? save != 0 : dst;
1465 	return save;
1466 }
1467 
1468 static void
inrule(char ** fields,int nfields)1469 inrule(char **fields, int nfields)
1470 {
1471 	static struct rule r;
1472 
1473 	if (nfields != RULE_FIELDS)
1474 	{
1475 		error(_("wrong number of fields on Rule line"));
1476 		return;
1477 	}
1478 	switch (*fields[RF_NAME])
1479 	{
1480 		case '\0':
1481 		case ' ':
1482 		case '\f':
1483 		case '\n':
1484 		case '\r':
1485 		case '\t':
1486 		case '\v':
1487 		case '+':
1488 		case '-':
1489 		case '0':
1490 		case '1':
1491 		case '2':
1492 		case '3':
1493 		case '4':
1494 		case '5':
1495 		case '6':
1496 		case '7':
1497 		case '8':
1498 		case '9':
1499 			error(_("Invalid rule name \"%s\""), fields[RF_NAME]);
1500 			return;
1501 	}
1502 	r.r_filename = filename;
1503 	r.r_linenum = linenum;
1504 	r.r_save = getsave(fields[RF_SAVE], &r.r_isdst);
1505 	rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
1506 			fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
1507 	r.r_name = ecpyalloc(fields[RF_NAME]);
1508 	r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
1509 	if (max_abbrvar_len < strlen(r.r_abbrvar))
1510 		max_abbrvar_len = strlen(r.r_abbrvar);
1511 	rules = growalloc(rules, sizeof *rules, nrules, &nrules_alloc);
1512 	rules[nrules++] = r;
1513 }
1514 
1515 static bool
inzone(char ** fields,int nfields)1516 inzone(char **fields, int nfields)
1517 {
1518 	ptrdiff_t	i;
1519 
1520 	if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS)
1521 	{
1522 		error(_("wrong number of fields on Zone line"));
1523 		return false;
1524 	}
1525 	if (lcltime != NULL && strcmp(fields[ZF_NAME], tzdefault) == 0)
1526 	{
1527 		error(
1528 			  _("\"Zone %s\" line and -l option are mutually exclusive"),
1529 			  tzdefault);
1530 		return false;
1531 	}
1532 	if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL)
1533 	{
1534 		error(
1535 			  _("\"Zone %s\" line and -p option are mutually exclusive"),
1536 			  TZDEFRULES);
1537 		return false;
1538 	}
1539 	for (i = 0; i < nzones; ++i)
1540 		if (zones[i].z_name != NULL &&
1541 			strcmp(zones[i].z_name, fields[ZF_NAME]) == 0)
1542 		{
1543 			error(_("duplicate zone name %s"
1544 					" (file \"%s\", line %d)"),
1545 				  fields[ZF_NAME],
1546 				  zones[i].z_filename,
1547 				  zones[i].z_linenum);
1548 			return false;
1549 		}
1550 	return inzsub(fields, nfields, false);
1551 }
1552 
1553 static bool
inzcont(char ** fields,int nfields)1554 inzcont(char **fields, int nfields)
1555 {
1556 	if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS)
1557 	{
1558 		error(_("wrong number of fields on Zone continuation line"));
1559 		return false;
1560 	}
1561 	return inzsub(fields, nfields, true);
1562 }
1563 
1564 static bool
inzsub(char ** fields,int nfields,bool iscont)1565 inzsub(char **fields, int nfields, bool iscont)
1566 {
1567 	char	   *cp;
1568 	char	   *cp1;
1569 	static struct zone z;
1570 	int			i_stdoff,
1571 				i_rule,
1572 				i_format;
1573 	int			i_untilyear,
1574 				i_untilmonth;
1575 	int			i_untilday,
1576 				i_untiltime;
1577 	bool		hasuntil;
1578 
1579 	if (iscont)
1580 	{
1581 		i_stdoff = ZFC_STDOFF;
1582 		i_rule = ZFC_RULE;
1583 		i_format = ZFC_FORMAT;
1584 		i_untilyear = ZFC_TILYEAR;
1585 		i_untilmonth = ZFC_TILMONTH;
1586 		i_untilday = ZFC_TILDAY;
1587 		i_untiltime = ZFC_TILTIME;
1588 		z.z_name = NULL;
1589 	}
1590 	else if (!namecheck(fields[ZF_NAME]))
1591 		return false;
1592 	else
1593 	{
1594 		i_stdoff = ZF_STDOFF;
1595 		i_rule = ZF_RULE;
1596 		i_format = ZF_FORMAT;
1597 		i_untilyear = ZF_TILYEAR;
1598 		i_untilmonth = ZF_TILMONTH;
1599 		i_untilday = ZF_TILDAY;
1600 		i_untiltime = ZF_TILTIME;
1601 		z.z_name = ecpyalloc(fields[ZF_NAME]);
1602 	}
1603 	z.z_filename = filename;
1604 	z.z_linenum = linenum;
1605 	z.z_stdoff = gethms(fields[i_stdoff], _("invalid UT offset"));
1606 	if ((cp = strchr(fields[i_format], '%')) != NULL)
1607 	{
1608 		if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
1609 			|| strchr(fields[i_format], '/'))
1610 		{
1611 			error(_("invalid abbreviation format"));
1612 			return false;
1613 		}
1614 	}
1615 	z.z_rule = ecpyalloc(fields[i_rule]);
1616 	z.z_format = cp1 = ecpyalloc(fields[i_format]);
1617 	z.z_format_specifier = cp ? *cp : '\0';
1618 	if (z.z_format_specifier == 'z')
1619 	{
1620 		if (noise)
1621 			warning(_("format '%s' not handled by pre-2015 versions of zic"),
1622 					z.z_format);
1623 		cp1[cp - fields[i_format]] = 's';
1624 	}
1625 	if (max_format_len < strlen(z.z_format))
1626 		max_format_len = strlen(z.z_format);
1627 	hasuntil = nfields > i_untilyear;
1628 	if (hasuntil)
1629 	{
1630 		z.z_untilrule.r_filename = filename;
1631 		z.z_untilrule.r_linenum = linenum;
1632 		rulesub(&z.z_untilrule,
1633 				fields[i_untilyear],
1634 				"only",
1635 				"",
1636 				(nfields > i_untilmonth) ?
1637 				fields[i_untilmonth] : "Jan",
1638 				(nfields > i_untilday) ? fields[i_untilday] : "1",
1639 				(nfields > i_untiltime) ? fields[i_untiltime] : "0");
1640 		z.z_untiltime = rpytime(&z.z_untilrule,
1641 								z.z_untilrule.r_loyear);
1642 		if (iscont && nzones > 0 &&
1643 			z.z_untiltime > min_time &&
1644 			z.z_untiltime < max_time &&
1645 			zones[nzones - 1].z_untiltime > min_time &&
1646 			zones[nzones - 1].z_untiltime < max_time &&
1647 			zones[nzones - 1].z_untiltime >= z.z_untiltime)
1648 		{
1649 			error(_("Zone continuation line end time is not after end time of previous line"));
1650 			return false;
1651 		}
1652 	}
1653 	zones = growalloc(zones, sizeof *zones, nzones, &nzones_alloc);
1654 	zones[nzones++] = z;
1655 
1656 	/*
1657 	 * If there was an UNTIL field on this line, there's more information
1658 	 * about the zone on the next line.
1659 	 */
1660 	return hasuntil;
1661 }
1662 
1663 static zic_t
getleapdatetime(char ** fields,int nfields,bool expire_line)1664 getleapdatetime(char **fields, int nfields, bool expire_line)
1665 {
1666 	const char *cp;
1667 	const struct lookup *lp;
1668 	zic_t		i,
1669 				j;
1670 
1671 	/* PG: make year be int not zic_t to avoid sscanf portability issues */
1672 	int			year;
1673 	int			month,
1674 				day;
1675 	zic_t		dayoff,
1676 				tod;
1677 	zic_t		t;
1678 	char		xs;
1679 
1680 	dayoff = 0;
1681 	cp = fields[LP_YEAR];
1682 	if (sscanf(cp, "%d%c", &year, &xs) != 1)
1683 	{
1684 		/*
1685 		 * Leapin' Lizards!
1686 		 */
1687 		error(_("invalid leaping year"));
1688 		return -1;
1689 	}
1690 	if (!expire_line)
1691 	{
1692 		if (!leapseen || leapmaxyear < year)
1693 			leapmaxyear = year;
1694 		if (!leapseen || leapminyear > year)
1695 			leapminyear = year;
1696 		leapseen = true;
1697 	}
1698 	j = EPOCH_YEAR;
1699 	while (j != year)
1700 	{
1701 		if (year > j)
1702 		{
1703 			i = len_years[isleap(j)];
1704 			++j;
1705 		}
1706 		else
1707 		{
1708 			--j;
1709 			i = -len_years[isleap(j)];
1710 		}
1711 		dayoff = oadd(dayoff, i);
1712 	}
1713 	if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL)
1714 	{
1715 		error(_("invalid month name"));
1716 		return -1;
1717 	}
1718 	month = lp->l_value;
1719 	j = TM_JANUARY;
1720 	while (j != month)
1721 	{
1722 		i = len_months[isleap(year)][j];
1723 		dayoff = oadd(dayoff, i);
1724 		++j;
1725 	}
1726 	cp = fields[LP_DAY];
1727 	if (sscanf(cp, "%d%c", &day, &xs) != 1 ||
1728 		day <= 0 || day > len_months[isleap(year)][month])
1729 	{
1730 		error(_("invalid day of month"));
1731 		return -1;
1732 	}
1733 	dayoff = oadd(dayoff, day - 1);
1734 	if (dayoff < min_time / SECSPERDAY)
1735 	{
1736 		error(_("time too small"));
1737 		return -1;
1738 	}
1739 	if (dayoff > max_time / SECSPERDAY)
1740 	{
1741 		error(_("time too large"));
1742 		return -1;
1743 	}
1744 	t = dayoff * SECSPERDAY;
1745 	tod = gethms(fields[LP_TIME], _("invalid time of day"));
1746 	t = tadd(t, tod);
1747 	if (t < 0)
1748 		error(_("leap second precedes Epoch"));
1749 	return t;
1750 }
1751 
1752 static void
inleap(char ** fields,int nfields)1753 inleap(char **fields, int nfields)
1754 {
1755 	if (nfields != LEAP_FIELDS)
1756 		error(_("wrong number of fields on Leap line"));
1757 	else
1758 	{
1759 		zic_t		t = getleapdatetime(fields, nfields, false);
1760 
1761 		if (0 <= t)
1762 		{
1763 			struct lookup const *lp = byword(fields[LP_ROLL], leap_types);
1764 
1765 			if (!lp)
1766 				error(_("invalid Rolling/Stationary field on Leap line"));
1767 			else
1768 			{
1769 				int			correction = 0;
1770 
1771 				if (!fields[LP_CORR][0])	/* infile() turns "-" into "".  */
1772 					correction = -1;
1773 				else if (strcmp(fields[LP_CORR], "+") == 0)
1774 					correction = 1;
1775 				else
1776 					error(_("invalid CORRECTION field on Leap line"));
1777 				if (correction)
1778 					leapadd(t, correction, lp->l_value);
1779 			}
1780 		}
1781 	}
1782 }
1783 
1784 static void
inexpires(char ** fields,int nfields)1785 inexpires(char **fields, int nfields)
1786 {
1787 	if (nfields != EXPIRES_FIELDS)
1788 		error(_("wrong number of fields on Expires line"));
1789 	else if (0 <= leapexpires)
1790 		error(_("multiple Expires lines"));
1791 	else
1792 		leapexpires = getleapdatetime(fields, nfields, true);
1793 }
1794 
1795 static void
inlink(char ** fields,int nfields)1796 inlink(char **fields, int nfields)
1797 {
1798 	struct link l;
1799 
1800 	if (nfields != LINK_FIELDS)
1801 	{
1802 		error(_("wrong number of fields on Link line"));
1803 		return;
1804 	}
1805 	if (*fields[LF_TARGET] == '\0')
1806 	{
1807 		error(_("blank TARGET field on Link line"));
1808 		return;
1809 	}
1810 	if (!namecheck(fields[LF_LINKNAME]))
1811 		return;
1812 	l.l_filename = filename;
1813 	l.l_linenum = linenum;
1814 	l.l_target = ecpyalloc(fields[LF_TARGET]);
1815 	l.l_linkname = ecpyalloc(fields[LF_LINKNAME]);
1816 	links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc);
1817 	links[nlinks++] = l;
1818 }
1819 
1820 static void
rulesub(struct rule * rp,const char * loyearp,const char * hiyearp,const char * typep,const char * monthp,const char * dayp,const char * timep)1821 rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
1822 		const char *typep, const char *monthp, const char *dayp,
1823 		const char *timep)
1824 {
1825 	const struct lookup *lp;
1826 	const char *cp;
1827 	char	   *dp;
1828 	char	   *ep;
1829 	char		xs;
1830 
1831 	/* PG: year_tmp is to avoid sscanf portability issues */
1832 	int			year_tmp;
1833 
1834 	if ((lp = byword(monthp, mon_names)) == NULL)
1835 	{
1836 		error(_("invalid month name"));
1837 		return;
1838 	}
1839 	rp->r_month = lp->l_value;
1840 	rp->r_todisstd = false;
1841 	rp->r_todisut = false;
1842 	dp = ecpyalloc(timep);
1843 	if (*dp != '\0')
1844 	{
1845 		ep = dp + strlen(dp) - 1;
1846 		switch (lowerit(*ep))
1847 		{
1848 			case 's':			/* Standard */
1849 				rp->r_todisstd = true;
1850 				rp->r_todisut = false;
1851 				*ep = '\0';
1852 				break;
1853 			case 'w':			/* Wall */
1854 				rp->r_todisstd = false;
1855 				rp->r_todisut = false;
1856 				*ep = '\0';
1857 				break;
1858 			case 'g':			/* Greenwich */
1859 			case 'u':			/* Universal */
1860 			case 'z':			/* Zulu */
1861 				rp->r_todisstd = true;
1862 				rp->r_todisut = true;
1863 				*ep = '\0';
1864 				break;
1865 		}
1866 	}
1867 	rp->r_tod = gethms(dp, _("invalid time of day"));
1868 	free(dp);
1869 
1870 	/*
1871 	 * Year work.
1872 	 */
1873 	cp = loyearp;
1874 	lp = byword(cp, begin_years);
1875 	rp->r_lowasnum = lp == NULL;
1876 	if (!rp->r_lowasnum)
1877 		switch (lp->l_value)
1878 		{
1879 			case YR_MINIMUM:
1880 				rp->r_loyear = ZIC_MIN;
1881 				break;
1882 			case YR_MAXIMUM:
1883 				rp->r_loyear = ZIC_MAX;
1884 				break;
1885 			default:			/* "cannot happen" */
1886 				fprintf(stderr,
1887 						_("%s: panic: Invalid l_value %d\n"),
1888 						progname, lp->l_value);
1889 				exit(EXIT_FAILURE);
1890 		}
1891 	else if (sscanf(cp, "%d%c", &year_tmp, &xs) == 1)
1892 		rp->r_loyear = year_tmp;
1893 	else
1894 	{
1895 		error(_("invalid starting year"));
1896 		return;
1897 	}
1898 	cp = hiyearp;
1899 	lp = byword(cp, end_years);
1900 	rp->r_hiwasnum = lp == NULL;
1901 	if (!rp->r_hiwasnum)
1902 		switch (lp->l_value)
1903 		{
1904 			case YR_MINIMUM:
1905 				rp->r_hiyear = ZIC_MIN;
1906 				break;
1907 			case YR_MAXIMUM:
1908 				rp->r_hiyear = ZIC_MAX;
1909 				break;
1910 			case YR_ONLY:
1911 				rp->r_hiyear = rp->r_loyear;
1912 				break;
1913 			default:			/* "cannot happen" */
1914 				fprintf(stderr,
1915 						_("%s: panic: Invalid l_value %d\n"),
1916 						progname, lp->l_value);
1917 				exit(EXIT_FAILURE);
1918 		}
1919 	else if (sscanf(cp, "%d%c", &year_tmp, &xs) == 1)
1920 		rp->r_hiyear = year_tmp;
1921 	else
1922 	{
1923 		error(_("invalid ending year"));
1924 		return;
1925 	}
1926 	if (rp->r_loyear > rp->r_hiyear)
1927 	{
1928 		error(_("starting year greater than ending year"));
1929 		return;
1930 	}
1931 	if (*typep != '\0')
1932 	{
1933 		error(_("year type \"%s\" is unsupported; use \"-\" instead"),
1934 			  typep);
1935 		return;
1936 	}
1937 
1938 	/*
1939 	 * Day work. Accept things such as: 1 lastSunday last-Sunday
1940 	 * (undocumented; warn about this) Sun<=20 Sun>=7
1941 	 */
1942 	dp = ecpyalloc(dayp);
1943 	if ((lp = byword(dp, lasts)) != NULL)
1944 	{
1945 		rp->r_dycode = DC_DOWLEQ;
1946 		rp->r_wday = lp->l_value;
1947 		rp->r_dayofmonth = len_months[1][rp->r_month];
1948 	}
1949 	else
1950 	{
1951 		if ((ep = strchr(dp, '<')) != NULL)
1952 			rp->r_dycode = DC_DOWLEQ;
1953 		else if ((ep = strchr(dp, '>')) != NULL)
1954 			rp->r_dycode = DC_DOWGEQ;
1955 		else
1956 		{
1957 			ep = dp;
1958 			rp->r_dycode = DC_DOM;
1959 		}
1960 		if (rp->r_dycode != DC_DOM)
1961 		{
1962 			*ep++ = 0;
1963 			if (*ep++ != '=')
1964 			{
1965 				error(_("invalid day of month"));
1966 				free(dp);
1967 				return;
1968 			}
1969 			if ((lp = byword(dp, wday_names)) == NULL)
1970 			{
1971 				error(_("invalid weekday name"));
1972 				free(dp);
1973 				return;
1974 			}
1975 			rp->r_wday = lp->l_value;
1976 		}
1977 		if (sscanf(ep, "%d%c", &rp->r_dayofmonth, &xs) != 1 ||
1978 			rp->r_dayofmonth <= 0 ||
1979 			(rp->r_dayofmonth > len_months[1][rp->r_month]))
1980 		{
1981 			error(_("invalid day of month"));
1982 			free(dp);
1983 			return;
1984 		}
1985 	}
1986 	free(dp);
1987 }
1988 
1989 static void
convert(const int32 val,char * const buf)1990 convert(const int32 val, char *const buf)
1991 {
1992 	int			i;
1993 	int			shift;
1994 	unsigned char *const b = (unsigned char *) buf;
1995 
1996 	for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
1997 		b[i] = val >> shift;
1998 }
1999 
2000 static void
convert64(const zic_t val,char * const buf)2001 convert64(const zic_t val, char *const buf)
2002 {
2003 	int			i;
2004 	int			shift;
2005 	unsigned char *const b = (unsigned char *) buf;
2006 
2007 	for (i = 0, shift = 56; i < 8; ++i, shift -= 8)
2008 		b[i] = val >> shift;
2009 }
2010 
2011 static void
puttzcode(const int32 val,FILE * const fp)2012 puttzcode(const int32 val, FILE *const fp)
2013 {
2014 	char		buf[4];
2015 
2016 	convert(val, buf);
2017 	fwrite(buf, sizeof buf, 1, fp);
2018 }
2019 
2020 static void
puttzcodepass(zic_t val,FILE * fp,int pass)2021 puttzcodepass(zic_t val, FILE *fp, int pass)
2022 {
2023 	if (pass == 1)
2024 		puttzcode(val, fp);
2025 	else
2026 	{
2027 		char		buf[8];
2028 
2029 		convert64(val, buf);
2030 		fwrite(buf, sizeof buf, 1, fp);
2031 	}
2032 }
2033 
2034 static int
atcomp(const void * avp,const void * bvp)2035 atcomp(const void *avp, const void *bvp)
2036 {
2037 	const zic_t a = ((const struct attype *) avp)->at;
2038 	const zic_t b = ((const struct attype *) bvp)->at;
2039 
2040 	return (a < b) ? -1 : (a > b);
2041 }
2042 
2043 struct timerange
2044 {
2045 	int			defaulttype;
2046 	ptrdiff_t	base,
2047 				count;
2048 	int			leapbase,
2049 				leapcount;
2050 };
2051 
2052 static struct timerange
limitrange(struct timerange r,zic_t lo,zic_t hi,zic_t const * ats,unsigned char const * types)2053 limitrange(struct timerange r, zic_t lo, zic_t hi,
2054 		   zic_t const *ats, unsigned char const *types)
2055 {
2056 	while (0 < r.count && ats[r.base] < lo)
2057 	{
2058 		r.defaulttype = types[r.base];
2059 		r.count--;
2060 		r.base++;
2061 	}
2062 	while (0 < r.leapcount && trans[r.leapbase] < lo)
2063 	{
2064 		r.leapcount--;
2065 		r.leapbase++;
2066 	}
2067 
2068 	if (hi < ZIC_MAX)
2069 	{
2070 		while (0 < r.count && hi + 1 < ats[r.base + r.count - 1])
2071 			r.count--;
2072 		while (0 < r.leapcount && hi + 1 < trans[r.leapbase + r.leapcount - 1])
2073 			r.leapcount--;
2074 	}
2075 
2076 	return r;
2077 }
2078 
2079 static void
writezone(const char * const name,const char * const string,char version,int defaulttype)2080 writezone(const char *const name, const char *const string, char version,
2081 		  int defaulttype)
2082 {
2083 	FILE	   *fp;
2084 	ptrdiff_t	i,
2085 				j;
2086 	int			pass;
2087 	static const struct tzhead tzh0;
2088 	static struct tzhead tzh;
2089 	bool		dir_checked = false;
2090 	zic_t		one = 1;
2091 	zic_t		y2038_boundary = one << 31;
2092 	ptrdiff_t	nats = timecnt + WORK_AROUND_QTBUG_53071;
2093 
2094 	/*
2095 	 * Allocate the ATS and TYPES arrays via a single malloc, as this is a bit
2096 	 * faster.
2097 	 */
2098 	zic_t	   *ats = emalloc(MAXALIGN(size_product(nats, sizeof *ats + 1)));
2099 	void	   *typesptr = ats + nats;
2100 	unsigned char *types = typesptr;
2101 	struct timerange rangeall,
2102 				range32,
2103 				range64;
2104 
2105 	/*
2106 	 * Sort.
2107 	 */
2108 	if (timecnt > 1)
2109 		qsort(attypes, timecnt, sizeof *attypes, atcomp);
2110 
2111 	/*
2112 	 * Optimize.
2113 	 */
2114 	{
2115 		ptrdiff_t	fromi,
2116 					toi;
2117 
2118 		toi = 0;
2119 		fromi = 0;
2120 		for (; fromi < timecnt; ++fromi)
2121 		{
2122 			if (toi != 0
2123 				&& ((attypes[fromi].at
2124 					 + utoffs[attypes[toi - 1].type])
2125 					<= (attypes[toi - 1].at
2126 						+ utoffs[toi == 1 ? 0
2127 								 : attypes[toi - 2].type])))
2128 			{
2129 				attypes[toi - 1].type =
2130 					attypes[fromi].type;
2131 				continue;
2132 			}
2133 			if (toi == 0
2134 				|| attypes[fromi].dontmerge
2135 				|| (utoffs[attypes[toi - 1].type]
2136 					!= utoffs[attypes[fromi].type])
2137 				|| (isdsts[attypes[toi - 1].type]
2138 					!= isdsts[attypes[fromi].type])
2139 				|| (desigidx[attypes[toi - 1].type]
2140 					!= desigidx[attypes[fromi].type]))
2141 				attypes[toi++] = attypes[fromi];
2142 		}
2143 		timecnt = toi;
2144 	}
2145 
2146 	if (noise && timecnt > 1200)
2147 	{
2148 		if (timecnt > TZ_MAX_TIMES)
2149 			warning(_("reference clients mishandle"
2150 					  " more than %d transition times"),
2151 					TZ_MAX_TIMES);
2152 		else
2153 			warning(_("pre-2014 clients may mishandle"
2154 					  " more than 1200 transition times"));
2155 	}
2156 
2157 	/*
2158 	 * Transfer.
2159 	 */
2160 	for (i = 0; i < timecnt; ++i)
2161 	{
2162 		ats[i] = attypes[i].at;
2163 		types[i] = attypes[i].type;
2164 	}
2165 
2166 	/*
2167 	 * Correct for leap seconds.
2168 	 */
2169 	for (i = 0; i < timecnt; ++i)
2170 	{
2171 		j = leapcnt;
2172 		while (--j >= 0)
2173 			if (ats[i] > trans[j] - corr[j])
2174 			{
2175 				ats[i] = tadd(ats[i], corr[j]);
2176 				break;
2177 			}
2178 	}
2179 
2180 	/*
2181 	 * Work around QTBUG-53071 for timestamps less than y2038_boundary - 1, by
2182 	 * inserting a no-op transition at time y2038_boundary - 1. This works
2183 	 * only for timestamps before the boundary, which should be good enough in
2184 	 * practice as QTBUG-53071 should be long-dead by 2038.  Do this after
2185 	 * correcting for leap seconds, as the idea is to insert a transition just
2186 	 * before 32-bit pg_time_t rolls around, and this occurs at a slightly
2187 	 * different moment if transitions are leap-second corrected.
2188 	 */
2189 	if (WORK_AROUND_QTBUG_53071 && timecnt != 0 && want_bloat()
2190 		&& ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<'))
2191 	{
2192 		ats[timecnt] = y2038_boundary - 1;
2193 		types[timecnt] = types[timecnt - 1];
2194 		timecnt++;
2195 	}
2196 
2197 	rangeall.defaulttype = defaulttype;
2198 	rangeall.base = rangeall.leapbase = 0;
2199 	rangeall.count = timecnt;
2200 	rangeall.leapcount = leapcnt;
2201 	range64 = limitrange(rangeall, lo_time, hi_time, ats, types);
2202 	range32 = limitrange(range64, PG_INT32_MIN, PG_INT32_MAX, ats, types);
2203 
2204 	/*
2205 	 * Remove old file, if any, to snap links.
2206 	 */
2207 	if (remove(name) == 0)
2208 		dir_checked = true;
2209 	else if (errno != ENOENT)
2210 	{
2211 		const char *e = strerror(errno);
2212 
2213 		fprintf(stderr, _("%s: Cannot remove %s/%s: %s\n"),
2214 				progname, directory, name, e);
2215 		exit(EXIT_FAILURE);
2216 	}
2217 	fp = fopen(name, "wb");
2218 	if (!fp)
2219 	{
2220 		int			fopen_errno = errno;
2221 
2222 		if (fopen_errno == ENOENT && !dir_checked)
2223 		{
2224 			mkdirs(name, true);
2225 			fp = fopen(name, "wb");
2226 			fopen_errno = errno;
2227 		}
2228 		if (!fp)
2229 		{
2230 			fprintf(stderr, _("%s: Cannot create %s/%s: %s\n"),
2231 					progname, directory, name, strerror(fopen_errno));
2232 			exit(EXIT_FAILURE);
2233 		}
2234 	}
2235 	for (pass = 1; pass <= 2; ++pass)
2236 	{
2237 		ptrdiff_t	thistimei,
2238 					thistimecnt,
2239 					thistimelim;
2240 		int			thisleapi,
2241 					thisleapcnt,
2242 					thisleaplim;
2243 		int			currenttype,
2244 					thisdefaulttype;
2245 		bool		locut,
2246 					hicut;
2247 		zic_t		lo;
2248 		int			old0;
2249 		char		omittype[TZ_MAX_TYPES];
2250 		int			typemap[TZ_MAX_TYPES];
2251 		int			thistypecnt,
2252 					stdcnt,
2253 					utcnt;
2254 		char		thischars[TZ_MAX_CHARS];
2255 		int			thischarcnt;
2256 		bool		toomanytimes;
2257 		int			indmap[TZ_MAX_CHARS];
2258 
2259 		if (pass == 1)
2260 		{
2261 			/*
2262 			 * Arguably the default time type in the 32-bit data should be
2263 			 * range32.defaulttype, which is suited for timestamps just before
2264 			 * PG_INT32_MIN.  However, zic traditionally used the time type of
2265 			 * the indefinite past instead.  Internet RFC 8532 says readers
2266 			 * should ignore 32-bit data, so this discrepancy matters only to
2267 			 * obsolete readers where the traditional type might be more
2268 			 * appropriate even if it's "wrong".  So, use the historical zic
2269 			 * value, unless -r specifies a low cutoff that excludes some
2270 			 * 32-bit timestamps.
2271 			 */
2272 			thisdefaulttype = (lo_time <= PG_INT32_MIN
2273 							   ? range64.defaulttype
2274 							   : range32.defaulttype);
2275 
2276 			thistimei = range32.base;
2277 			thistimecnt = range32.count;
2278 			toomanytimes = thistimecnt >> 31 >> 1 != 0;
2279 			thisleapi = range32.leapbase;
2280 			thisleapcnt = range32.leapcount;
2281 			locut = PG_INT32_MIN < lo_time;
2282 			hicut = hi_time < PG_INT32_MAX;
2283 		}
2284 		else
2285 		{
2286 			thisdefaulttype = range64.defaulttype;
2287 			thistimei = range64.base;
2288 			thistimecnt = range64.count;
2289 			toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
2290 			thisleapi = range64.leapbase;
2291 			thisleapcnt = range64.leapcount;
2292 			locut = min_time < lo_time;
2293 			hicut = hi_time < max_time;
2294 		}
2295 		if (toomanytimes)
2296 			error(_("too many transition times"));
2297 
2298 		/*
2299 		 * Keep the last too-low transition if no transition is exactly at LO.
2300 		 * The kept transition will be output as a LO "transition"; see
2301 		 * "Output a LO_TIME transition" below.  This is needed when the
2302 		 * output is truncated at the start, and is also useful when catering
2303 		 * to buggy 32-bit clients that do not use time type 0 for timestamps
2304 		 * before the first transition.
2305 		 */
2306 		if (0 < thistimei && ats[thistimei] != lo_time)
2307 		{
2308 			thistimei--;
2309 			thistimecnt++;
2310 			locut = false;
2311 		}
2312 
2313 		thistimelim = thistimei + thistimecnt;
2314 		thisleaplim = thisleapi + thisleapcnt;
2315 		if (thistimecnt != 0)
2316 		{
2317 			if (ats[thistimei] == lo_time)
2318 				locut = false;
2319 			if (hi_time < ZIC_MAX && ats[thistimelim - 1] == hi_time + 1)
2320 				hicut = false;
2321 		}
2322 		memset(omittype, true, typecnt);
2323 		omittype[thisdefaulttype] = false;
2324 		for (i = thistimei; i < thistimelim; i++)
2325 			omittype[types[i]] = false;
2326 
2327 		/*
2328 		 * Reorder types to make THISDEFAULTTYPE type 0. Use TYPEMAP to swap
2329 		 * OLD0 and THISDEFAULTTYPE so that THISDEFAULTTYPE appears as type 0
2330 		 * in the output instead of OLD0.  TYPEMAP also omits unused types.
2331 		 */
2332 		old0 = strlen(omittype);
2333 
2334 #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
2335 
2336 		/*
2337 		 * For some pre-2011 systems: if the last-to-be-written standard (or
2338 		 * daylight) type has an offset different from the most recently used
2339 		 * offset, append an (unused) copy of the most recently used type (to
2340 		 * help get global "altzone" and "timezone" variables set correctly).
2341 		 */
2342 		if (want_bloat())
2343 		{
2344 			int			mrudst,
2345 						mrustd,
2346 						hidst,
2347 						histd,
2348 						type;
2349 
2350 			hidst = histd = mrudst = mrustd = -1;
2351 			for (i = thistimei; i < thistimelim; ++i)
2352 				if (isdsts[types[i]])
2353 					mrudst = types[i];
2354 				else
2355 					mrustd = types[i];
2356 			for (i = old0; i < typecnt; i++)
2357 			{
2358 				int			h = (i == old0 ? thisdefaulttype
2359 								 : i == thisdefaulttype ? old0 : i);
2360 
2361 				if (!omittype[h])
2362 				{
2363 					if (isdsts[h])
2364 						hidst = i;
2365 					else
2366 						histd = i;
2367 				}
2368 			}
2369 			if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
2370 				utoffs[hidst] != utoffs[mrudst])
2371 			{
2372 				isdsts[mrudst] = -1;
2373 				type = addtype(utoffs[mrudst],
2374 							   &chars[desigidx[mrudst]],
2375 							   true,
2376 							   ttisstds[mrudst],
2377 							   ttisuts[mrudst]);
2378 				isdsts[mrudst] = 1;
2379 				omittype[type] = false;
2380 			}
2381 			if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
2382 				utoffs[histd] != utoffs[mrustd])
2383 			{
2384 				isdsts[mrustd] = -1;
2385 				type = addtype(utoffs[mrustd],
2386 							   &chars[desigidx[mrustd]],
2387 							   false,
2388 							   ttisstds[mrustd],
2389 							   ttisuts[mrustd]);
2390 				isdsts[mrustd] = 0;
2391 				omittype[type] = false;
2392 			}
2393 		}
2394 #endif							/* !defined
2395 								 * LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
2396 		thistypecnt = 0;
2397 		for (i = old0; i < typecnt; i++)
2398 			if (!omittype[i])
2399 				typemap[i == old0 ? thisdefaulttype
2400 						: i == thisdefaulttype ? old0 : i]
2401 					= thistypecnt++;
2402 
2403 		for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
2404 			indmap[i] = -1;
2405 		thischarcnt = stdcnt = utcnt = 0;
2406 		for (i = old0; i < typecnt; i++)
2407 		{
2408 			char	   *thisabbr;
2409 
2410 			if (omittype[i])
2411 				continue;
2412 			if (ttisstds[i])
2413 				stdcnt = thistypecnt;
2414 			if (ttisuts[i])
2415 				utcnt = thistypecnt;
2416 			if (indmap[desigidx[i]] >= 0)
2417 				continue;
2418 			thisabbr = &chars[desigidx[i]];
2419 			for (j = 0; j < thischarcnt; ++j)
2420 				if (strcmp(&thischars[j], thisabbr) == 0)
2421 					break;
2422 			if (j == thischarcnt)
2423 			{
2424 				strcpy(&thischars[thischarcnt], thisabbr);
2425 				thischarcnt += strlen(thisabbr) + 1;
2426 			}
2427 			indmap[desigidx[i]] = j;
2428 		}
2429 		if (pass == 1 && !want_bloat())
2430 		{
2431 			utcnt = stdcnt = thisleapcnt = 0;
2432 			thistimecnt = -(locut + hicut);
2433 			thistypecnt = thischarcnt = 1;
2434 			thistimelim = thistimei;
2435 		}
2436 #define DO(field)	fwrite(tzh.field, sizeof tzh.field, 1, fp)
2437 		tzh = tzh0;
2438 		memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
2439 		tzh.tzh_version[0] = version;
2440 		convert(utcnt, tzh.tzh_ttisutcnt);
2441 		convert(stdcnt, tzh.tzh_ttisstdcnt);
2442 		convert(thisleapcnt, tzh.tzh_leapcnt);
2443 		convert(locut + thistimecnt + hicut, tzh.tzh_timecnt);
2444 		convert(thistypecnt, tzh.tzh_typecnt);
2445 		convert(thischarcnt, tzh.tzh_charcnt);
2446 		DO(tzh_magic);
2447 		DO(tzh_version);
2448 		DO(tzh_reserved);
2449 		DO(tzh_ttisutcnt);
2450 		DO(tzh_ttisstdcnt);
2451 		DO(tzh_leapcnt);
2452 		DO(tzh_timecnt);
2453 		DO(tzh_typecnt);
2454 		DO(tzh_charcnt);
2455 #undef DO
2456 		if (pass == 1 && !want_bloat())
2457 		{
2458 			/* Output a minimal data block with just one time type.  */
2459 			puttzcode(0, fp);	/* utoff */
2460 			putc(0, fp);		/* dst */
2461 			putc(0, fp);		/* index of abbreviation */
2462 			putc(0, fp);		/* empty-string abbreviation */
2463 			continue;
2464 		}
2465 
2466 		/* PG: print current timezone abbreviations if requested */
2467 		if (print_abbrevs && pass == 2)
2468 		{
2469 			/* Print "type" data for periods ending after print_cutoff */
2470 			for (i = thistimei; i < thistimelim; ++i)
2471 			{
2472 				if (i == thistimelim - 1 || ats[i + 1] > print_cutoff)
2473 				{
2474 					unsigned char tm = types[i];
2475 					char	   *thisabbrev = &thischars[indmap[desigidx[tm]]];
2476 
2477 					fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
2478 							thisabbrev,
2479 							utoffs[tm],
2480 							isdsts[tm] ? "\tD" : "");
2481 				}
2482 			}
2483 			/* Print the default type if we have no transitions at all */
2484 			if (thistimei >= thistimelim)
2485 			{
2486 				unsigned char tm = defaulttype;
2487 				char	   *thisabbrev = &thischars[indmap[desigidx[tm]]];
2488 
2489 				fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
2490 						thisabbrev,
2491 						utoffs[tm],
2492 						isdsts[tm] ? "\tD" : "");
2493 			}
2494 		}
2495 
2496 		/*
2497 		 * Output a LO_TIME transition if needed; see limitrange. But do not
2498 		 * go below the minimum representable value for this pass.
2499 		 */
2500 		lo = pass == 1 && lo_time < PG_INT32_MIN ? PG_INT32_MIN : lo_time;
2501 
2502 		if (locut)
2503 			puttzcodepass(lo, fp, pass);
2504 		for (i = thistimei; i < thistimelim; ++i)
2505 		{
2506 			zic_t		at = ats[i] < lo ? lo : ats[i];
2507 
2508 			puttzcodepass(at, fp, pass);
2509 		}
2510 		if (hicut)
2511 			puttzcodepass(hi_time + 1, fp, pass);
2512 		currenttype = 0;
2513 		if (locut)
2514 			putc(currenttype, fp);
2515 		for (i = thistimei; i < thistimelim; ++i)
2516 		{
2517 			currenttype = typemap[types[i]];
2518 			putc(currenttype, fp);
2519 		}
2520 		if (hicut)
2521 			putc(currenttype, fp);
2522 
2523 		for (i = old0; i < typecnt; i++)
2524 		{
2525 			int			h = (i == old0 ? thisdefaulttype
2526 							 : i == thisdefaulttype ? old0 : i);
2527 
2528 			if (!omittype[h])
2529 			{
2530 				puttzcode(utoffs[h], fp);
2531 				putc(isdsts[h], fp);
2532 				putc(indmap[desigidx[h]], fp);
2533 			}
2534 		}
2535 		if (thischarcnt != 0)
2536 			fwrite(thischars, sizeof thischars[0],
2537 				   thischarcnt, fp);
2538 		for (i = thisleapi; i < thisleaplim; ++i)
2539 		{
2540 			zic_t		todo;
2541 
2542 			if (roll[i])
2543 			{
2544 				if (timecnt == 0 || trans[i] < ats[0])
2545 				{
2546 					j = 0;
2547 					while (isdsts[j])
2548 						if (++j >= typecnt)
2549 						{
2550 							j = 0;
2551 							break;
2552 						}
2553 				}
2554 				else
2555 				{
2556 					j = 1;
2557 					while (j < timecnt &&
2558 						   trans[i] >= ats[j])
2559 						++j;
2560 					j = types[j - 1];
2561 				}
2562 				todo = tadd(trans[i], -utoffs[j]);
2563 			}
2564 			else
2565 				todo = trans[i];
2566 			puttzcodepass(todo, fp, pass);
2567 			puttzcode(corr[i], fp);
2568 		}
2569 		if (stdcnt != 0)
2570 			for (i = old0; i < typecnt; i++)
2571 				if (!omittype[i])
2572 					putc(ttisstds[i], fp);
2573 		if (utcnt != 0)
2574 			for (i = old0; i < typecnt; i++)
2575 				if (!omittype[i])
2576 					putc(ttisuts[i], fp);
2577 	}
2578 	fprintf(fp, "\n%s\n", string);
2579 	close_file(fp, directory, name);
2580 	free(ats);
2581 }
2582 
2583 static char const *
abbroffset(char * buf,zic_t offset)2584 abbroffset(char *buf, zic_t offset)
2585 {
2586 	char		sign = '+';
2587 	int			seconds,
2588 				minutes;
2589 
2590 	if (offset < 0)
2591 	{
2592 		offset = -offset;
2593 		sign = '-';
2594 	}
2595 
2596 	seconds = offset % SECSPERMIN;
2597 	offset /= SECSPERMIN;
2598 	minutes = offset % MINSPERHOUR;
2599 	offset /= MINSPERHOUR;
2600 	if (100 <= offset)
2601 	{
2602 		error(_("%%z UT offset magnitude exceeds 99:59:59"));
2603 		return "%z";
2604 	}
2605 	else
2606 	{
2607 		char	   *p = buf;
2608 
2609 		*p++ = sign;
2610 		*p++ = '0' + offset / 10;
2611 		*p++ = '0' + offset % 10;
2612 		if (minutes | seconds)
2613 		{
2614 			*p++ = '0' + minutes / 10;
2615 			*p++ = '0' + minutes % 10;
2616 			if (seconds)
2617 			{
2618 				*p++ = '0' + seconds / 10;
2619 				*p++ = '0' + seconds % 10;
2620 			}
2621 		}
2622 		*p = '\0';
2623 		return buf;
2624 	}
2625 }
2626 
2627 static size_t
doabbr(char * abbr,struct zone const * zp,char const * letters,bool isdst,zic_t save,bool doquotes)2628 doabbr(char *abbr, struct zone const *zp, char const *letters,
2629 	   bool isdst, zic_t save, bool doquotes)
2630 {
2631 	char	   *cp;
2632 	char	   *slashp;
2633 	size_t		len;
2634 	char const *format = zp->z_format;
2635 
2636 	slashp = strchr(format, '/');
2637 	if (slashp == NULL)
2638 	{
2639 		char		letterbuf[PERCENT_Z_LEN_BOUND + 1];
2640 
2641 		if (zp->z_format_specifier == 'z')
2642 			letters = abbroffset(letterbuf, zp->z_stdoff + save);
2643 		else if (!letters)
2644 			letters = "%s";
2645 		sprintf(abbr, format, letters);
2646 	}
2647 	else if (isdst)
2648 	{
2649 		strcpy(abbr, slashp + 1);
2650 	}
2651 	else
2652 	{
2653 		memcpy(abbr, format, slashp - format);
2654 		abbr[slashp - format] = '\0';
2655 	}
2656 	len = strlen(abbr);
2657 	if (!doquotes)
2658 		return len;
2659 	for (cp = abbr; is_alpha(*cp); cp++)
2660 		continue;
2661 	if (len > 0 && *cp == '\0')
2662 		return len;
2663 	abbr[len + 2] = '\0';
2664 	abbr[len + 1] = '>';
2665 	memmove(abbr + 1, abbr, len);
2666 	abbr[0] = '<';
2667 	return len + 2;
2668 }
2669 
2670 static void
updateminmax(const zic_t x)2671 updateminmax(const zic_t x)
2672 {
2673 	if (min_year > x)
2674 		min_year = x;
2675 	if (max_year < x)
2676 		max_year = x;
2677 }
2678 
2679 static int
stringoffset(char * result,zic_t offset)2680 stringoffset(char *result, zic_t offset)
2681 {
2682 	int			hours;
2683 	int			minutes;
2684 	int			seconds;
2685 	bool		negative = offset < 0;
2686 	int			len = negative;
2687 
2688 	if (negative)
2689 	{
2690 		offset = -offset;
2691 		result[0] = '-';
2692 	}
2693 	seconds = offset % SECSPERMIN;
2694 	offset /= SECSPERMIN;
2695 	minutes = offset % MINSPERHOUR;
2696 	offset /= MINSPERHOUR;
2697 	hours = offset;
2698 	if (hours >= HOURSPERDAY * DAYSPERWEEK)
2699 	{
2700 		result[0] = '\0';
2701 		return 0;
2702 	}
2703 	len += sprintf(result + len, "%d", hours);
2704 	if (minutes != 0 || seconds != 0)
2705 	{
2706 		len += sprintf(result + len, ":%02d", minutes);
2707 		if (seconds != 0)
2708 			len += sprintf(result + len, ":%02d", seconds);
2709 	}
2710 	return len;
2711 }
2712 
2713 static int
stringrule(char * result,struct rule * const rp,zic_t save,zic_t stdoff)2714 stringrule(char *result, struct rule *const rp, zic_t save, zic_t stdoff)
2715 {
2716 	zic_t		tod = rp->r_tod;
2717 	int			compat = 0;
2718 
2719 	if (rp->r_dycode == DC_DOM)
2720 	{
2721 		int			month,
2722 					total;
2723 
2724 		if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY)
2725 			return -1;
2726 		total = 0;
2727 		for (month = 0; month < rp->r_month; ++month)
2728 			total += len_months[0][month];
2729 		/* Omit the "J" in Jan and Feb, as that's shorter.  */
2730 		if (rp->r_month <= 1)
2731 			result += sprintf(result, "%d", total + rp->r_dayofmonth - 1);
2732 		else
2733 			result += sprintf(result, "J%d", total + rp->r_dayofmonth);
2734 	}
2735 	else
2736 	{
2737 		int			week;
2738 		int			wday = rp->r_wday;
2739 		int			wdayoff;
2740 
2741 		if (rp->r_dycode == DC_DOWGEQ)
2742 		{
2743 			wdayoff = (rp->r_dayofmonth - 1) % DAYSPERWEEK;
2744 			if (wdayoff)
2745 				compat = 2013;
2746 			wday -= wdayoff;
2747 			tod += wdayoff * SECSPERDAY;
2748 			week = 1 + (rp->r_dayofmonth - 1) / DAYSPERWEEK;
2749 		}
2750 		else if (rp->r_dycode == DC_DOWLEQ)
2751 		{
2752 			if (rp->r_dayofmonth == len_months[1][rp->r_month])
2753 				week = 5;
2754 			else
2755 			{
2756 				wdayoff = rp->r_dayofmonth % DAYSPERWEEK;
2757 				if (wdayoff)
2758 					compat = 2013;
2759 				wday -= wdayoff;
2760 				tod += wdayoff * SECSPERDAY;
2761 				week = rp->r_dayofmonth / DAYSPERWEEK;
2762 			}
2763 		}
2764 		else
2765 			return -1;			/* "cannot happen" */
2766 		if (wday < 0)
2767 			wday += DAYSPERWEEK;
2768 		result += sprintf(result, "M%d.%d.%d",
2769 						  rp->r_month + 1, week, wday);
2770 	}
2771 	if (rp->r_todisut)
2772 		tod += stdoff;
2773 	if (rp->r_todisstd && !rp->r_isdst)
2774 		tod += save;
2775 	if (tod != 2 * SECSPERMIN * MINSPERHOUR)
2776 	{
2777 		*result++ = '/';
2778 		if (!stringoffset(result, tod))
2779 			return -1;
2780 		if (tod < 0)
2781 		{
2782 			if (compat < 2013)
2783 				compat = 2013;
2784 		}
2785 		else if (SECSPERDAY <= tod)
2786 		{
2787 			if (compat < 1994)
2788 				compat = 1994;
2789 		}
2790 	}
2791 	return compat;
2792 }
2793 
2794 static int
rule_cmp(struct rule const * a,struct rule const * b)2795 rule_cmp(struct rule const *a, struct rule const *b)
2796 {
2797 	if (!a)
2798 		return -!!b;
2799 	if (!b)
2800 		return 1;
2801 	if (a->r_hiyear != b->r_hiyear)
2802 		return a->r_hiyear < b->r_hiyear ? -1 : 1;
2803 	if (a->r_month - b->r_month != 0)
2804 		return a->r_month - b->r_month;
2805 	return a->r_dayofmonth - b->r_dayofmonth;
2806 }
2807 
2808 static int
stringzone(char * result,struct zone const * zpfirst,ptrdiff_t zonecount)2809 stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
2810 {
2811 	const struct zone *zp;
2812 	struct rule *rp;
2813 	struct rule *stdrp;
2814 	struct rule *dstrp;
2815 	ptrdiff_t	i;
2816 	const char *abbrvar;
2817 	int			compat = 0;
2818 	int			c;
2819 	size_t		len;
2820 	int			offsetlen;
2821 	struct rule stdr,
2822 				dstr;
2823 
2824 	result[0] = '\0';
2825 
2826 	/*
2827 	 * Internet RFC 8536 section 5.1 says to use an empty TZ string if future
2828 	 * timestamps are truncated.
2829 	 */
2830 	if (hi_time < max_time)
2831 		return -1;
2832 
2833 	zp = zpfirst + zonecount - 1;
2834 	stdrp = dstrp = NULL;
2835 	for (i = 0; i < zp->z_nrules; ++i)
2836 	{
2837 		rp = &zp->z_rules[i];
2838 		if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX)
2839 			continue;
2840 		if (!rp->r_isdst)
2841 		{
2842 			if (stdrp == NULL)
2843 				stdrp = rp;
2844 			else
2845 				return -1;
2846 		}
2847 		else
2848 		{
2849 			if (dstrp == NULL)
2850 				dstrp = rp;
2851 			else
2852 				return -1;
2853 		}
2854 	}
2855 	if (stdrp == NULL && dstrp == NULL)
2856 	{
2857 		/*
2858 		 * There are no rules running through "max". Find the latest std rule
2859 		 * in stdabbrrp and latest rule of any type in stdrp.
2860 		 */
2861 		struct rule *stdabbrrp = NULL;
2862 
2863 		for (i = 0; i < zp->z_nrules; ++i)
2864 		{
2865 			rp = &zp->z_rules[i];
2866 			if (!rp->r_isdst && rule_cmp(stdabbrrp, rp) < 0)
2867 				stdabbrrp = rp;
2868 			if (rule_cmp(stdrp, rp) < 0)
2869 				stdrp = rp;
2870 		}
2871 		if (stdrp != NULL && stdrp->r_isdst)
2872 		{
2873 			/* Perpetual DST.  */
2874 			dstr.r_month = TM_JANUARY;
2875 			dstr.r_dycode = DC_DOM;
2876 			dstr.r_dayofmonth = 1;
2877 			dstr.r_tod = 0;
2878 			dstr.r_todisstd = dstr.r_todisut = false;
2879 			dstr.r_isdst = stdrp->r_isdst;
2880 			dstr.r_save = stdrp->r_save;
2881 			dstr.r_abbrvar = stdrp->r_abbrvar;
2882 			stdr.r_month = TM_DECEMBER;
2883 			stdr.r_dycode = DC_DOM;
2884 			stdr.r_dayofmonth = 31;
2885 			stdr.r_tod = SECSPERDAY + stdrp->r_save;
2886 			stdr.r_todisstd = stdr.r_todisut = false;
2887 			stdr.r_isdst = false;
2888 			stdr.r_save = 0;
2889 			stdr.r_abbrvar
2890 				= (stdabbrrp ? stdabbrrp->r_abbrvar : "");
2891 			dstrp = &dstr;
2892 			stdrp = &stdr;
2893 		}
2894 	}
2895 	if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_isdst))
2896 		return -1;
2897 	abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
2898 	len = doabbr(result, zp, abbrvar, false, 0, true);
2899 	offsetlen = stringoffset(result + len, -zp->z_stdoff);
2900 	if (!offsetlen)
2901 	{
2902 		result[0] = '\0';
2903 		return -1;
2904 	}
2905 	len += offsetlen;
2906 	if (dstrp == NULL)
2907 		return compat;
2908 	len += doabbr(result + len, zp, dstrp->r_abbrvar,
2909 				  dstrp->r_isdst, dstrp->r_save, true);
2910 	if (dstrp->r_save != SECSPERMIN * MINSPERHOUR)
2911 	{
2912 		offsetlen = stringoffset(result + len,
2913 								 -(zp->z_stdoff + dstrp->r_save));
2914 		if (!offsetlen)
2915 		{
2916 			result[0] = '\0';
2917 			return -1;
2918 		}
2919 		len += offsetlen;
2920 	}
2921 	result[len++] = ',';
2922 	c = stringrule(result + len, dstrp, dstrp->r_save, zp->z_stdoff);
2923 	if (c < 0)
2924 	{
2925 		result[0] = '\0';
2926 		return -1;
2927 	}
2928 	if (compat < c)
2929 		compat = c;
2930 	len += strlen(result + len);
2931 	result[len++] = ',';
2932 	c = stringrule(result + len, stdrp, dstrp->r_save, zp->z_stdoff);
2933 	if (c < 0)
2934 	{
2935 		result[0] = '\0';
2936 		return -1;
2937 	}
2938 	if (compat < c)
2939 		compat = c;
2940 	return compat;
2941 }
2942 
2943 static void
outzone(const struct zone * zpfirst,ptrdiff_t zonecount)2944 outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
2945 {
2946 	const struct zone *zp;
2947 	struct rule *rp;
2948 	ptrdiff_t	i,
2949 				j;
2950 	bool		usestart,
2951 				useuntil;
2952 	zic_t		starttime,
2953 				untiltime;
2954 	zic_t		stdoff;
2955 	zic_t		save;
2956 	zic_t		year;
2957 	zic_t		startoff;
2958 	bool		startttisstd;
2959 	bool		startttisut;
2960 	int			type;
2961 	char	   *startbuf;
2962 	char	   *ab;
2963 	char	   *envvar;
2964 	int			max_abbr_len;
2965 	int			max_envvar_len;
2966 	bool		prodstic;		/* all rules are min to max */
2967 	int			compat;
2968 	bool		do_extend;
2969 	char		version;
2970 	ptrdiff_t	lastatmax = -1;
2971 	zic_t		one = 1;
2972 	zic_t		y2038_boundary = one << 31;
2973 	zic_t		max_year0;
2974 	int			defaulttype = -1;
2975 
2976 	max_abbr_len = 2 + max_format_len + max_abbrvar_len;
2977 	max_envvar_len = 2 * max_abbr_len + 5 * 9;
2978 	startbuf = emalloc(max_abbr_len + 1);
2979 	ab = emalloc(max_abbr_len + 1);
2980 	envvar = emalloc(max_envvar_len + 1);
2981 	INITIALIZE(untiltime);
2982 	INITIALIZE(starttime);
2983 
2984 	/*
2985 	 * Now. . .finally. . .generate some useful data!
2986 	 */
2987 	timecnt = 0;
2988 	typecnt = 0;
2989 	charcnt = 0;
2990 	prodstic = zonecount == 1;
2991 
2992 	/*
2993 	 * Thanks to Earl Chew for noting the need to unconditionally initialize
2994 	 * startttisstd.
2995 	 */
2996 	startttisstd = false;
2997 	startttisut = false;
2998 	min_year = max_year = EPOCH_YEAR;
2999 	if (leapseen)
3000 	{
3001 		updateminmax(leapminyear);
3002 		updateminmax(leapmaxyear + (leapmaxyear < ZIC_MAX));
3003 	}
3004 	for (i = 0; i < zonecount; ++i)
3005 	{
3006 		zp = &zpfirst[i];
3007 		if (i < zonecount - 1)
3008 			updateminmax(zp->z_untilrule.r_loyear);
3009 		for (j = 0; j < zp->z_nrules; ++j)
3010 		{
3011 			rp = &zp->z_rules[j];
3012 			if (rp->r_lowasnum)
3013 				updateminmax(rp->r_loyear);
3014 			if (rp->r_hiwasnum)
3015 				updateminmax(rp->r_hiyear);
3016 			if (rp->r_lowasnum || rp->r_hiwasnum)
3017 				prodstic = false;
3018 		}
3019 	}
3020 
3021 	/*
3022 	 * Generate lots of data if a rule can't cover all future times.
3023 	 */
3024 	compat = stringzone(envvar, zpfirst, zonecount);
3025 	version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION;
3026 	do_extend = compat < 0;
3027 	if (noise)
3028 	{
3029 		if (!*envvar)
3030 			warning("%s %s",
3031 					_("no POSIX environment variable for zone"),
3032 					zpfirst->z_name);
3033 		else if (compat != 0)
3034 		{
3035 			/*
3036 			 * Circa-COMPAT clients, and earlier clients, might not work for
3037 			 * this zone when given dates before 1970 or after 2038.
3038 			 */
3039 			warning(_("%s: pre-%d clients may mishandle"
3040 					  " distant timestamps"),
3041 					zpfirst->z_name, compat);
3042 		}
3043 	}
3044 	if (do_extend)
3045 	{
3046 		/*
3047 		 * Search through a couple of extra years past the obvious 400, to
3048 		 * avoid edge cases.  For example, suppose a non-POSIX rule applies
3049 		 * from 2012 onwards and has transitions in March and September, plus
3050 		 * some one-off transitions in November 2013.  If zic looked only at
3051 		 * the last 400 years, it would set max_year=2413, with the intent
3052 		 * that the 400 years 2014 through 2413 will be repeated.  The last
3053 		 * transition listed in the tzfile would be in 2413-09, less than 400
3054 		 * years after the last one-off transition in 2013-11.  Two years
3055 		 * might be overkill, but with the kind of edge cases available we're
3056 		 * not sure that one year would suffice.
3057 		 */
3058 		enum
3059 		{
3060 		years_of_observations = YEARSPERREPEAT + 2};
3061 
3062 		if (min_year >= ZIC_MIN + years_of_observations)
3063 			min_year -= years_of_observations;
3064 		else
3065 			min_year = ZIC_MIN;
3066 		if (max_year <= ZIC_MAX - years_of_observations)
3067 			max_year += years_of_observations;
3068 		else
3069 			max_year = ZIC_MAX;
3070 
3071 		/*
3072 		 * Regardless of any of the above, for a "proDSTic" zone which
3073 		 * specifies that its rules always have and always will be in effect,
3074 		 * we only need one cycle to define the zone.
3075 		 */
3076 		if (prodstic)
3077 		{
3078 			min_year = 1900;
3079 			max_year = min_year + years_of_observations;
3080 		}
3081 	}
3082 	max_year0 = max_year;
3083 	if (want_bloat())
3084 	{
3085 		/*
3086 		 * For the benefit of older systems, generate data from 1900 through
3087 		 * 2038.
3088 		 */
3089 		if (min_year > 1900)
3090 			min_year = 1900;
3091 		if (max_year < 2038)
3092 			max_year = 2038;
3093 	}
3094 
3095 	for (i = 0; i < zonecount; ++i)
3096 	{
3097 		struct rule *prevrp = NULL;
3098 
3099 		/*
3100 		 * A guess that may well be corrected later.
3101 		 */
3102 		save = 0;
3103 		zp = &zpfirst[i];
3104 		usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
3105 		useuntil = i < (zonecount - 1);
3106 		if (useuntil && zp->z_untiltime <= min_time)
3107 			continue;
3108 		stdoff = zp->z_stdoff;
3109 		eat(zp->z_filename, zp->z_linenum);
3110 		*startbuf = '\0';
3111 		startoff = zp->z_stdoff;
3112 		if (zp->z_nrules == 0)
3113 		{
3114 			save = zp->z_save;
3115 			doabbr(startbuf, zp, NULL, zp->z_isdst, save, false);
3116 			type = addtype(oadd(zp->z_stdoff, save),
3117 						   startbuf, zp->z_isdst, startttisstd,
3118 						   startttisut);
3119 			if (usestart)
3120 			{
3121 				addtt(starttime, type);
3122 				usestart = false;
3123 			}
3124 			else
3125 				defaulttype = type;
3126 		}
3127 		else
3128 			for (year = min_year; year <= max_year; ++year)
3129 			{
3130 				if (useuntil && year > zp->z_untilrule.r_hiyear)
3131 					break;
3132 
3133 				/*
3134 				 * Mark which rules to do in the current year. For those to
3135 				 * do, calculate rpytime(rp, year); The former TYPE field was
3136 				 * also considered here.
3137 				 */
3138 				for (j = 0; j < zp->z_nrules; ++j)
3139 				{
3140 					rp = &zp->z_rules[j];
3141 					eats(zp->z_filename, zp->z_linenum,
3142 						 rp->r_filename, rp->r_linenum);
3143 					rp->r_todo = year >= rp->r_loyear &&
3144 						year <= rp->r_hiyear;
3145 					if (rp->r_todo)
3146 					{
3147 						rp->r_temp = rpytime(rp, year);
3148 						rp->r_todo
3149 							= (rp->r_temp < y2038_boundary
3150 							   || year <= max_year0);
3151 					}
3152 				}
3153 				for (;;)
3154 				{
3155 					ptrdiff_t	k;
3156 					zic_t		jtime,
3157 								ktime;
3158 					zic_t		offset;
3159 
3160 					INITIALIZE(ktime);
3161 					if (useuntil)
3162 					{
3163 						/*
3164 						 * Turn untiltime into UT assuming the current stdoff
3165 						 * and save values.
3166 						 */
3167 						untiltime = zp->z_untiltime;
3168 						if (!zp->z_untilrule.r_todisut)
3169 							untiltime = tadd(untiltime,
3170 											 -stdoff);
3171 						if (!zp->z_untilrule.r_todisstd)
3172 							untiltime = tadd(untiltime,
3173 											 -save);
3174 					}
3175 
3176 					/*
3177 					 * Find the rule (of those to do, if any) that takes
3178 					 * effect earliest in the year.
3179 					 */
3180 					k = -1;
3181 					for (j = 0; j < zp->z_nrules; ++j)
3182 					{
3183 						rp = &zp->z_rules[j];
3184 						if (!rp->r_todo)
3185 							continue;
3186 						eats(zp->z_filename, zp->z_linenum,
3187 							 rp->r_filename, rp->r_linenum);
3188 						offset = rp->r_todisut ? 0 : stdoff;
3189 						if (!rp->r_todisstd)
3190 							offset = oadd(offset, save);
3191 						jtime = rp->r_temp;
3192 						if (jtime == min_time ||
3193 							jtime == max_time)
3194 							continue;
3195 						jtime = tadd(jtime, -offset);
3196 						if (k < 0 || jtime < ktime)
3197 						{
3198 							k = j;
3199 							ktime = jtime;
3200 						}
3201 						else if (jtime == ktime)
3202 						{
3203 							char const *dup_rules_msg =
3204 							_("two rules for same instant");
3205 
3206 							eats(zp->z_filename, zp->z_linenum,
3207 								 rp->r_filename, rp->r_linenum);
3208 							warning("%s", dup_rules_msg);
3209 							rp = &zp->z_rules[k];
3210 							eats(zp->z_filename, zp->z_linenum,
3211 								 rp->r_filename, rp->r_linenum);
3212 							error("%s", dup_rules_msg);
3213 						}
3214 					}
3215 					if (k < 0)
3216 						break;	/* go on to next year */
3217 					rp = &zp->z_rules[k];
3218 					rp->r_todo = false;
3219 					if (useuntil && ktime >= untiltime)
3220 						break;
3221 					save = rp->r_save;
3222 					if (usestart && ktime == starttime)
3223 						usestart = false;
3224 					if (usestart)
3225 					{
3226 						if (ktime < starttime)
3227 						{
3228 							startoff = oadd(zp->z_stdoff,
3229 											save);
3230 							doabbr(startbuf, zp,
3231 								   rp->r_abbrvar,
3232 								   rp->r_isdst,
3233 								   rp->r_save,
3234 								   false);
3235 							continue;
3236 						}
3237 						if (*startbuf == '\0'
3238 							&& startoff == oadd(zp->z_stdoff,
3239 												save))
3240 						{
3241 							doabbr(startbuf,
3242 								   zp,
3243 								   rp->r_abbrvar,
3244 								   rp->r_isdst,
3245 								   rp->r_save,
3246 								   false);
3247 						}
3248 					}
3249 					eats(zp->z_filename, zp->z_linenum,
3250 						 rp->r_filename, rp->r_linenum);
3251 					doabbr(ab, zp, rp->r_abbrvar,
3252 						   rp->r_isdst, rp->r_save, false);
3253 					offset = oadd(zp->z_stdoff, rp->r_save);
3254 					if (!want_bloat() && !useuntil && !do_extend
3255 						&& prevrp
3256 						&& rp->r_hiyear == ZIC_MAX
3257 						&& prevrp->r_hiyear == ZIC_MAX)
3258 						break;
3259 					type = addtype(offset, ab, rp->r_isdst,
3260 								   rp->r_todisstd, rp->r_todisut);
3261 					if (defaulttype < 0 && !rp->r_isdst)
3262 						defaulttype = type;
3263 					if (rp->r_hiyear == ZIC_MAX
3264 						&& !(0 <= lastatmax
3265 							 && ktime < attypes[lastatmax].at))
3266 						lastatmax = timecnt;
3267 					addtt(ktime, type);
3268 					prevrp = rp;
3269 				}
3270 			}
3271 		if (usestart)
3272 		{
3273 			if (*startbuf == '\0' &&
3274 				zp->z_format != NULL &&
3275 				strchr(zp->z_format, '%') == NULL &&
3276 				strchr(zp->z_format, '/') == NULL)
3277 				strcpy(startbuf, zp->z_format);
3278 			eat(zp->z_filename, zp->z_linenum);
3279 			if (*startbuf == '\0')
3280 				error(_("cannot determine time zone abbreviation to use just after until time"));
3281 			else
3282 			{
3283 				bool		isdst = startoff != zp->z_stdoff;
3284 
3285 				type = addtype(startoff, startbuf, isdst,
3286 							   startttisstd, startttisut);
3287 				if (defaulttype < 0 && !isdst)
3288 					defaulttype = type;
3289 				addtt(starttime, type);
3290 			}
3291 		}
3292 
3293 		/*
3294 		 * Now we may get to set starttime for the next zone line.
3295 		 */
3296 		if (useuntil)
3297 		{
3298 			startttisstd = zp->z_untilrule.r_todisstd;
3299 			startttisut = zp->z_untilrule.r_todisut;
3300 			starttime = zp->z_untiltime;
3301 			if (!startttisstd)
3302 				starttime = tadd(starttime, -save);
3303 			if (!startttisut)
3304 				starttime = tadd(starttime, -stdoff);
3305 		}
3306 	}
3307 	if (defaulttype < 0)
3308 		defaulttype = 0;
3309 	if (0 <= lastatmax)
3310 		attypes[lastatmax].dontmerge = true;
3311 	if (do_extend)
3312 	{
3313 		/*
3314 		 * If we're extending the explicitly listed observations for 400 years
3315 		 * because we can't fill the POSIX-TZ field, check whether we actually
3316 		 * ended up explicitly listing observations through that period.  If
3317 		 * there aren't any near the end of the 400-year period, add a
3318 		 * redundant one at the end of the final year, to make it clear that
3319 		 * we are claiming to have definite knowledge of the lack of
3320 		 * transitions up to that point.
3321 		 */
3322 		struct rule xr;
3323 		struct attype *lastat;
3324 
3325 		xr.r_month = TM_JANUARY;
3326 		xr.r_dycode = DC_DOM;
3327 		xr.r_dayofmonth = 1;
3328 		xr.r_tod = 0;
3329 		for (lastat = attypes, i = 1; i < timecnt; i++)
3330 			if (attypes[i].at > lastat->at)
3331 				lastat = &attypes[i];
3332 		if (!lastat || lastat->at < rpytime(&xr, max_year - 1))
3333 		{
3334 			addtt(rpytime(&xr, max_year + 1),
3335 				  lastat ? lastat->type : defaulttype);
3336 			attypes[timecnt - 1].dontmerge = true;
3337 		}
3338 	}
3339 	writezone(zpfirst->z_name, envvar, version, defaulttype);
3340 	free(startbuf);
3341 	free(ab);
3342 	free(envvar);
3343 }
3344 
3345 static void
addtt(zic_t starttime,int type)3346 addtt(zic_t starttime, int type)
3347 {
3348 	attypes = growalloc(attypes, sizeof *attypes, timecnt, &timecnt_alloc);
3349 	attypes[timecnt].at = starttime;
3350 	attypes[timecnt].dontmerge = false;
3351 	attypes[timecnt].type = type;
3352 	++timecnt;
3353 }
3354 
3355 static int
addtype(zic_t utoff,char const * abbr,bool isdst,bool ttisstd,bool ttisut)3356 addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut)
3357 {
3358 	int			i,
3359 				j;
3360 
3361 	if (!(-1L - 2147483647L <= utoff && utoff <= 2147483647L))
3362 	{
3363 		error(_("UT offset out of range"));
3364 		exit(EXIT_FAILURE);
3365 	}
3366 	if (!want_bloat())
3367 		ttisstd = ttisut = false;
3368 
3369 	for (j = 0; j < charcnt; ++j)
3370 		if (strcmp(&chars[j], abbr) == 0)
3371 			break;
3372 	if (j == charcnt)
3373 		newabbr(abbr);
3374 	else
3375 	{
3376 		/* If there's already an entry, return its index.  */
3377 		for (i = 0; i < typecnt; i++)
3378 			if (utoff == utoffs[i] && isdst == isdsts[i] && j == desigidx[i]
3379 				&& ttisstd == ttisstds[i] && ttisut == ttisuts[i])
3380 				return i;
3381 	}
3382 
3383 	/*
3384 	 * There isn't one; add a new one, unless there are already too many.
3385 	 */
3386 	if (typecnt >= TZ_MAX_TYPES)
3387 	{
3388 		error(_("too many local time types"));
3389 		exit(EXIT_FAILURE);
3390 	}
3391 	i = typecnt++;
3392 	utoffs[i] = utoff;
3393 	isdsts[i] = isdst;
3394 	ttisstds[i] = ttisstd;
3395 	ttisuts[i] = ttisut;
3396 	desigidx[i] = j;
3397 	return i;
3398 }
3399 
3400 static void
leapadd(zic_t t,int correction,int rolling)3401 leapadd(zic_t t, int correction, int rolling)
3402 {
3403 	int			i;
3404 
3405 	if (TZ_MAX_LEAPS <= leapcnt)
3406 	{
3407 		error(_("too many leap seconds"));
3408 		exit(EXIT_FAILURE);
3409 	}
3410 	for (i = 0; i < leapcnt; ++i)
3411 		if (t <= trans[i])
3412 			break;
3413 	memmove(&trans[i + 1], &trans[i], (leapcnt - i) * sizeof *trans);
3414 	memmove(&corr[i + 1], &corr[i], (leapcnt - i) * sizeof *corr);
3415 	memmove(&roll[i + 1], &roll[i], (leapcnt - i) * sizeof *roll);
3416 	trans[i] = t;
3417 	corr[i] = correction;
3418 	roll[i] = rolling;
3419 	++leapcnt;
3420 }
3421 
3422 static void
adjleap(void)3423 adjleap(void)
3424 {
3425 	int			i;
3426 	zic_t		last = 0;
3427 	zic_t		prevtrans = 0;
3428 
3429 	/*
3430 	 * propagate leap seconds forward
3431 	 */
3432 	for (i = 0; i < leapcnt; ++i)
3433 	{
3434 		if (trans[i] - prevtrans < 28 * SECSPERDAY)
3435 		{
3436 			error(_("Leap seconds too close together"));
3437 			exit(EXIT_FAILURE);
3438 		}
3439 		prevtrans = trans[i];
3440 		trans[i] = tadd(trans[i], last);
3441 		last = corr[i] += last;
3442 	}
3443 
3444 	if (leapexpires < 0)
3445 	{
3446 		leapexpires = comment_leapexpires;
3447 		if (0 <= leapexpires)
3448 			warning(_("\"#expires\" is obsolescent; use \"Expires\""));
3449 	}
3450 
3451 	if (0 <= leapexpires)
3452 	{
3453 		leapexpires = oadd(leapexpires, last);
3454 		if (!(leapcnt == 0 || (trans[leapcnt - 1] < leapexpires)))
3455 		{
3456 			error(_("last Leap time does not precede Expires time"));
3457 			exit(EXIT_FAILURE);
3458 		}
3459 		if (leapexpires <= hi_time)
3460 			hi_time = leapexpires - 1;
3461 	}
3462 }
3463 
3464 /* Is A a space character in the C locale?  */
3465 static bool
is_space(char a)3466 is_space(char a)
3467 {
3468 	switch (a)
3469 	{
3470 		default:
3471 			return false;
3472 		case ' ':
3473 		case '\f':
3474 		case '\n':
3475 		case '\r':
3476 		case '\t':
3477 		case '\v':
3478 			return true;
3479 	}
3480 }
3481 
3482 /* Is A an alphabetic character in the C locale?  */
3483 static bool
is_alpha(char a)3484 is_alpha(char a)
3485 {
3486 	switch (a)
3487 	{
3488 		default:
3489 			return false;
3490 		case 'A':
3491 		case 'B':
3492 		case 'C':
3493 		case 'D':
3494 		case 'E':
3495 		case 'F':
3496 		case 'G':
3497 		case 'H':
3498 		case 'I':
3499 		case 'J':
3500 		case 'K':
3501 		case 'L':
3502 		case 'M':
3503 		case 'N':
3504 		case 'O':
3505 		case 'P':
3506 		case 'Q':
3507 		case 'R':
3508 		case 'S':
3509 		case 'T':
3510 		case 'U':
3511 		case 'V':
3512 		case 'W':
3513 		case 'X':
3514 		case 'Y':
3515 		case 'Z':
3516 		case 'a':
3517 		case 'b':
3518 		case 'c':
3519 		case 'd':
3520 		case 'e':
3521 		case 'f':
3522 		case 'g':
3523 		case 'h':
3524 		case 'i':
3525 		case 'j':
3526 		case 'k':
3527 		case 'l':
3528 		case 'm':
3529 		case 'n':
3530 		case 'o':
3531 		case 'p':
3532 		case 'q':
3533 		case 'r':
3534 		case 's':
3535 		case 't':
3536 		case 'u':
3537 		case 'v':
3538 		case 'w':
3539 		case 'x':
3540 		case 'y':
3541 		case 'z':
3542 			return true;
3543 	}
3544 }
3545 
3546 /* If A is an uppercase character in the C locale, return its lowercase
3547    counterpart.  Otherwise, return A.  */
3548 static char
lowerit(char a)3549 lowerit(char a)
3550 {
3551 	switch (a)
3552 	{
3553 		default:
3554 			return a;
3555 		case 'A':
3556 			return 'a';
3557 		case 'B':
3558 			return 'b';
3559 		case 'C':
3560 			return 'c';
3561 		case 'D':
3562 			return 'd';
3563 		case 'E':
3564 			return 'e';
3565 		case 'F':
3566 			return 'f';
3567 		case 'G':
3568 			return 'g';
3569 		case 'H':
3570 			return 'h';
3571 		case 'I':
3572 			return 'i';
3573 		case 'J':
3574 			return 'j';
3575 		case 'K':
3576 			return 'k';
3577 		case 'L':
3578 			return 'l';
3579 		case 'M':
3580 			return 'm';
3581 		case 'N':
3582 			return 'n';
3583 		case 'O':
3584 			return 'o';
3585 		case 'P':
3586 			return 'p';
3587 		case 'Q':
3588 			return 'q';
3589 		case 'R':
3590 			return 'r';
3591 		case 'S':
3592 			return 's';
3593 		case 'T':
3594 			return 't';
3595 		case 'U':
3596 			return 'u';
3597 		case 'V':
3598 			return 'v';
3599 		case 'W':
3600 			return 'w';
3601 		case 'X':
3602 			return 'x';
3603 		case 'Y':
3604 			return 'y';
3605 		case 'Z':
3606 			return 'z';
3607 	}
3608 }
3609 
3610 /* case-insensitive equality */
3611 static bool
ciequal(const char * ap,const char * bp)3612 ciequal(const char *ap, const char *bp)
3613 {
3614 	while (lowerit(*ap) == lowerit(*bp++))
3615 		if (*ap++ == '\0')
3616 			return true;
3617 	return false;
3618 }
3619 
3620 static bool
itsabbr(const char * abbr,const char * word)3621 itsabbr(const char *abbr, const char *word)
3622 {
3623 	if (lowerit(*abbr) != lowerit(*word))
3624 		return false;
3625 	++word;
3626 	while (*++abbr != '\0')
3627 		do
3628 		{
3629 			if (*word == '\0')
3630 				return false;
3631 		} while (lowerit(*word++) != lowerit(*abbr));
3632 	return true;
3633 }
3634 
3635 /* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case.  */
3636 
3637 static bool
ciprefix(char const * abbr,char const * word)3638 ciprefix(char const *abbr, char const *word)
3639 {
3640 	do
3641 		if (!*abbr)
3642 			return true;
3643 	while (lowerit(*abbr++) == lowerit(*word++));
3644 
3645 	return false;
3646 }
3647 
3648 static const struct lookup *
byword(const char * word,const struct lookup * table)3649 byword(const char *word, const struct lookup *table)
3650 {
3651 	const struct lookup *foundlp;
3652 	const struct lookup *lp;
3653 
3654 	if (word == NULL || table == NULL)
3655 		return NULL;
3656 
3657 	/*
3658 	 * If TABLE is LASTS and the word starts with "last" followed by a
3659 	 * non-'-', skip the "last" and look in WDAY_NAMES instead. Warn about any
3660 	 * usage of the undocumented prefix "last-".
3661 	 */
3662 	if (table == lasts && ciprefix("last", word) && word[4])
3663 	{
3664 		if (word[4] == '-')
3665 			warning(_("\"%s\" is undocumented; use \"last%s\" instead"),
3666 					word, word + 5);
3667 		else
3668 		{
3669 			word += 4;
3670 			table = wday_names;
3671 		}
3672 	}
3673 
3674 	/*
3675 	 * Look for exact match.
3676 	 */
3677 	for (lp = table; lp->l_word != NULL; ++lp)
3678 		if (ciequal(word, lp->l_word))
3679 			return lp;
3680 
3681 	/*
3682 	 * Look for inexact match.
3683 	 */
3684 	foundlp = NULL;
3685 	for (lp = table; lp->l_word != NULL; ++lp)
3686 		if (ciprefix(word, lp->l_word))
3687 		{
3688 			if (foundlp == NULL)
3689 				foundlp = lp;
3690 			else
3691 				return NULL;	/* multiple inexact matches */
3692 		}
3693 
3694 	if (foundlp && noise)
3695 	{
3696 		/* Warn about any backward-compatibility issue with pre-2017c zic.  */
3697 		bool		pre_2017c_match = false;
3698 
3699 		for (lp = table; lp->l_word; lp++)
3700 			if (itsabbr(word, lp->l_word))
3701 			{
3702 				if (pre_2017c_match)
3703 				{
3704 					warning(_("\"%s\" is ambiguous in pre-2017c zic"), word);
3705 					break;
3706 				}
3707 				pre_2017c_match = true;
3708 			}
3709 	}
3710 
3711 	return foundlp;
3712 }
3713 
3714 static char **
getfields(char * cp)3715 getfields(char *cp)
3716 {
3717 	char	   *dp;
3718 	char	  **array;
3719 	int			nsubs;
3720 
3721 	if (cp == NULL)
3722 		return NULL;
3723 	array = emalloc(size_product(strlen(cp) + 1, sizeof *array));
3724 	nsubs = 0;
3725 	for (;;)
3726 	{
3727 		while (is_space(*cp))
3728 			++cp;
3729 		if (*cp == '\0' || *cp == '#')
3730 			break;
3731 		array[nsubs++] = dp = cp;
3732 		do
3733 		{
3734 			if ((*dp = *cp++) != '"')
3735 				++dp;
3736 			else
3737 				while ((*dp = *cp++) != '"')
3738 					if (*dp != '\0')
3739 						++dp;
3740 					else
3741 					{
3742 						error(_("Odd number of quotation marks"));
3743 						exit(EXIT_FAILURE);
3744 					}
3745 		} while (*cp && *cp != '#' && !is_space(*cp));
3746 		if (is_space(*cp))
3747 			++cp;
3748 		*dp = '\0';
3749 	}
3750 	array[nsubs] = NULL;
3751 	return array;
3752 }
3753 
3754 static void
time_overflow(void)3755 time_overflow(void)
3756 {
3757 	error(_("time overflow"));
3758 	exit(EXIT_FAILURE);
3759 }
3760 
3761 static zic_t
oadd(zic_t t1,zic_t t2)3762 oadd(zic_t t1, zic_t t2)
3763 {
3764 	if (t1 < 0 ? t2 < ZIC_MIN - t1 : ZIC_MAX - t1 < t2)
3765 		time_overflow();
3766 	return t1 + t2;
3767 }
3768 
3769 static zic_t
tadd(zic_t t1,zic_t t2)3770 tadd(zic_t t1, zic_t t2)
3771 {
3772 	if (t1 < 0)
3773 	{
3774 		if (t2 < min_time - t1)
3775 		{
3776 			if (t1 != min_time)
3777 				time_overflow();
3778 			return min_time;
3779 		}
3780 	}
3781 	else
3782 	{
3783 		if (max_time - t1 < t2)
3784 		{
3785 			if (t1 != max_time)
3786 				time_overflow();
3787 			return max_time;
3788 		}
3789 	}
3790 	return t1 + t2;
3791 }
3792 
3793 /*
3794  * Given a rule, and a year, compute the date (in seconds since January 1,
3795  * 1970, 00:00 LOCAL time) in that year that the rule refers to.
3796  */
3797 
3798 static zic_t
rpytime(const struct rule * rp,zic_t wantedy)3799 rpytime(const struct rule *rp, zic_t wantedy)
3800 {
3801 	int			m,
3802 				i;
3803 	zic_t		dayoff;			/* with a nod to Margaret O. */
3804 	zic_t		t,
3805 				y;
3806 
3807 	if (wantedy == ZIC_MIN)
3808 		return min_time;
3809 	if (wantedy == ZIC_MAX)
3810 		return max_time;
3811 	dayoff = 0;
3812 	m = TM_JANUARY;
3813 	y = EPOCH_YEAR;
3814 	if (y < wantedy)
3815 	{
3816 		wantedy -= y;
3817 		dayoff = (wantedy / YEARSPERREPEAT) * (SECSPERREPEAT / SECSPERDAY);
3818 		wantedy %= YEARSPERREPEAT;
3819 		wantedy += y;
3820 	}
3821 	else if (wantedy < 0)
3822 	{
3823 		dayoff = (wantedy / YEARSPERREPEAT) * (SECSPERREPEAT / SECSPERDAY);
3824 		wantedy %= YEARSPERREPEAT;
3825 	}
3826 	while (wantedy != y)
3827 	{
3828 		if (wantedy > y)
3829 		{
3830 			i = len_years[isleap(y)];
3831 			++y;
3832 		}
3833 		else
3834 		{
3835 			--y;
3836 			i = -len_years[isleap(y)];
3837 		}
3838 		dayoff = oadd(dayoff, i);
3839 	}
3840 	while (m != rp->r_month)
3841 	{
3842 		i = len_months[isleap(y)][m];
3843 		dayoff = oadd(dayoff, i);
3844 		++m;
3845 	}
3846 	i = rp->r_dayofmonth;
3847 	if (m == TM_FEBRUARY && i == 29 && !isleap(y))
3848 	{
3849 		if (rp->r_dycode == DC_DOWLEQ)
3850 			--i;
3851 		else
3852 		{
3853 			error(_("use of 2/29 in non leap-year"));
3854 			exit(EXIT_FAILURE);
3855 		}
3856 	}
3857 	--i;
3858 	dayoff = oadd(dayoff, i);
3859 	if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ)
3860 	{
3861 		zic_t		wday;
3862 
3863 #define LDAYSPERWEEK	((zic_t) DAYSPERWEEK)
3864 		wday = EPOCH_WDAY;
3865 
3866 		/*
3867 		 * Don't trust mod of negative numbers.
3868 		 */
3869 		if (dayoff >= 0)
3870 			wday = (wday + dayoff) % LDAYSPERWEEK;
3871 		else
3872 		{
3873 			wday -= ((-dayoff) % LDAYSPERWEEK);
3874 			if (wday < 0)
3875 				wday += LDAYSPERWEEK;
3876 		}
3877 		while (wday != rp->r_wday)
3878 			if (rp->r_dycode == DC_DOWGEQ)
3879 			{
3880 				dayoff = oadd(dayoff, 1);
3881 				if (++wday >= LDAYSPERWEEK)
3882 					wday = 0;
3883 				++i;
3884 			}
3885 			else
3886 			{
3887 				dayoff = oadd(dayoff, -1);
3888 				if (--wday < 0)
3889 					wday = LDAYSPERWEEK - 1;
3890 				--i;
3891 			}
3892 		if (i < 0 || i >= len_months[isleap(y)][m])
3893 		{
3894 			if (noise)
3895 				warning(_("rule goes past start/end of month; \
3896 will not work with pre-2004 versions of zic"));
3897 		}
3898 	}
3899 	if (dayoff < min_time / SECSPERDAY)
3900 		return min_time;
3901 	if (dayoff > max_time / SECSPERDAY)
3902 		return max_time;
3903 	t = (zic_t) dayoff * SECSPERDAY;
3904 	return tadd(t, rp->r_tod);
3905 }
3906 
3907 static void
newabbr(const char * string)3908 newabbr(const char *string)
3909 {
3910 	int			i;
3911 
3912 	if (strcmp(string, GRANDPARENTED) != 0)
3913 	{
3914 		const char *cp;
3915 		const char *mp;
3916 
3917 		cp = string;
3918 		mp = NULL;
3919 		while (is_alpha(*cp) || ('0' <= *cp && *cp <= '9')
3920 			   || *cp == '-' || *cp == '+')
3921 			++cp;
3922 		if (noise && cp - string < 3)
3923 			mp = _("time zone abbreviation has fewer than 3 characters");
3924 		if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN)
3925 			mp = _("time zone abbreviation has too many characters");
3926 		if (*cp != '\0')
3927 			mp = _("time zone abbreviation differs from POSIX standard");
3928 		if (mp != NULL)
3929 			warning("%s (%s)", mp, string);
3930 	}
3931 	i = strlen(string) + 1;
3932 	if (charcnt + i > TZ_MAX_CHARS)
3933 	{
3934 		error(_("too many, or too long, time zone abbreviations"));
3935 		exit(EXIT_FAILURE);
3936 	}
3937 	strcpy(&chars[charcnt], string);
3938 	charcnt += i;
3939 }
3940 
3941 /* Ensure that the directories of ARGNAME exist, by making any missing
3942    ones.  If ANCESTORS, do this only for ARGNAME's ancestors; otherwise,
3943    do it for ARGNAME too.  Exit with failure if there is trouble.
3944    Do not consider an existing non-directory to be trouble.  */
3945 static void
mkdirs(char const * argname,bool ancestors)3946 mkdirs(char const *argname, bool ancestors)
3947 {
3948 	char	   *name;
3949 	char	   *cp;
3950 
3951 	cp = name = ecpyalloc(argname);
3952 
3953 	/*
3954 	 * On MS-Windows systems, do not worry about drive letters or backslashes,
3955 	 * as this should suffice in practice.  Time zone names do not use drive
3956 	 * letters and backslashes.  If the -d option of zic does not name an
3957 	 * already-existing directory, it can use slashes to separate the
3958 	 * already-existing ancestor prefix from the to-be-created subdirectories.
3959 	 */
3960 
3961 	/* Do not mkdir a root directory, as it must exist.  */
3962 	while (*cp == '/')
3963 		cp++;
3964 
3965 	while (cp && ((cp = strchr(cp, '/')) || !ancestors))
3966 	{
3967 		if (cp)
3968 			*cp = '\0';
3969 
3970 		/*
3971 		 * Try to create it.  It's OK if creation fails because the directory
3972 		 * already exists, perhaps because some other process just created it.
3973 		 * For simplicity do not check first whether it already exists, as
3974 		 * that is checked anyway if the mkdir fails.
3975 		 */
3976 		if (mkdir(name, MKDIR_UMASK) != 0)
3977 		{
3978 			/*
3979 			 * For speed, skip itsdir if errno == EEXIST.  Since mkdirs is
3980 			 * called only after open fails with ENOENT on a subfile, EEXIST
3981 			 * implies itsdir here.
3982 			 */
3983 			int			err = errno;
3984 
3985 			if (err != EEXIST && !itsdir(name))
3986 			{
3987 				error(_("%s: Cannot create directory %s: %s"),
3988 					  progname, name, strerror(err));
3989 				exit(EXIT_FAILURE);
3990 			}
3991 		}
3992 		if (cp)
3993 			*cp++ = '/';
3994 	}
3995 	free(name);
3996 }
3997 
3998 
3999 #ifdef WIN32
4000 /*
4001  * To run on win32
4002  */
4003 int
link(const char * oldpath,const char * newpath)4004 link(const char *oldpath, const char *newpath)
4005 {
4006 	if (!CopyFile(oldpath, newpath, false))
4007 	{
4008 		_dosmaperr(GetLastError());
4009 		return -1;
4010 	}
4011 	return 0;
4012 }
4013 #endif
4014