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