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