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