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