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