zic.c revision 1.72 1 /* $NetBSD: zic.c,v 1.72 2018/10/27 22:29:24 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
7 #if HAVE_NBTOOL_CONFIG_H
8 #include "nbtool_config.h"
9 #endif
10
11 #include <sys/cdefs.h>
12 #ifndef lint
13 __RCSID("$NetBSD: zic.c,v 1.72 2018/10/27 22:29:24 christos Exp $");
14 #endif /* !defined lint */
15
16 #include "private.h"
17 #include "tzfile.h"
18
19 #include <fcntl.h>
20 #include <locale.h>
21 #include <stdarg.h>
22 #include <stddef.h>
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <util.h>
26
27 #define ZIC_VERSION_PRE_2013 '2'
28 #define ZIC_VERSION '3'
29
30 typedef int_fast64_t zic_t;
31 #define ZIC_MIN INT_FAST64_MIN
32 #define ZIC_MAX INT_FAST64_MAX
33 #define PRIdZIC PRIdFAST64
34 #define SCNdZIC SCNdFAST64
35
36 #ifndef ZIC_MAX_ABBR_LEN_WO_WARN
37 #define ZIC_MAX_ABBR_LEN_WO_WARN 6
38 #endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
39
40 #ifdef HAVE_DIRECT_H
41 # include <direct.h>
42 # include <io.h>
43 # undef mkdir
44 # define mkdir(name, mode) _mkdir(name)
45 #endif
46
47 #if HAVE_SYS_STAT_H
48 #include <sys/stat.h>
49 #endif
50 #ifdef S_IRUSR
51 #define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
52 #else
53 #define MKDIR_UMASK 0755
54 #endif
55 /* Port to native MS-Windows and to ancient UNIX. */
56 #if !defined S_ISDIR && defined S_IFDIR && defined S_IFMT
57 # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
58 #endif
59
60 #if HAVE_SYS_WAIT_H
61 #include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */
62 #endif /* HAVE_SYS_WAIT_H */
63
64 #ifndef WIFEXITED
65 #define WIFEXITED(status) (((status) & 0xff) == 0)
66 #endif /* !defined WIFEXITED */
67 #ifndef WEXITSTATUS
68 #define WEXITSTATUS(status) (((status) >> 8) & 0xff)
69 #endif /* !defined WEXITSTATUS */
70
71 /* The maximum ptrdiff_t value, for pre-C99 platforms. */
72 #ifndef PTRDIFF_MAX
73 static ptrdiff_t const PTRDIFF_MAX = MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t));
74 #endif
75
76 /* The minimum alignment of a type, for pre-C11 platforms. */
77 #if __STDC_VERSION__ < 201112
78 # define _Alignof(type) offsetof(struct { char a; type b; }, b)
79 #endif
80
81 /* The type for line numbers. Use PRIdMAX to format them; formerly
82 there was also "#define PRIdLINENO PRIdMAX" and formats used
83 PRIdLINENO, but xgettext cannot grok that. */
84 typedef intmax_t lineno;
85
86 struct rule {
87 const char * r_filename;
88 lineno r_linenum;
89 const char * r_name;
90
91 zic_t r_loyear; /* for example, 1986 */
92 zic_t r_hiyear; /* for example, 1986 */
93 const char * r_yrtype;
94 bool r_lowasnum;
95 bool r_hiwasnum;
96
97 int r_month; /* 0..11 */
98
99 int r_dycode; /* see below */
100 int r_dayofmonth;
101 int r_wday;
102
103 zic_t r_tod; /* time from midnight */
104 bool r_todisstd; /* above is standard time if 1 */
105 /* or wall clock time if 0 */
106 bool r_todisgmt; /* above is GMT if 1 */
107 /* or local time if 0 */
108 bool r_isdst; /* is this daylight saving time? */
109 zic_t r_stdoff; /* offset from default time (which is
110 usually standard time) */
111 const char * r_abbrvar; /* variable part of abbreviation */
112
113 bool r_todo; /* a rule to do (used in outzone) */
114 zic_t r_temp; /* used in outzone */
115 };
116
117 /*
118 ** r_dycode r_dayofmonth r_wday
119 */
120
121 #define DC_DOM 0 /* 1..31 */ /* unused */
122 #define DC_DOWGEQ 1 /* 1..31 */ /* 0..6 (Sun..Sat) */
123 #define DC_DOWLEQ 2 /* 1..31 */ /* 0..6 (Sun..Sat) */
124
125 struct zone {
126 const char * z_filename;
127 lineno z_linenum;
128
129 const char * z_name;
130 zic_t z_gmtoff;
131 char * z_rule;
132 const char * z_format;
133 char z_format_specifier;
134
135 bool z_isdst;
136 zic_t z_stdoff;
137
138 struct rule * z_rules;
139 ptrdiff_t z_nrules;
140
141 struct rule z_untilrule;
142 zic_t z_untiltime;
143 };
144
145 #if !HAVE_POSIX_DECLS
146 extern int getopt(int argc, char * const argv[],
147 const char * options);
148 extern int link(const char * fromname, const char * toname);
149 extern char * optarg;
150 extern int optind;
151 #endif
152
153 #if ! HAVE_LINK
154 # define link(from, to) (errno = ENOTSUP, -1)
155 #endif
156 #if ! HAVE_SYMLINK
157 # define readlink(file, buf, size) (errno = ENOTSUP, -1)
158 # define symlink(from, to) (errno = ENOTSUP, -1)
159 # define S_ISLNK(m) 0
160 #endif
161 #ifndef AT_SYMLINK_FOLLOW
162 # define linkat(fromdir, from, todir, to, flag) \
163 (itssymlink(from) ? (errno = ENOTSUP, -1) : link(from, to))
164 #endif
165
166 static void addtt(zic_t starttime, int type);
167 static int addtype(zic_t, char const *, bool, bool, bool);
168 static void leapadd(zic_t, bool, int, int);
169 static void adjleap(void);
170 static void associate(void);
171 static void dolink(const char *, const char *, bool);
172 static char ** getfields(char * buf);
173 static zic_t gethms(const char * string, const char * errstring,
174 bool);
175 static zic_t getstdoff(char *, bool *);
176 static void infile(const char * filename);
177 static void inleap(char ** fields, int nfields);
178 static void inlink(char ** fields, int nfields);
179 static void inrule(char ** fields, int nfields);
180 static bool inzcont(char ** fields, int nfields);
181 static bool inzone(char ** fields, int nfields);
182 static bool inzsub(char **, int, int);
183 static bool itsdir(const char *);
184 static bool itssymlink(const char *);
185 static bool is_alpha(char a);
186 static char lowerit(char);
187 static void mkdirs(char const *, bool);
188 static void newabbr(const char * abbr);
189 static zic_t oadd(zic_t t1, zic_t t2);
190 static void outzone(const struct zone * zp, ptrdiff_t ntzones);
191 static zic_t rpytime(const struct rule * rp, zic_t wantedy);
192 static void rulesub(struct rule * rp,
193 const char * loyearp, const char * hiyearp,
194 const char * typep, const char * monthp,
195 const char * dayp, const char * timep);
196 static zic_t tadd(zic_t t1, zic_t t2);
197 static bool yearistype(zic_t year, const char * type);
198
199 /* Bound on length of what %z can expand to. */
200 enum { PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1 };
201
202 /* If true, work around a bug in Qt 5.6.1 and earlier, which mishandles
203 tz binary files whose POSIX-TZ-style strings contain '<'; see
204 QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>. This
205 workaround will no longer be needed when Qt 5.6.1 and earlier are
206 obsolete, say in the year 2021. */
207 #ifndef WORK_AROUND_QTBUG_53071
208 enum { WORK_AROUND_QTBUG_53071 = 1 };
209 #endif
210
211 static int charcnt;
212 static bool errors;
213 static bool warnings;
214 static const char * filename;
215 static int leapcnt;
216 static bool leapseen;
217 static zic_t leapminyear;
218 static zic_t leapmaxyear;
219 static lineno linenum;
220 static size_t max_abbrvar_len = PERCENT_Z_LEN_BOUND;
221 static size_t max_format_len;
222 static zic_t max_year;
223 static zic_t min_year;
224 static bool noise;
225 static const char * rfilename;
226 static lineno rlinenum;
227 static const char * progname;
228 static ptrdiff_t timecnt;
229 static ptrdiff_t timecnt_alloc;
230 static int typecnt;
231
232 /*
233 ** Line codes.
234 */
235
236 #define LC_RULE 0
237 #define LC_ZONE 1
238 #define LC_LINK 2
239 #define LC_LEAP 3
240
241 /*
242 ** Which fields are which on a Zone line.
243 */
244
245 #define ZF_NAME 1
246 #define ZF_GMTOFF 2
247 #define ZF_RULE 3
248 #define ZF_FORMAT 4
249 #define ZF_TILYEAR 5
250 #define ZF_TILMONTH 6
251 #define ZF_TILDAY 7
252 #define ZF_TILTIME 8
253 #define ZONE_MINFIELDS 5
254 #define ZONE_MAXFIELDS 9
255
256 /*
257 ** Which fields are which on a Zone continuation line.
258 */
259
260 #define ZFC_GMTOFF 0
261 #define ZFC_RULE 1
262 #define ZFC_FORMAT 2
263 #define ZFC_TILYEAR 3
264 #define ZFC_TILMONTH 4
265 #define ZFC_TILDAY 5
266 #define ZFC_TILTIME 6
267 #define ZONEC_MINFIELDS 3
268 #define ZONEC_MAXFIELDS 7
269
270 /*
271 ** Which files are which on a Rule line.
272 */
273
274 #define RF_NAME 1
275 #define RF_LOYEAR 2
276 #define RF_HIYEAR 3
277 #define RF_COMMAND 4
278 #define RF_MONTH 5
279 #define RF_DAY 6
280 #define RF_TOD 7
281 #define RF_STDOFF 8
282 #define RF_ABBRVAR 9
283 #define RULE_FIELDS 10
284
285 /*
286 ** Which fields are which on a Link line.
287 */
288
289 #define LF_FROM 1
290 #define LF_TO 2
291 #define LINK_FIELDS 3
292
293 /*
294 ** Which fields are which on a Leap line.
295 */
296
297 #define LP_YEAR 1
298 #define LP_MONTH 2
299 #define LP_DAY 3
300 #define LP_TIME 4
301 #define LP_CORR 5
302 #define LP_ROLL 6
303 #define LEAP_FIELDS 7
304
305 /*
306 ** Year synonyms.
307 */
308
309 #define YR_MINIMUM 0
310 #define YR_MAXIMUM 1
311 #define YR_ONLY 2
312
313 static struct rule * rules;
314 static ptrdiff_t nrules; /* number of rules */
315 static ptrdiff_t nrules_alloc;
316
317 static struct zone * zones;
318 static ptrdiff_t nzones; /* number of zones */
319 static ptrdiff_t nzones_alloc;
320
321 struct link {
322 const char * l_filename;
323 lineno l_linenum;
324 const char * l_from;
325 const char * l_to;
326 };
327
328 static struct link * links;
329 static ptrdiff_t nlinks;
330 static ptrdiff_t nlinks_alloc;
331
332 struct lookup {
333 const char * l_word;
334 const int l_value;
335 };
336
337 static struct lookup const * byword(const char * string,
338 const struct lookup * lp);
339
340 static struct lookup const zi_line_codes[] = {
341 { "Rule", LC_RULE },
342 { "Zone", LC_ZONE },
343 { "Link", LC_LINK },
344 { NULL, 0 }
345 };
346 static struct lookup const leap_line_codes[] = {
347 { "Leap", LC_LEAP },
348 { NULL, 0}
349 };
350
351 static struct lookup const mon_names[] = {
352 { "January", TM_JANUARY },
353 { "February", TM_FEBRUARY },
354 { "March", TM_MARCH },
355 { "April", TM_APRIL },
356 { "May", TM_MAY },
357 { "June", TM_JUNE },
358 { "July", TM_JULY },
359 { "August", TM_AUGUST },
360 { "September", TM_SEPTEMBER },
361 { "October", TM_OCTOBER },
362 { "November", TM_NOVEMBER },
363 { "December", TM_DECEMBER },
364 { NULL, 0 }
365 };
366
367 static struct lookup const wday_names[] = {
368 { "Sunday", TM_SUNDAY },
369 { "Monday", TM_MONDAY },
370 { "Tuesday", TM_TUESDAY },
371 { "Wednesday", TM_WEDNESDAY },
372 { "Thursday", TM_THURSDAY },
373 { "Friday", TM_FRIDAY },
374 { "Saturday", TM_SATURDAY },
375 { NULL, 0 }
376 };
377
378 static struct lookup const lasts[] = {
379 { "last-Sunday", TM_SUNDAY },
380 { "last-Monday", TM_MONDAY },
381 { "last-Tuesday", TM_TUESDAY },
382 { "last-Wednesday", TM_WEDNESDAY },
383 { "last-Thursday", TM_THURSDAY },
384 { "last-Friday", TM_FRIDAY },
385 { "last-Saturday", TM_SATURDAY },
386 { NULL, 0 }
387 };
388
389 static struct lookup const begin_years[] = {
390 { "minimum", YR_MINIMUM },
391 { "maximum", YR_MAXIMUM },
392 { NULL, 0 }
393 };
394
395 static struct lookup const end_years[] = {
396 { "minimum", YR_MINIMUM },
397 { "maximum", YR_MAXIMUM },
398 { "only", YR_ONLY },
399 { NULL, 0 }
400 };
401
402 static struct lookup const leap_types[] = {
403 { "Rolling", true },
404 { "Stationary", false },
405 { NULL, 0 }
406 };
407
408 static const int len_months[2][MONSPERYEAR] = {
409 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
410 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
411 };
412
413 static const int len_years[2] = {
414 DAYSPERNYEAR, DAYSPERLYEAR
415 };
416
417 static struct attype {
418 zic_t at;
419 bool dontmerge;
420 unsigned char type;
421 } * attypes;
422 static zic_t gmtoffs[TZ_MAX_TYPES];
423 static char isdsts[TZ_MAX_TYPES];
424 static unsigned char abbrinds[TZ_MAX_TYPES];
425 static bool ttisstds[TZ_MAX_TYPES];
426 static bool ttisgmts[TZ_MAX_TYPES];
427 static char chars[TZ_MAX_CHARS];
428 static zic_t trans[TZ_MAX_LEAPS];
429 static zic_t corr[TZ_MAX_LEAPS];
430 static char roll[TZ_MAX_LEAPS];
431
432 /*
433 ** Memory allocation.
434 */
435
436 static _Noreturn void
437 memory_exhausted(const char *msg)
438 {
439 fprintf(stderr, _("%s: Memory exhausted: %s\n"), progname, msg);
440 exit(EXIT_FAILURE);
441 }
442
443 static ATTRIBUTE_PURE size_t
444 size_product(size_t nitems, size_t itemsize)
445 {
446 if (SIZE_MAX / itemsize < nitems)
447 memory_exhausted(_("size overflow"));
448 return nitems * itemsize;
449 }
450
451 static ATTRIBUTE_PURE size_t
452 align_to(size_t size, size_t alignment)
453 {
454 size_t aligned_size = size + alignment - 1;
455 aligned_size -= aligned_size % alignment;
456 if (aligned_size < size)
457 memory_exhausted(_("alignment overflow"));
458 return aligned_size;
459 }
460
461 #if !HAVE_STRDUP
462 static char *
463 strdup(char const *str)
464 {
465 char *result = malloc(strlen(str) + 1);
466 return result ? strcpy(result, str) : result;
467 }
468 #endif
469
470 static void *
471 memcheck(void *ptr)
472 {
473 if (ptr == NULL)
474 memory_exhausted(strerror(errno));
475 return ptr;
476 }
477
478 static void * ATTRIBUTE_MALLOC
479 zic_malloc(size_t size)
480 {
481 return memcheck(malloc(size));
482 }
483
484 static void *
485 zic_realloc(void *ptr, size_t size)
486 {
487 return memcheck(realloc(ptr, size));
488 }
489
490 static char * ATTRIBUTE_MALLOC
491 ecpyalloc(char const *str)
492 {
493 return memcheck(strdup(str));
494 }
495
496 static void *
497 growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
498 {
499 if (nitems < *nitems_alloc)
500 return ptr;
501 else {
502 ptrdiff_t nitems_max = PTRDIFF_MAX - WORK_AROUND_QTBUG_53071;
503 ptrdiff_t amax = (ptrdiff_t)((size_t)nitems_max < SIZE_MAX ?
504 (size_t)nitems_max : SIZE_MAX);
505 if ((amax - 1) / 3 * 2 < *nitems_alloc)
506 memory_exhausted(_("integer overflow"));
507 *nitems_alloc += (*nitems_alloc >> 1) + 1;
508 return zic_realloc(ptr, size_product(*nitems_alloc, itemsize));
509 }
510 }
511
512 /*
513 ** Error handling.
514 */
515
516 static void
517 eats(char const *name, lineno num, char const *rname, lineno rnum)
518 {
519 filename = name;
520 linenum = num;
521 rfilename = rname;
522 rlinenum = rnum;
523 }
524
525 static void
526 eat(char const *name, lineno num)
527 {
528 eats(name, num, NULL, -1);
529 }
530
531 static void ATTRIBUTE_FORMAT((printf, 1, 0))
532 verror(const char *const string, va_list args)
533 {
534 /*
535 ** Match the format of "cc" to allow sh users to
536 ** zic ... 2>&1 | error -t "*" -v
537 ** on BSD systems.
538 */
539 if (filename)
540 fprintf(stderr, _("\"%s\", line %"PRIdMAX": "), filename, linenum);
541 vfprintf(stderr, string, args);
542 if (rfilename != NULL)
543 fprintf(stderr, _(" (rule from \"%s\", line %"PRIdMAX")"),
544 rfilename, rlinenum);
545 fprintf(stderr, "\n");
546 }
547
548 static void ATTRIBUTE_FORMAT((printf, 1, 2))
549 error(const char *const string, ...)
550 {
551 va_list args;
552 va_start(args, string);
553 verror(string, args);
554 va_end(args);
555 errors = true;
556 }
557
558 static void ATTRIBUTE_FORMAT((printf, 1, 2))
559 warning(const char *const string, ...)
560 {
561 va_list args;
562 fprintf(stderr, _("warning: "));
563 va_start(args, string);
564 verror(string, args);
565 va_end(args);
566 warnings = true;
567 }
568
569 static void
570 close_file(FILE *stream, char const *dir, char const *name)
571 {
572 char const *e = (ferror(stream) ? _("I/O error")
573 : fclose(stream) != 0 ? strerror(errno) : NULL);
574 if (e) {
575 fprintf(stderr, "%s: %s%s%s%s%s\n", progname,
576 dir ? dir : "", dir ? "/" : "",
577 name ? name : "", name ? ": " : "",
578 e);
579 exit(EXIT_FAILURE);
580 }
581 }
582
583 static _Noreturn void
584 usage(FILE *stream, int status)
585 {
586 fprintf(stream,
587 _("%s: usage is %s [ --version ] [ --help ] [ -v ] \\\n"
588 "\t[ -l localtime ] [ -p posixrules ] [ -d directory ] \\\n"
589 "\t[ -t localtime-link ] [ -L leapseconds ] [ filename ... ]\n\n"
590 "Report bugs to %s.\n"),
591 progname, progname, REPORT_BUGS_TO);
592 if (status == EXIT_SUCCESS)
593 close_file(stream, NULL, NULL);
594 exit(status);
595 }
596
597 /* Change the working directory to DIR, possibly creating DIR and its
598 ancestors. After this is done, all files are accessed with names
599 relative to DIR. */
600 static void
601 change_directory (char const *dir)
602 {
603 if (chdir(dir) != 0) {
604 int chdir_errno = errno;
605 if (chdir_errno == ENOENT) {
606 mkdirs(dir, false);
607 chdir_errno = chdir(dir) == 0 ? 0 : errno;
608 }
609 if (chdir_errno != 0) {
610 fprintf(stderr, _("%s: Can't chdir to %s: %s\n"),
611 progname, dir, strerror(chdir_errno));
612 exit(EXIT_FAILURE);
613 }
614 }
615 }
616
617 static const char * psxrules;
618 static const char * lcltime;
619 static const char * directory;
620 static const char * leapsec;
621 static const char * tzdefault;
622 static const char * yitcommand;
623
624 int
625 main(int argc, char **argv)
626 {
627 int c, k;
628 ptrdiff_t i, j;
629
630 #ifdef S_IWGRP
631 umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
632 #endif
633 #if HAVE_GETTEXT
634 setlocale(LC_MESSAGES, "");
635 #ifdef TZ_DOMAINDIR
636 bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
637 #endif /* defined TEXTDOMAINDIR */
638 textdomain(TZ_DOMAIN);
639 #endif /* HAVE_GETTEXT */
640 progname = argv[0];
641 if (TYPE_BIT(zic_t) < 64) {
642 fprintf(stderr, "%s: %s\n", progname,
643 _("wild compilation-time specification of zic_t"));
644 return EXIT_FAILURE;
645 }
646 for (k = 1; k < argc; k++)
647 if (strcmp(argv[k], "--version") == 0) {
648 printf("zic %s%s\n", PKGVERSION, TZVERSION);
649 close_file(stdout, NULL, NULL);
650 return EXIT_SUCCESS;
651 } else if (strcmp(argv[k], "--help") == 0) {
652 usage(stdout, EXIT_SUCCESS);
653 }
654 while ((c = getopt(argc, argv, "d:l:L:p:st:vy:")) != EOF && c != -1)
655 switch (c) {
656 default:
657 usage(stderr, EXIT_FAILURE);
658 case 'd':
659 if (directory == NULL)
660 directory = optarg;
661 else {
662 fprintf(stderr,
663 _("%s: More than one -d option specified\n"),
664 progname);
665 return EXIT_FAILURE;
666 }
667 break;
668 case 'l':
669 if (lcltime == NULL)
670 lcltime = optarg;
671 else {
672 fprintf(stderr,
673 _("%s: More than one -l option specified\n"),
674 progname);
675 return EXIT_FAILURE;
676 }
677 break;
678 case 'p':
679 if (psxrules == NULL)
680 psxrules = optarg;
681 else {
682 fprintf(stderr,
683 _("%s: More than one -p option specified\n"),
684 progname);
685 return EXIT_FAILURE;
686 }
687 break;
688 case 't':
689 if (tzdefault != NULL) {
690 fprintf(stderr,
691 _("%s: More than one -t option"
692 " specified\n"),
693 progname);
694 return EXIT_FAILURE;
695 }
696 tzdefault = optarg;
697 break;
698 case 'y':
699 if (yitcommand == NULL) {
700 warning(_("-y is obsolescent"));
701 yitcommand = optarg;
702 } else {
703 fprintf(stderr,
704 _("%s: More than one -y option specified\n"),
705 progname);
706 return EXIT_FAILURE;
707 }
708 break;
709 case 'L':
710 if (leapsec == NULL)
711 leapsec = optarg;
712 else {
713 fprintf(stderr,
714 _("%s: More than one -L option specified\n"),
715 progname);
716 return EXIT_FAILURE;
717 }
718 break;
719 case 'v':
720 noise = true;
721 break;
722 case 's':
723 warning(_("-s ignored"));
724 break;
725 }
726 if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
727 usage(stderr, EXIT_FAILURE); /* usage message by request */
728 if (directory == NULL)
729 directory = TZDIR;
730 if (tzdefault == NULL)
731 tzdefault = TZDEFAULT;
732 if (yitcommand == NULL)
733 yitcommand = "yearistype";
734
735 if (optind < argc && leapsec != NULL) {
736 infile(leapsec);
737 adjleap();
738 }
739
740 for (k = optind; k < argc; k++)
741 infile(argv[k]);
742 if (errors)
743 return EXIT_FAILURE;
744 associate();
745 change_directory(directory);
746 for (i = 0; i < nzones; i = j) {
747 /*
748 ** Find the next non-continuation zone entry.
749 */
750 for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
751 continue;
752 outzone(&zones[i], j - i);
753 }
754 /*
755 ** Make links.
756 */
757 for (i = 0; i < nlinks; ++i) {
758 eat(links[i].l_filename, links[i].l_linenum);
759 dolink(links[i].l_from, links[i].l_to, false);
760 if (noise)
761 for (j = 0; j < nlinks; ++j)
762 if (strcmp(links[i].l_to,
763 links[j].l_from) == 0)
764 warning(_("link to link"));
765 }
766 if (lcltime != NULL) {
767 eat(_("command line"), 1);
768 dolink(lcltime, tzdefault, true);
769 }
770 if (psxrules != NULL) {
771 eat(_("command line"), 1);
772 dolink(psxrules, TZDEFRULES, true);
773 }
774 if (warnings && (ferror(stderr) || fclose(stderr) != 0))
775 return EXIT_FAILURE;
776 return errors ? EXIT_FAILURE : EXIT_SUCCESS;
777 }
778
779 static bool
780 componentcheck(char const *name, char const *component,
781 char const *component_end)
782 {
783 enum { component_len_max = 14 };
784 ptrdiff_t component_len = component_end - component;
785 if (component_len == 0) {
786 if (!*name)
787 error (_("empty file name"));
788 else
789 error (_(component == name
790 ? "file name '%s' begins with '/'"
791 : *component_end
792 ? "file name '%s' contains '//'"
793 : "file name '%s' ends with '/'"),
794 name);
795 return false;
796 }
797 if (0 < component_len && component_len <= 2
798 && component[0] == '.' && component_end[-1] == '.') {
799 int len = component_len;
800 error(_("file name '%s' contains '%.*s' component"),
801 name, len, component);
802 return false;
803 }
804 if (noise) {
805 if (0 < component_len && component[0] == '-')
806 warning(_("file name '%s' component contains leading '-'"),
807 name);
808 if (component_len_max < component_len)
809 warning(_("file name '%s' contains overlength component"
810 " '%.*s...'"),
811 name, component_len_max, component);
812 }
813 return true;
814 }
815
816 static bool
817 namecheck(const char *name)
818 {
819 char const *cp;
820
821 /* Benign characters in a portable file name. */
822 static char const benign[] =
823 "-/_"
824 "abcdefghijklmnopqrstuvwxyz"
825 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
826
827 /* Non-control chars in the POSIX portable character set,
828 excluding the benign characters. */
829 static char const printable_and_not_benign[] =
830 " !\"#$%&'()*+,.0123456789:;<=>?@[\\]^`{|}~";
831
832 char const *component = name;
833 for (cp = name; *cp; cp++) {
834 unsigned char c = *cp;
835 if (noise && !strchr(benign, c)) {
836 warning((strchr(printable_and_not_benign, c)
837 ? _("file name '%s' contains byte '%c'")
838 : _("file name '%s' contains byte '\\%o'")),
839 name, c);
840 }
841 if (c == '/') {
842 if (!componentcheck(name, component, cp))
843 return false;
844 component = cp + 1;
845 }
846 }
847 return componentcheck(name, component, cp);
848 }
849
850 /* Create symlink contents suitable for symlinking FROM to TO, as a
851 freshly allocated string. FROM should be a relative file name, and
852 is relative to the global variable DIRECTORY. TO can be either
853 relative or absolute. */
854 static char *
855 relname(char const *from, char const *to)
856 {
857 size_t i, taillen, dotdotetcsize;
858 size_t dir_len = 0, dotdots = 0, linksize = SIZE_MAX;
859 char const *f = from;
860 char *result = NULL;
861 if (*to == '/') {
862 /* Make F absolute too. */
863 size_t len = strlen(directory);
864 bool needslash = len && directory[len - 1] != '/';
865 linksize = len + needslash + strlen(from) + 1;
866 f = result = emalloc(linksize);
867 strcpy(result, directory);
868 result[len] = '/';
869 strcpy(result + len + needslash, from);
870 }
871 for (i = 0; f[i] && f[i] == to[i]; i++)
872 if (f[i] == '/')
873 dir_len = i + 1;
874 for (; to[i]; i++)
875 dotdots += to[i] == '/' && to[i - 1] != '/';
876 taillen = strlen(f + dir_len);
877 dotdotetcsize = 3 * dotdots + taillen + 1;
878 if (dotdotetcsize <= linksize) {
879 if (!result)
880 result = emalloc(dotdotetcsize);
881 for (i = 0; i < dotdots; i++)
882 memcpy(result + 3 * i, "../", 3);
883 memmove(result + 3 * dotdots, f + dir_len, taillen + 1);
884 }
885 return result;
886 }
887
888 /* Hard link FROM to TO, following any symbolic links.
889 Return 0 if successful, an error number otherwise. */
890 static int
891 hardlinkerr(char const *from, char const *to)
892 {
893 int r = linkat(AT_FDCWD, from, AT_FDCWD, to, AT_SYMLINK_FOLLOW);
894 return r == 0 ? 0 : errno;
895 }
896
897 static void
898 dolink(char const *fromfield, char const *tofield, bool staysymlink)
899 {
900 bool todirs_made = false;
901 int link_errno;
902
903 /*
904 ** We get to be careful here since
905 ** there's a fair chance of root running us.
906 */
907 if (itsdir(fromfield)) {
908 fprintf(stderr, _("%s: link from %s/%s failed: %s\n"),
909 progname, directory, fromfield, strerror(EPERM));
910 exit(EXIT_FAILURE);
911 }
912 if (staysymlink)
913 staysymlink = itssymlink(tofield);
914 if (remove(tofield) == 0)
915 todirs_made = true;
916 else if (errno != ENOENT) {
917 char const *e = strerror(errno);
918 fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"),
919 progname, directory, tofield, e);
920 exit(EXIT_FAILURE);
921 }
922 link_errno = staysymlink ? ENOTSUP : hardlinkerr(fromfield, tofield);
923 if (link_errno == ENOENT && !todirs_made) {
924 mkdirs(tofield, true);
925 todirs_made = true;
926 link_errno = hardlinkerr(fromfield, tofield);
927 }
928 if (link_errno != 0) {
929 bool absolute = *fromfield == '/';
930 char *linkalloc = absolute ? NULL : relname(fromfield, tofield);
931 char const *contents = absolute ? fromfield : linkalloc;
932 int symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno;
933 if (!todirs_made
934 && (symlink_errno == ENOENT || symlink_errno == ENOTSUP)) {
935 mkdirs(tofield, true);
936 if (symlink_errno == ENOENT)
937 symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno;
938 }
939 free(linkalloc);
940 if (symlink_errno == 0) {
941 if (link_errno != ENOTSUP)
942 warning(_("symbolic link used because hard link failed: %s"),
943 strerror(link_errno));
944 } else {
945 FILE *fp, *tp;
946 int c;
947 fp = fopen(fromfield, "rb");
948 if (!fp) {
949 char const *e = strerror(errno);
950 fprintf(stderr, _("%s: Can't read %s/%s: %s\n"),
951 progname, directory, fromfield, e);
952 exit(EXIT_FAILURE);
953 }
954 tp = fopen(tofield, "wb");
955 if (!tp) {
956 char const *e = strerror(errno);
957 fprintf(stderr, _("%s: Can't create %s/%s: %s\n"),
958 progname, directory, tofield, e);
959 exit(EXIT_FAILURE);
960 }
961 while ((c = getc(fp)) != EOF)
962 putc(c, tp);
963 close_file(fp, directory, fromfield);
964 close_file(tp, directory, tofield);
965 if (link_errno != ENOTSUP)
966 warning(_("copy used because hard link failed: %s"),
967 strerror(link_errno));
968 else if (symlink_errno != ENOTSUP)
969 warning(_("copy used because symbolic link failed: %s"),
970 strerror(symlink_errno));
971 }
972 }
973 }
974
975 #define TIME_T_BITS_IN_FILE 64
976
977 static zic_t const min_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
978 static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
979
980 /* Estimated time of the Big Bang, in seconds since the POSIX epoch.
981 rounded downward to the negation of a power of two that is
982 comfortably outside the error bounds.
983
984 For the time of the Big Bang, see:
985
986 Ade PAR, Aghanim N, Armitage-Caplan C et al. Planck 2013 results.
987 I. Overview of products and scientific results.
988 arXiv:1303.5062 2013-03-20 20:10:01 UTC
989 <https://arxiv.org/pdf/1303.5062v1> [PDF]
990
991 Page 36, Table 9, row Age/Gyr, column Planck+WP+highL+BAO 68% limits
992 gives the value 13.798 plus-or-minus 0.037 billion years.
993 Multiplying this by 1000000000 and then by 31557600 (the number of
994 seconds in an astronomical year) gives a value that is comfortably
995 less than 2**59, so BIG_BANG is - 2**59.
996
997 BIG_BANG is approximate, and may change in future versions.
998 Please do not rely on its exact value. */
999
1000 #ifndef BIG_BANG
1001 #define BIG_BANG (- (1LL << 59))
1002 #endif
1003
1004 /* If true, work around GNOME bug 730332
1005 <https://bugzilla.gnome.org/show_bug.cgi?id=730332>
1006 by refusing to output time stamps before BIG_BANG.
1007 Such time stamps are physically suspect anyway.
1008
1009 The GNOME bug is scheduled to be fixed in GNOME 3.22, and if so
1010 this workaround will no longer be needed when GNOME 3.21 and
1011 earlier are obsolete, say in the year 2021. */
1012 enum { WORK_AROUND_GNOME_BUG_730332 = true };
1013
1014 static const zic_t early_time = (WORK_AROUND_GNOME_BUG_730332
1015 ? BIG_BANG
1016 : MINVAL(zic_t, TIME_T_BITS_IN_FILE));
1017
1018 /* Return true if NAME is a directory. */
1019 static bool
1020 itsdir(const char *name)
1021 {
1022 struct stat st;
1023 int res = stat(name, &st);
1024 #ifdef S_ISDIR
1025 if (res == 0)
1026 return S_ISDIR(st.st_mode) != 0;
1027 #endif
1028 if (res == 0 || errno == EOVERFLOW) {
1029 size_t n = strlen(name);
1030 char *nameslashdot = emalloc(n + 3);
1031 bool dir;
1032 memcpy(nameslashdot, name, n);
1033 strcpy(&nameslashdot[n], &"/."[! (n && name[n - 1] != '/')]);
1034 dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW;
1035 free(nameslashdot);
1036 return dir;
1037 }
1038 return false;
1039 }
1040
1041 /* Return true if NAME is a symbolic link. */
1042 static bool
1043 itssymlink(char const *name)
1044 {
1045 char c;
1046 return 0 <= readlink(name, &c, 1);
1047 }
1048
1049 /*
1050 ** Associate sets of rules with zones.
1051 */
1052
1053 /*
1054 ** Sort by rule name.
1055 */
1056
1057 static int
1058 rcomp(const void *cp1, const void *cp2)
1059 {
1060 return strcmp(((const struct rule *) cp1)->r_name,
1061 ((const struct rule *) cp2)->r_name);
1062 }
1063
1064 static void
1065 associate(void)
1066 {
1067 struct zone * zp;
1068 struct rule * rp;
1069 ptrdiff_t base, out;
1070 int i, j;
1071
1072 if (nrules != 0) {
1073 qsort(rules, (size_t)nrules, sizeof *rules, rcomp);
1074 for (i = 0; i < nrules - 1; ++i) {
1075 if (strcmp(rules[i].r_name,
1076 rules[i + 1].r_name) != 0)
1077 continue;
1078 if (strcmp(rules[i].r_filename,
1079 rules[i + 1].r_filename) == 0)
1080 continue;
1081 eat(rules[i].r_filename, rules[i].r_linenum);
1082 warning(_("same rule name in multiple files"));
1083 eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);
1084 warning(_("same rule name in multiple files"));
1085 for (j = i + 2; j < nrules; ++j) {
1086 if (strcmp(rules[i].r_name,
1087 rules[j].r_name) != 0)
1088 break;
1089 if (strcmp(rules[i].r_filename,
1090 rules[j].r_filename) == 0)
1091 continue;
1092 if (strcmp(rules[i + 1].r_filename,
1093 rules[j].r_filename) == 0)
1094 continue;
1095 break;
1096 }
1097 i = j - 1;
1098 }
1099 }
1100 for (i = 0; i < nzones; ++i) {
1101 zp = &zones[i];
1102 zp->z_rules = NULL;
1103 zp->z_nrules = 0;
1104 }
1105 for (base = 0; base < nrules; base = out) {
1106 rp = &rules[base];
1107 for (out = base + 1; out < nrules; ++out)
1108 if (strcmp(rp->r_name, rules[out].r_name) != 0)
1109 break;
1110 for (i = 0; i < nzones; ++i) {
1111 zp = &zones[i];
1112 if (strcmp(zp->z_rule, rp->r_name) != 0)
1113 continue;
1114 zp->z_rules = rp;
1115 zp->z_nrules = out - base;
1116 }
1117 }
1118 for (i = 0; i < nzones; ++i) {
1119 zp = &zones[i];
1120 if (zp->z_nrules == 0) {
1121 /*
1122 ** Maybe we have a local standard time offset.
1123 */
1124 eat(zp->z_filename, zp->z_linenum);
1125 zp->z_stdoff = getstdoff(zp->z_rule, &zp->z_isdst);
1126 /*
1127 ** Note, though, that if there's no rule,
1128 ** a '%s' in the format is a bad thing.
1129 */
1130 if (zp->z_format_specifier == 's')
1131 error("%s", _("%s in ruleless zone"));
1132 }
1133 }
1134 if (errors)
1135 exit(EXIT_FAILURE);
1136 }
1137
1138 static void
1139 infile(const char *name)
1140 {
1141 FILE * fp;
1142 char ** fields;
1143 char * cp;
1144 const struct lookup * lp;
1145 int nfields;
1146 bool wantcont;
1147 lineno num;
1148 char buf[BUFSIZ];
1149
1150 if (strcmp(name, "-") == 0) {
1151 name = _("standard input");
1152 fp = stdin;
1153 } else if ((fp = fopen(name, "r")) == NULL) {
1154 const char *e = strerror(errno);
1155
1156 fprintf(stderr, _("%s: Can't open %s: %s\n"),
1157 progname, name, e);
1158 exit(EXIT_FAILURE);
1159 }
1160 wantcont = false;
1161 for (num = 1; ; ++num) {
1162 eat(name, num);
1163 if (fgets(buf, (int) sizeof buf, fp) != buf)
1164 break;
1165 cp = strchr(buf, '\n');
1166 if (cp == NULL) {
1167 error(_("line too long"));
1168 exit(EXIT_FAILURE);
1169 }
1170 *cp = '\0';
1171 fields = getfields(buf);
1172 nfields = 0;
1173 while (fields[nfields] != NULL) {
1174 static char nada;
1175
1176 if (strcmp(fields[nfields], "-") == 0)
1177 fields[nfields] = &nada;
1178 ++nfields;
1179 }
1180 if (nfields == 0) {
1181 /* nothing to do */
1182 } else if (wantcont) {
1183 wantcont = inzcont(fields, nfields);
1184 } else {
1185 struct lookup const *line_codes
1186 = name == leapsec ? leap_line_codes : zi_line_codes;
1187 lp = byword(fields[0], line_codes);
1188 if (lp == NULL)
1189 error(_("input line of unknown type"));
1190 else switch (lp->l_value) {
1191 case LC_RULE:
1192 inrule(fields, nfields);
1193 wantcont = false;
1194 break;
1195 case LC_ZONE:
1196 wantcont = inzone(fields, nfields);
1197 break;
1198 case LC_LINK:
1199 inlink(fields, nfields);
1200 wantcont = false;
1201 break;
1202 case LC_LEAP:
1203 inleap(fields, nfields);
1204 wantcont = false;
1205 break;
1206 default: /* "cannot happen" */
1207 fprintf(stderr,
1208 _("%s: panic: Invalid l_value %d\n"),
1209 progname, lp->l_value);
1210 exit(EXIT_FAILURE);
1211 }
1212 }
1213 free(fields);
1214 }
1215 close_file(fp, NULL, filename);
1216 if (wantcont)
1217 error(_("expected continuation line not found"));
1218 }
1219
1220 /*
1221 ** Convert a string of one of the forms
1222 ** h -h hh:mm -hh:mm hh:mm:ss -hh:mm:ss
1223 ** into a number of seconds.
1224 ** A null string maps to zero.
1225 ** Call error with errstring and return zero on errors.
1226 */
1227
1228 static zic_t
1229 gethms(char const *string, char const *errstring, bool signable)
1230 {
1231 zic_t hh;
1232 int sign, mm = 0, ss = 0;
1233 char hhx, mmx, ssx, xr = '0', xs;
1234 int tenths = 0;
1235 bool ok = true;
1236
1237 if (string == NULL || *string == '\0')
1238 return 0;
1239 if (!signable)
1240 sign = 1;
1241 else if (*string == '-') {
1242 sign = -1;
1243 ++string;
1244 } else sign = 1;
1245 switch (sscanf(string,
1246 "%"SCNdZIC"%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
1247 &hh, &hhx, &mm, &mmx, &ss, &ssx, &tenths, &xr, &xs)) {
1248 default: ok = false; break;
1249 case 8:
1250 ok = '0' <= xr && xr <= '9';
1251 /* fallthrough */
1252 case 7:
1253 ok &= ssx == '.';
1254 if (ok && noise)
1255 warning(_("fractional seconds rejected by"
1256 " pre-2018 versions of zic"));
1257 /* fallthrough */
1258 case 5: ok &= mmx == ':'; /* fallthrough */
1259 case 3: ok &= hhx == ':'; /* fallthrough */
1260 case 1: break;
1261 }
1262 if (!ok) {
1263 error("%s", errstring);
1264 return 0;
1265 }
1266 if (hh < 0 ||
1267 mm < 0 || mm >= MINSPERHOUR ||
1268 ss < 0 || ss > SECSPERMIN) {
1269 error("%s", errstring);
1270 return 0;
1271 }
1272 if (ZIC_MAX / SECSPERHOUR < hh) {
1273 error(_("time overflow"));
1274 return 0;
1275 }
1276 ss += 5 + ((ss ^ 1) & (xr == '0')) <= tenths; /* Round to even. */
1277 if (noise && (hh > HOURSPERDAY ||
1278 (hh == HOURSPERDAY && (mm != 0 || ss != 0))))
1279 warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
1280 return oadd(sign * hh * SECSPERHOUR,
1281 sign * (mm * SECSPERMIN + ss));
1282 }
1283
1284 static zic_t
1285 getstdoff(char *field, bool *isdst)
1286 {
1287 int dst = -1;
1288 zic_t stdoff;
1289 size_t fieldlen = strlen(field);
1290 if (fieldlen != 0) {
1291 char *ep = field + fieldlen - 1;
1292 switch (*ep) {
1293 case 'd': dst = 1; *ep = '\0'; break;
1294 case 's': dst = 0; *ep = '\0'; break;
1295 }
1296 }
1297 stdoff = gethms(field, _("invalid saved time"), true);
1298 *isdst = dst < 0 ? stdoff != 0 : dst;
1299 return stdoff;
1300 }
1301
1302 static void
1303 inrule(char **fields, int nfields)
1304 {
1305 static struct rule r;
1306
1307 if (nfields != RULE_FIELDS) {
1308 error(_("wrong number of fields on Rule line"));
1309 return;
1310 }
1311 if (*fields[RF_NAME] == '\0') {
1312 error(_("nameless rule"));
1313 return;
1314 }
1315 r.r_filename = filename;
1316 r.r_linenum = linenum;
1317 r.r_stdoff = getstdoff(fields[RF_STDOFF], &r.r_isdst);
1318 rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
1319 fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
1320 r.r_name = ecpyalloc(fields[RF_NAME]);
1321 r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
1322 if (max_abbrvar_len < strlen(r.r_abbrvar))
1323 max_abbrvar_len = strlen(r.r_abbrvar);
1324 rules = growalloc(rules, sizeof *rules, nrules, &nrules_alloc);
1325 rules[nrules++] = r;
1326 }
1327
1328 static bool
1329 inzone(char **fields, int nfields)
1330 {
1331 ptrdiff_t i;
1332
1333 if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
1334 error(_("wrong number of fields on Zone line"));
1335 return false;
1336 }
1337 if (lcltime != NULL && strcmp(fields[ZF_NAME], tzdefault) == 0) {
1338 error(
1339 _("\"Zone %s\" line and -l option are mutually exclusive"),
1340 tzdefault);
1341 return false;
1342 }
1343 if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
1344 error(
1345 _("\"Zone %s\" line and -p option are mutually exclusive"),
1346 TZDEFRULES);
1347 return false;
1348 }
1349 for (i = 0; i < nzones; ++i)
1350 if (zones[i].z_name != NULL &&
1351 strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
1352 error(_("duplicate zone name %s"
1353 " (file \"%s\", line %"PRIdMAX")"),
1354 fields[ZF_NAME],
1355 zones[i].z_filename,
1356 zones[i].z_linenum);
1357 return false;
1358 }
1359 return inzsub(fields, nfields, false);
1360 }
1361
1362 static bool
1363 inzcont(char **fields, int nfields)
1364 {
1365 if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {
1366 error(_("wrong number of fields on Zone continuation line"));
1367 return false;
1368 }
1369 return inzsub(fields, nfields, true);
1370 }
1371
1372 static bool
1373 inzsub(char **fields, int nfields, const int iscont)
1374 {
1375 char * cp;
1376 char * cp1;
1377 static struct zone z;
1378 int i_gmtoff, i_rule, i_format;
1379 int i_untilyear, i_untilmonth;
1380 int i_untilday, i_untiltime;
1381 bool hasuntil;
1382
1383 if (iscont) {
1384 i_gmtoff = ZFC_GMTOFF;
1385 i_rule = ZFC_RULE;
1386 i_format = ZFC_FORMAT;
1387 i_untilyear = ZFC_TILYEAR;
1388 i_untilmonth = ZFC_TILMONTH;
1389 i_untilday = ZFC_TILDAY;
1390 i_untiltime = ZFC_TILTIME;
1391 z.z_name = NULL;
1392 } else if (!namecheck(fields[ZF_NAME]))
1393 return false;
1394 else {
1395 i_gmtoff = ZF_GMTOFF;
1396 i_rule = ZF_RULE;
1397 i_format = ZF_FORMAT;
1398 i_untilyear = ZF_TILYEAR;
1399 i_untilmonth = ZF_TILMONTH;
1400 i_untilday = ZF_TILDAY;
1401 i_untiltime = ZF_TILTIME;
1402 z.z_name = ecpyalloc(fields[ZF_NAME]);
1403 }
1404 z.z_filename = filename;
1405 z.z_linenum = linenum;
1406 z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UT offset"), true);
1407 if ((cp = strchr(fields[i_format], '%')) != 0) {
1408 if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
1409 || strchr(fields[i_format], '/')) {
1410 error(_("invalid abbreviation format"));
1411 return false;
1412 }
1413 }
1414 z.z_rule = ecpyalloc(fields[i_rule]);
1415 z.z_format = cp1 = ecpyalloc(fields[i_format]);
1416 z.z_format_specifier = cp ? *cp : '\0';
1417 if (z.z_format_specifier == 'z') {
1418 if (noise)
1419 warning(_("format '%s' not handled by pre-2015 versions of zic"),
1420 z.z_format);
1421 cp1[cp - fields[i_format]] = 's';
1422 }
1423 if (max_format_len < strlen(z.z_format))
1424 max_format_len = strlen(z.z_format);
1425 hasuntil = nfields > i_untilyear;
1426 if (hasuntil) {
1427 z.z_untilrule.r_filename = filename;
1428 z.z_untilrule.r_linenum = linenum;
1429 rulesub(&z.z_untilrule,
1430 fields[i_untilyear],
1431 "only",
1432 "",
1433 (nfields > i_untilmonth) ?
1434 fields[i_untilmonth] : "Jan",
1435 (nfields > i_untilday) ? fields[i_untilday] : "1",
1436 (nfields > i_untiltime) ? fields[i_untiltime] : "0");
1437 z.z_untiltime = rpytime(&z.z_untilrule,
1438 z.z_untilrule.r_loyear);
1439 if (iscont && nzones > 0 &&
1440 z.z_untiltime > min_time &&
1441 z.z_untiltime < max_time &&
1442 zones[nzones - 1].z_untiltime > min_time &&
1443 zones[nzones - 1].z_untiltime < max_time &&
1444 zones[nzones - 1].z_untiltime >= z.z_untiltime) {
1445 error(_(
1446 "Zone continuation line end time is not after end time of previous line"
1447 ));
1448 return false;
1449 }
1450 }
1451 zones = growalloc(zones, sizeof *zones, nzones, &nzones_alloc);
1452 zones[nzones++] = z;
1453 /*
1454 ** If there was an UNTIL field on this line,
1455 ** there's more information about the zone on the next line.
1456 */
1457 return hasuntil;
1458 }
1459
1460 static void
1461 inleap(char **fields, int nfields)
1462 {
1463 const char * cp;
1464 const struct lookup * lp;
1465 zic_t i, j;
1466 zic_t year;
1467 int month, day;
1468 zic_t dayoff, tod;
1469 zic_t t;
1470 char xs;
1471
1472 if (nfields != LEAP_FIELDS) {
1473 error(_("wrong number of fields on Leap line"));
1474 return;
1475 }
1476 dayoff = 0;
1477 cp = fields[LP_YEAR];
1478 if (sscanf(cp, "%"SCNdZIC"%c", &year, &xs) != 1) {
1479 /*
1480 ** Leapin' Lizards!
1481 */
1482 error(_("invalid leaping year"));
1483 return;
1484 }
1485 if (!leapseen || leapmaxyear < year)
1486 leapmaxyear = year;
1487 if (!leapseen || leapminyear > year)
1488 leapminyear = year;
1489 leapseen = true;
1490 j = EPOCH_YEAR;
1491 while (j != year) {
1492 if (year > j) {
1493 i = len_years[isleap(j)];
1494 ++j;
1495 } else {
1496 --j;
1497 i = -len_years[isleap(j)];
1498 }
1499 dayoff = oadd(dayoff, i);
1500 }
1501 if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
1502 error(_("invalid month name"));
1503 return;
1504 }
1505 month = lp->l_value;
1506 j = TM_JANUARY;
1507 while (j != month) {
1508 i = len_months[isleap(year)][j];
1509 dayoff = oadd(dayoff, i);
1510 ++j;
1511 }
1512 cp = fields[LP_DAY];
1513 if (sscanf(cp, "%d%c", &day, &xs) != 1 ||
1514 day <= 0 || day > len_months[isleap(year)][month]) {
1515 error(_("invalid day of month"));
1516 return;
1517 }
1518 dayoff = oadd(dayoff, day - 1);
1519 if (dayoff < min_time / SECSPERDAY) {
1520 error(_("time too small"));
1521 return;
1522 }
1523 if (dayoff > max_time / SECSPERDAY) {
1524 error(_("time too large"));
1525 return;
1526 }
1527 t = dayoff * SECSPERDAY;
1528 tod = gethms(fields[LP_TIME], _("invalid time of day"), false);
1529 cp = fields[LP_CORR];
1530 {
1531 bool positive;
1532 int count;
1533
1534 if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */
1535 positive = false;
1536 count = 1;
1537 } else if (strcmp(cp, "+") == 0) {
1538 positive = true;
1539 count = 1;
1540 } else {
1541 error(_("illegal CORRECTION field on Leap line"));
1542 return;
1543 }
1544 if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) {
1545 error(_(
1546 "illegal Rolling/Stationary field on Leap line"
1547 ));
1548 return;
1549 }
1550 t = tadd(t, tod);
1551 if (t < 0) {
1552 error(_("leap second precedes Epoch"));
1553 return;
1554 }
1555 leapadd(t, positive, lp->l_value, count);
1556 }
1557 }
1558
1559 static void
1560 inlink(char **fields, int nfields)
1561 {
1562 struct link l;
1563
1564 if (nfields != LINK_FIELDS) {
1565 error(_("wrong number of fields on Link line"));
1566 return;
1567 }
1568 if (*fields[LF_FROM] == '\0') {
1569 error(_("blank FROM field on Link line"));
1570 return;
1571 }
1572 if (! namecheck(fields[LF_TO]))
1573 return;
1574 l.l_filename = filename;
1575 l.l_linenum = linenum;
1576 l.l_from = ecpyalloc(fields[LF_FROM]);
1577 l.l_to = ecpyalloc(fields[LF_TO]);
1578 links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc);
1579 links[nlinks++] = l;
1580 }
1581
1582 static void
1583 rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
1584 const char *typep, const char *monthp, const char *dayp,
1585 const char *timep)
1586 {
1587 const struct lookup * lp;
1588 const char * cp;
1589 char * dp;
1590 char * ep;
1591 char xs;
1592
1593 if ((lp = byword(monthp, mon_names)) == NULL) {
1594 error(_("invalid month name"));
1595 return;
1596 }
1597 rp->r_month = lp->l_value;
1598 rp->r_todisstd = false;
1599 rp->r_todisgmt = false;
1600 dp = ecpyalloc(timep);
1601 if (*dp != '\0') {
1602 ep = dp + strlen(dp) - 1;
1603 switch (lowerit(*ep)) {
1604 case 's': /* Standard */
1605 rp->r_todisstd = true;
1606 rp->r_todisgmt = false;
1607 *ep = '\0';
1608 break;
1609 case 'w': /* Wall */
1610 rp->r_todisstd = false;
1611 rp->r_todisgmt = false;
1612 *ep = '\0';
1613 break;
1614 case 'g': /* Greenwich */
1615 case 'u': /* Universal */
1616 case 'z': /* Zulu */
1617 rp->r_todisstd = true;
1618 rp->r_todisgmt = true;
1619 *ep = '\0';
1620 break;
1621 }
1622 }
1623 rp->r_tod = gethms(dp, _("invalid time of day"), false);
1624 free(dp);
1625 /*
1626 ** Year work.
1627 */
1628 cp = loyearp;
1629 lp = byword(cp, begin_years);
1630 rp->r_lowasnum = lp == NULL;
1631 if (!rp->r_lowasnum) switch (lp->l_value) {
1632 case YR_MINIMUM:
1633 rp->r_loyear = ZIC_MIN;
1634 break;
1635 case YR_MAXIMUM:
1636 rp->r_loyear = ZIC_MAX;
1637 break;
1638 default: /* "cannot happen" */
1639 fprintf(stderr,
1640 _("%s: panic: Invalid l_value %d\n"),
1641 progname, lp->l_value);
1642 exit(EXIT_FAILURE);
1643 } else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_loyear, &xs) != 1) {
1644 error(_("invalid starting year"));
1645 return;
1646 }
1647 cp = hiyearp;
1648 lp = byword(cp, end_years);
1649 rp->r_hiwasnum = lp == NULL;
1650 if (!rp->r_hiwasnum) switch (lp->l_value) {
1651 case YR_MINIMUM:
1652 rp->r_hiyear = ZIC_MIN;
1653 break;
1654 case YR_MAXIMUM:
1655 rp->r_hiyear = ZIC_MAX;
1656 break;
1657 case YR_ONLY:
1658 rp->r_hiyear = rp->r_loyear;
1659 break;
1660 default: /* "cannot happen" */
1661 fprintf(stderr,
1662 _("%s: panic: Invalid l_value %d\n"),
1663 progname, lp->l_value);
1664 exit(EXIT_FAILURE);
1665 } else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_hiyear, &xs) != 1) {
1666 error(_("invalid ending year"));
1667 return;
1668 }
1669 if (rp->r_loyear > rp->r_hiyear) {
1670 error(_("starting year greater than ending year"));
1671 return;
1672 }
1673 if (*typep == '\0')
1674 rp->r_yrtype = NULL;
1675 else {
1676 if (rp->r_loyear == rp->r_hiyear) {
1677 error(_("typed single year"));
1678 return;
1679 }
1680 warning(_("year type \"%s\" is obsolete; use \"-\" instead"),
1681 typep);
1682 rp->r_yrtype = ecpyalloc(typep);
1683 }
1684 /*
1685 ** Day work.
1686 ** Accept things such as:
1687 ** 1
1688 ** lastSunday
1689 ** last-Sunday (undocumented; warn about this)
1690 ** Sun<=20
1691 ** Sun>=7
1692 */
1693 dp = ecpyalloc(dayp);
1694 if ((lp = byword(dp, lasts)) != NULL) {
1695 rp->r_dycode = DC_DOWLEQ;
1696 rp->r_wday = lp->l_value;
1697 rp->r_dayofmonth = len_months[1][rp->r_month];
1698 } else {
1699 if ((ep = strchr(dp, '<')) != 0)
1700 rp->r_dycode = DC_DOWLEQ;
1701 else if ((ep = strchr(dp, '>')) != 0)
1702 rp->r_dycode = DC_DOWGEQ;
1703 else {
1704 ep = dp;
1705 rp->r_dycode = DC_DOM;
1706 }
1707 if (rp->r_dycode != DC_DOM) {
1708 *ep++ = 0;
1709 if (*ep++ != '=') {
1710 error(_("invalid day of month"));
1711 free(dp);
1712 return;
1713 }
1714 if ((lp = byword(dp, wday_names)) == NULL) {
1715 error(_("invalid weekday name"));
1716 free(dp);
1717 return;
1718 }
1719 rp->r_wday = lp->l_value;
1720 }
1721 if (sscanf(ep, "%d%c", &rp->r_dayofmonth, &xs) != 1 ||
1722 rp->r_dayofmonth <= 0 ||
1723 (rp->r_dayofmonth > len_months[1][rp->r_month])) {
1724 error(_("invalid day of month"));
1725 free(dp);
1726 return;
1727 }
1728 }
1729 free(dp);
1730 }
1731
1732 static void
1733 convert(const zic_t val, char *const buf)
1734 {
1735 int i;
1736 int shift;
1737 unsigned char *const b = (unsigned char *) buf;
1738
1739 for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
1740 b[i] = val >> shift;
1741 }
1742
1743 static void
1744 convert64(const zic_t val, char *const buf)
1745 {
1746 int i;
1747 int shift;
1748 unsigned char *const b = (unsigned char *) buf;
1749
1750 for (i = 0, shift = 56; i < 8; ++i, shift -= 8)
1751 b[i] = val >> shift;
1752 }
1753
1754 static void
1755 puttzcode(const zic_t val, FILE *const fp)
1756 {
1757 char buf[4];
1758
1759 convert(val, buf);
1760 fwrite(buf, sizeof buf, (size_t) 1, fp);
1761 }
1762
1763 static void
1764 puttzcode64(const zic_t val, FILE *const fp)
1765 {
1766 char buf[8];
1767
1768 convert64(val, buf);
1769 fwrite(buf, sizeof buf, (size_t) 1, fp);
1770 }
1771
1772 static int
1773 atcomp(const void *avp, const void *bvp)
1774 {
1775 const zic_t a = ((const struct attype *) avp)->at;
1776 const zic_t b = ((const struct attype *) bvp)->at;
1777
1778 return (a < b) ? -1 : (a > b);
1779 }
1780
1781 static void
1782 writezone(const char *const name, const char *const string, char version)
1783 {
1784 FILE * fp;
1785 ptrdiff_t i, j;
1786 int leapcnt32, leapi32;
1787 ptrdiff_t timecnt32, timei32;
1788 int pass;
1789 static const struct tzhead tzh0;
1790 static struct tzhead tzh;
1791 bool dir_checked = false;
1792 zic_t one = 1;
1793 zic_t y2038_boundary = one << 31;
1794 ptrdiff_t nats = timecnt + WORK_AROUND_QTBUG_53071;
1795
1796 /* Allocate the ATS and TYPES arrays via a single malloc,
1797 as this is a bit faster. */
1798 zic_t *ats = zic_malloc(align_to(size_product(nats, sizeof *ats + 1),
1799 _Alignof(zic_t)));
1800 void *typesptr = ats + nats;
1801 unsigned char *types = typesptr;
1802
1803 /*
1804 ** Sort.
1805 */
1806 if (timecnt > 1)
1807 qsort(attypes, (size_t) timecnt, sizeof *attypes, atcomp);
1808 /*
1809 ** Optimize.
1810 */
1811 {
1812 ptrdiff_t fromi, toi;
1813
1814 toi = 0;
1815 fromi = 0;
1816 while (fromi < timecnt && attypes[fromi].at < early_time)
1817 ++fromi;
1818 for ( ; fromi < timecnt; ++fromi) {
1819 if (toi > 1 && ((attypes[fromi].at +
1820 gmtoffs[attypes[toi - 1].type]) <=
1821 (attypes[toi - 1].at +
1822 gmtoffs[attypes[toi - 2].type]))) {
1823 attypes[toi - 1].type =
1824 attypes[fromi].type;
1825 continue;
1826 }
1827 if (toi == 0
1828 || attypes[fromi].dontmerge
1829 || attypes[toi - 1].type != attypes[fromi].type)
1830 attypes[toi++] = attypes[fromi];
1831 }
1832 timecnt = toi;
1833 }
1834
1835 if (noise && timecnt > 1200) {
1836 if (timecnt > TZ_MAX_TIMES)
1837 warning(_("reference clients mishandle"
1838 " more than %d transition times"),
1839 TZ_MAX_TIMES);
1840 else
1841 warning(_("pre-2014 clients may mishandle"
1842 " more than 1200 transition times"));
1843 }
1844 /*
1845 ** Transfer.
1846 */
1847 for (i = 0; i < timecnt; ++i) {
1848 ats[i] = attypes[i].at;
1849 types[i] = attypes[i].type;
1850 }
1851
1852 /*
1853 ** Correct for leap seconds.
1854 */
1855 for (i = 0; i < timecnt; ++i) {
1856 j = leapcnt;
1857 while (--j >= 0)
1858 if (ats[i] > trans[j] - corr[j]) {
1859 ats[i] = tadd(ats[i], corr[j]);
1860 break;
1861 }
1862 }
1863
1864 /* Work around QTBUG-53071 for timestamps less than y2038_boundary - 1,
1865 by inserting a no-op transition at time y2038_boundary - 1.
1866 This works only for timestamps before the boundary, which
1867 should be good enough in practice as QTBUG-53071 should be
1868 long-dead by 2038. Do this after correcting for leap
1869 seconds, as the idea is to insert a transition just before
1870 32-bit time_t rolls around, and this occurs at a slightly
1871 different moment if transitions are leap-second corrected. */
1872 if (WORK_AROUND_QTBUG_53071 && timecnt != 0
1873 && ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<')) {
1874 ats[timecnt] = y2038_boundary - 1;
1875 types[timecnt] = types[timecnt - 1];
1876 timecnt++;
1877 }
1878
1879 /*
1880 ** Figure out 32-bit-limited starts and counts.
1881 */
1882 timecnt32 = timecnt;
1883 timei32 = 0;
1884 leapcnt32 = leapcnt;
1885 leapi32 = 0;
1886 while (0 < timecnt32 && INT32_MAX < ats[timecnt32 - 1])
1887 --timecnt32;
1888 while (1 < timecnt32 && ats[timei32] < INT32_MIN
1889 && ats[timei32 + 1] <= INT32_MIN) {
1890 /* Discard too-low transitions, except keep any last too-low
1891 transition if no transition is exactly at INT32_MIN.
1892 The kept transition will be output as an INT32_MIN
1893 "transition" appropriate for buggy 32-bit clients that do
1894 not use time type 0 for timestamps before the first
1895 transition; see below. */
1896 --timecnt32;
1897 ++timei32;
1898 }
1899 while (0 < leapcnt32 && INT32_MAX < trans[leapcnt32 - 1])
1900 --leapcnt32;
1901 while (0 < leapcnt32 && trans[leapi32] < INT32_MIN) {
1902 --leapcnt32;
1903 ++leapi32;
1904 }
1905 /*
1906 ** Remove old file, if any, to snap links.
1907 */
1908 if (remove(name) == 0)
1909 dir_checked = true;
1910 else if (errno != ENOENT) {
1911 const char *e = strerror(errno);
1912
1913 fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"),
1914 progname, directory, name, e);
1915 exit(EXIT_FAILURE);
1916 }
1917 fp = fopen(name, "wb");
1918 if (!fp) {
1919 int fopen_errno = errno;
1920 if (fopen_errno == ENOENT && !dir_checked) {
1921 mkdirs(name, true);
1922 fp = fopen(name, "wb");
1923 fopen_errno = errno;
1924 }
1925 if (!fp) {
1926 fprintf(stderr, _("%s: Can't create %s/%s: %s\n"),
1927 progname, directory, name, strerror(fopen_errno));
1928 exit(EXIT_FAILURE);
1929 }
1930 }
1931 for (pass = 1; pass <= 2; ++pass) {
1932 ptrdiff_t thistimei, thistimecnt, thistimelim;
1933 int thisleapi, thisleapcnt, thisleaplim;
1934 int writetype[TZ_MAX_TYPES];
1935 int typemap[TZ_MAX_TYPES];
1936 int thistypecnt;
1937 char thischars[TZ_MAX_CHARS];
1938 int thischarcnt;
1939 bool toomanytimes;
1940 int indmap[TZ_MAX_CHARS];
1941
1942 if (pass == 1) {
1943 thistimei = timei32;
1944 thistimecnt = timecnt32;
1945 toomanytimes = thistimecnt >> 31 >> 1 != 0;
1946 thisleapi = leapi32;
1947 thisleapcnt = leapcnt32;
1948 } else {
1949 thistimei = 0;
1950 thistimecnt = timecnt;
1951 toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
1952 thisleapi = 0;
1953 thisleapcnt = leapcnt;
1954 }
1955 if (toomanytimes)
1956 error(_("too many transition times"));
1957 thistimelim = thistimei + thistimecnt;
1958 thisleaplim = thisleapi + thisleapcnt;
1959 for (i = 0; i < typecnt; ++i)
1960 writetype[i] = thistimecnt == timecnt;
1961 if (thistimecnt == 0) {
1962 /*
1963 ** No transition times fall in the current
1964 ** (32- or 64-bit) window.
1965 */
1966 if (typecnt != 0)
1967 writetype[typecnt - 1] = true;
1968 } else {
1969 for (i = thistimei - 1; i < thistimelim; ++i)
1970 if (i >= 0)
1971 writetype[types[i]] = true;
1972 /*
1973 ** For America/Godthab and Antarctica/Palmer
1974 */
1975 if (thistimei == 0)
1976 writetype[0] = true;
1977 }
1978 #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
1979 /*
1980 ** For some pre-2011 systems: if the last-to-be-written
1981 ** standard (or daylight) type has an offset different from the
1982 ** most recently used offset,
1983 ** append an (unused) copy of the most recently used type
1984 ** (to help get global "altzone" and "timezone" variables
1985 ** set correctly).
1986 */
1987 {
1988 int mrudst, mrustd, hidst, histd, type;
1989
1990 hidst = histd = mrudst = mrustd = -1;
1991 for (i = thistimei; i < thistimelim; ++i) {
1992 if (i < 0)
1993 continue;
1994 if (isdsts[types[i]])
1995 mrudst = types[i];
1996 else mrustd = types[i];
1997 }
1998 for (i = 0; i < typecnt; ++i)
1999 if (writetype[i]) {
2000 if (isdsts[i])
2001 hidst = i;
2002 else histd = i;
2003 }
2004 if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
2005 gmtoffs[hidst] != gmtoffs[mrudst]) {
2006 isdsts[mrudst] = -1;
2007 type = addtype(gmtoffs[mrudst],
2008 &chars[abbrinds[mrudst]],
2009 true,
2010 ttisstds[mrudst],
2011 ttisgmts[mrudst]);
2012 isdsts[mrudst] = 1;
2013 writetype[type] = true;
2014 }
2015 if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
2016 gmtoffs[histd] != gmtoffs[mrustd]) {
2017 isdsts[mrustd] = -1;
2018 type = addtype(gmtoffs[mrustd],
2019 &chars[abbrinds[mrustd]],
2020 false,
2021 ttisstds[mrustd],
2022 ttisgmts[mrustd]);
2023 isdsts[mrustd] = 0;
2024 writetype[type] = true;
2025 }
2026 }
2027 #endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
2028 thistypecnt = 0;
2029 for (i = 0; i < typecnt; ++i)
2030 typemap[i] = writetype[i] ? thistypecnt++ : -1;
2031 for (i = 0; i < (int)(sizeof indmap / sizeof indmap[0]); ++i)
2032 indmap[i] = -1;
2033 thischarcnt = 0;
2034 for (i = 0; i < typecnt; ++i) {
2035 char * thisabbr;
2036
2037 if (!writetype[i])
2038 continue;
2039 if (indmap[abbrinds[i]] >= 0)
2040 continue;
2041 thisabbr = &chars[abbrinds[i]];
2042 for (j = 0; j < thischarcnt; ++j)
2043 if (strcmp(&thischars[j], thisabbr) == 0)
2044 break;
2045 if (j == thischarcnt) {
2046 strcpy(&thischars[thischarcnt], thisabbr);
2047 thischarcnt += strlen(thisabbr) + 1;
2048 }
2049 indmap[abbrinds[i]] = j;
2050 }
2051 #define DO(field) fwrite(tzh.field, sizeof tzh.field, (size_t) 1, fp)
2052 tzh = tzh0;
2053 memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
2054 tzh.tzh_version[0] = version;
2055 convert(thistypecnt, tzh.tzh_ttisgmtcnt);
2056 convert(thistypecnt, tzh.tzh_ttisstdcnt);
2057 convert(thisleapcnt, tzh.tzh_leapcnt);
2058 convert(thistimecnt, tzh.tzh_timecnt);
2059 convert(thistypecnt, tzh.tzh_typecnt);
2060 convert(thischarcnt, tzh.tzh_charcnt);
2061 DO(tzh_magic);
2062 DO(tzh_version);
2063 DO(tzh_reserved);
2064 DO(tzh_ttisgmtcnt);
2065 DO(tzh_ttisstdcnt);
2066 DO(tzh_leapcnt);
2067 DO(tzh_timecnt);
2068 DO(tzh_typecnt);
2069 DO(tzh_charcnt);
2070 #undef DO
2071 for (i = thistimei; i < thistimelim; ++i)
2072 if (pass == 1)
2073 /*
2074 ** Output an INT32_MIN "transition"
2075 ** if appropriate; see above.
2076 */
2077 puttzcode(((ats[i] < INT32_MIN) ?
2078 INT32_MIN : ats[i]), fp);
2079 else puttzcode64(ats[i], fp);
2080 for (i = thistimei; i < thistimelim; ++i) {
2081 unsigned char uc;
2082
2083 uc = typemap[types[i]];
2084 fwrite(&uc, sizeof uc, (size_t) 1, fp);
2085 }
2086 for (i = 0; i < typecnt; ++i)
2087 if (writetype[i]) {
2088 puttzcode(gmtoffs[i], fp);
2089 putc(isdsts[i], fp);
2090 putc((unsigned char) indmap[abbrinds[i]], fp);
2091 }
2092 if (thischarcnt != 0)
2093 fwrite(thischars, sizeof thischars[0],
2094 (size_t) thischarcnt, fp);
2095 for (i = thisleapi; i < thisleaplim; ++i) {
2096 zic_t todo;
2097
2098 if (roll[i]) {
2099 if (timecnt == 0 || trans[i] < ats[0]) {
2100 j = 0;
2101 while (isdsts[j])
2102 if (++j >= typecnt) {
2103 j = 0;
2104 break;
2105 }
2106 } else {
2107 j = 1;
2108 while (j < timecnt &&
2109 trans[i] >= ats[j])
2110 ++j;
2111 j = types[j - 1];
2112 }
2113 todo = tadd(trans[i], -gmtoffs[j]);
2114 } else todo = trans[i];
2115 if (pass == 1)
2116 puttzcode(todo, fp);
2117 else puttzcode64(todo, fp);
2118 puttzcode(corr[i], fp);
2119 }
2120 for (i = 0; i < typecnt; ++i)
2121 if (writetype[i])
2122 putc(ttisstds[i], fp);
2123 for (i = 0; i < typecnt; ++i)
2124 if (writetype[i])
2125 putc(ttisgmts[i], fp);
2126 }
2127 fprintf(fp, "\n%s\n", string);
2128 close_file(fp, directory, name);
2129 free(ats);
2130 }
2131
2132 static char const *
2133 abbroffset(char *buf, zic_t offset)
2134 {
2135 char sign = '+';
2136 int seconds, minutes;
2137
2138 if (offset < 0) {
2139 offset = -offset;
2140 sign = '-';
2141 }
2142
2143 seconds = offset % SECSPERMIN;
2144 offset /= SECSPERMIN;
2145 minutes = offset % MINSPERHOUR;
2146 offset /= MINSPERHOUR;
2147 if (100 <= offset) {
2148 error(_("%%z UT offset magnitude exceeds 99:59:59"));
2149 return "%z";
2150 } else {
2151 char *p = buf;
2152 *p++ = sign;
2153 *p++ = '0' + offset / 10;
2154 *p++ = '0' + offset % 10;
2155 if (minutes | seconds) {
2156 *p++ = '0' + minutes / 10;
2157 *p++ = '0' + minutes % 10;
2158 if (seconds) {
2159 *p++ = '0' + seconds / 10;
2160 *p++ = '0' + seconds % 10;
2161 }
2162 }
2163 *p = '\0';
2164 return buf;
2165 }
2166 }
2167
2168 static size_t
2169 doabbr(char *abbr, int abbrlen, struct zone const *zp, const char *letters,
2170 bool isdst, zic_t stdoff, bool doquotes)
2171 {
2172 char * cp;
2173 char * slashp;
2174 size_t len;
2175 char const *format = zp->z_format;
2176
2177 slashp = strchr(format, '/');
2178 if (slashp == NULL) {
2179 char letterbuf[PERCENT_Z_LEN_BOUND + 1];
2180 if (zp->z_format_specifier == 'z')
2181 letters = abbroffset(letterbuf, zp->z_gmtoff + stdoff);
2182 else if (!letters)
2183 letters = "%s";
2184 snprintf(abbr, abbrlen, format, letters);
2185 } else if (isdst) {
2186 strlcpy(abbr, slashp + 1, abbrlen);
2187 } else {
2188 memcpy(abbr, format, slashp - format);
2189 abbr[slashp - format] = '\0';
2190 }
2191 len = strlen(abbr);
2192 if (!doquotes)
2193 return len;
2194 for (cp = abbr; is_alpha(*cp); cp++)
2195 continue;
2196 if (len > 0 && *cp == '\0')
2197 return len;
2198 abbr[len + 2] = '\0';
2199 abbr[len + 1] = '>';
2200 memmove(abbr + 1, abbr, len);
2201 abbr[0] = '<';
2202 return len + 2;
2203 }
2204
2205 static void
2206 updateminmax(const zic_t x)
2207 {
2208 if (min_year > x)
2209 min_year = x;
2210 if (max_year < x)
2211 max_year = x;
2212 }
2213
2214 static int
2215 stringoffset(char *result, zic_t offset)
2216 {
2217 int hours;
2218 int minutes;
2219 int seconds;
2220 bool negative = offset < 0;
2221 int len = negative;
2222
2223 if (negative) {
2224 offset = -offset;
2225 result[0] = '-';
2226 }
2227 seconds = offset % SECSPERMIN;
2228 offset /= SECSPERMIN;
2229 minutes = offset % MINSPERHOUR;
2230 offset /= MINSPERHOUR;
2231 hours = offset;
2232 if (hours >= HOURSPERDAY * DAYSPERWEEK) {
2233 result[0] = '\0';
2234 return 0;
2235 }
2236 len += sprintf(result + len, "%d", hours);
2237 if (minutes != 0 || seconds != 0) {
2238 len += sprintf(result + len, ":%02d", minutes);
2239 if (seconds != 0)
2240 len += sprintf(result + len, ":%02d", seconds);
2241 }
2242 return len;
2243 }
2244
2245 static int
2246 stringrule(char *result, const struct rule *const rp, const zic_t dstoff,
2247 const zic_t gmtoff)
2248 {
2249 zic_t tod = rp->r_tod;
2250 int compat = 0;
2251
2252 if (rp->r_dycode == DC_DOM) {
2253 int month, total;
2254
2255 if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY)
2256 return -1;
2257 total = 0;
2258 for (month = 0; month < rp->r_month; ++month)
2259 total += len_months[0][month];
2260 /* Omit the "J" in Jan and Feb, as that's shorter. */
2261 if (rp->r_month <= 1)
2262 result += sprintf(result, "%d", total + rp->r_dayofmonth - 1);
2263 else
2264 result += sprintf(result, "J%d", total + rp->r_dayofmonth);
2265 } else {
2266 int week;
2267 int wday = rp->r_wday;
2268 int wdayoff;
2269
2270 if (rp->r_dycode == DC_DOWGEQ) {
2271 wdayoff = (rp->r_dayofmonth - 1) % DAYSPERWEEK;
2272 if (wdayoff)
2273 compat = 2013;
2274 wday -= wdayoff;
2275 tod += wdayoff * SECSPERDAY;
2276 week = 1 + (rp->r_dayofmonth - 1) / DAYSPERWEEK;
2277 } else if (rp->r_dycode == DC_DOWLEQ) {
2278 if (rp->r_dayofmonth == len_months[1][rp->r_month])
2279 week = 5;
2280 else {
2281 wdayoff = rp->r_dayofmonth % DAYSPERWEEK;
2282 if (wdayoff)
2283 compat = 2013;
2284 wday -= wdayoff;
2285 tod += wdayoff * SECSPERDAY;
2286 week = rp->r_dayofmonth / DAYSPERWEEK;
2287 }
2288 } else return -1; /* "cannot happen" */
2289 if (wday < 0)
2290 wday += DAYSPERWEEK;
2291 result += sprintf(result, "M%d.%d.%d",
2292 rp->r_month + 1, week, wday);
2293 }
2294 if (rp->r_todisgmt)
2295 tod += gmtoff;
2296 if (rp->r_todisstd && !rp->r_isdst)
2297 tod += dstoff;
2298 if (tod != 2 * SECSPERMIN * MINSPERHOUR) {
2299 *result++ = '/';
2300 if (! stringoffset(result, tod))
2301 return -1;
2302 if (tod < 0) {
2303 if (compat < 2013)
2304 compat = 2013;
2305 } else if (SECSPERDAY <= tod) {
2306 if (compat < 1994)
2307 compat = 1994;
2308 }
2309 }
2310 return compat;
2311 }
2312
2313 static int
2314 rule_cmp(struct rule const *a, struct rule const *b)
2315 {
2316 if (!a)
2317 return -!!b;
2318 if (!b)
2319 return 1;
2320 if (a->r_hiyear != b->r_hiyear)
2321 return a->r_hiyear < b->r_hiyear ? -1 : 1;
2322 if (a->r_month - b->r_month != 0)
2323 return a->r_month - b->r_month;
2324 return a->r_dayofmonth - b->r_dayofmonth;
2325 }
2326
2327 enum { YEAR_BY_YEAR_ZONE = 1 };
2328
2329 static int
2330 stringzone(char *result, const int resultlen, const struct zone *const zpfirst,
2331 const int zonecount)
2332 {
2333 const struct zone * zp;
2334 struct rule * rp;
2335 struct rule * stdrp;
2336 struct rule * dstrp;
2337 ptrdiff_t i;
2338 const char * abbrvar;
2339 int compat = 0;
2340 int c;
2341 size_t len;
2342 int offsetlen;
2343 struct rule stdr, dstr;
2344
2345 result[0] = '\0';
2346 zp = zpfirst + zonecount - 1;
2347 stdrp = dstrp = NULL;
2348 for (i = 0; i < zp->z_nrules; ++i) {
2349 rp = &zp->z_rules[i];
2350 if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX)
2351 continue;
2352 if (rp->r_yrtype != NULL)
2353 continue;
2354 if (!rp->r_isdst) {
2355 if (stdrp == NULL)
2356 stdrp = rp;
2357 else return -1;
2358 } else {
2359 if (dstrp == NULL)
2360 dstrp = rp;
2361 else return -1;
2362 }
2363 }
2364 if (stdrp == NULL && dstrp == NULL) {
2365 /*
2366 ** There are no rules running through "max".
2367 ** Find the latest std rule in stdabbrrp
2368 ** and latest rule of any type in stdrp.
2369 */
2370 struct rule *stdabbrrp = NULL;
2371 for (i = 0; i < zp->z_nrules; ++i) {
2372 rp = &zp->z_rules[i];
2373 if (!rp->r_isdst && rule_cmp(stdabbrrp, rp) < 0)
2374 stdabbrrp = rp;
2375 if (rule_cmp(stdrp, rp) < 0)
2376 stdrp = rp;
2377 }
2378 /*
2379 ** Horrid special case: if year is 2037,
2380 ** presume this is a zone handled on a year-by-year basis;
2381 ** do not try to apply a rule to the zone.
2382 */
2383 if (stdrp != NULL && stdrp->r_hiyear == 2037)
2384 return YEAR_BY_YEAR_ZONE;
2385
2386 if (stdrp != NULL && stdrp->r_isdst) {
2387 /* Perpetual DST. */
2388 dstr.r_month = TM_JANUARY;
2389 dstr.r_dycode = DC_DOM;
2390 dstr.r_dayofmonth = 1;
2391 dstr.r_tod = 0;
2392 dstr.r_todisstd = dstr.r_todisgmt = false;
2393 dstr.r_isdst = stdrp->r_isdst;
2394 dstr.r_stdoff = stdrp->r_stdoff;
2395 dstr.r_abbrvar = stdrp->r_abbrvar;
2396 stdr.r_month = TM_DECEMBER;
2397 stdr.r_dycode = DC_DOM;
2398 stdr.r_dayofmonth = 31;
2399 stdr.r_tod = SECSPERDAY + stdrp->r_stdoff;
2400 stdr.r_todisstd = stdr.r_todisgmt = false;
2401 stdr.r_isdst = false;
2402 stdr.r_stdoff = 0;
2403 stdr.r_abbrvar
2404 = (stdabbrrp ? stdabbrrp->r_abbrvar : "");
2405 dstrp = &dstr;
2406 stdrp = &stdr;
2407 }
2408 }
2409 if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_isdst))
2410 return -1;
2411 abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
2412 len = doabbr(result, resultlen, zp, abbrvar, false, 0, true);
2413 offsetlen = stringoffset(result + len, -zp->z_gmtoff);
2414 if (! offsetlen) {
2415 result[0] = '\0';
2416 return -1;
2417 }
2418 len += offsetlen;
2419 if (dstrp == NULL)
2420 return compat;
2421 len += doabbr(result + len, resultlen - len, zp, dstrp->r_abbrvar,
2422 dstrp->r_isdst, dstrp->r_stdoff, true);
2423 if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR) {
2424 offsetlen = stringoffset(result + len,
2425 -(zp->z_gmtoff + dstrp->r_stdoff));
2426 if (! offsetlen) {
2427 result[0] = '\0';
2428 return -1;
2429 }
2430 len += offsetlen;
2431 }
2432 result[len++] = ',';
2433 c = stringrule(result + len, dstrp, dstrp->r_stdoff, zp->z_gmtoff);
2434 if (c < 0) {
2435 result[0] = '\0';
2436 return -1;
2437 }
2438 if (compat < c)
2439 compat = c;
2440 len += strlen(result + len);
2441 result[len++] = ',';
2442 c = stringrule(result + len, stdrp, dstrp->r_stdoff, zp->z_gmtoff);
2443 if (c < 0) {
2444 result[0] = '\0';
2445 return -1;
2446 }
2447 if (compat < c)
2448 compat = c;
2449 return compat;
2450 }
2451
2452 static void
2453 outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
2454 {
2455 const struct zone * zp;
2456 struct rule * rp;
2457 ptrdiff_t i, j;
2458 bool usestart, useuntil;
2459 zic_t starttime, untiltime;
2460 zic_t gmtoff;
2461 zic_t stdoff;
2462 zic_t year;
2463 zic_t startoff;
2464 bool startttisstd;
2465 bool startttisgmt;
2466 int type;
2467 char * startbuf;
2468 char * ab;
2469 char * envvar;
2470 size_t max_abbr_len;
2471 size_t max_envvar_len;
2472 bool prodstic; /* all rules are min to max */
2473 int compat;
2474 bool do_extend;
2475 int version;
2476 ptrdiff_t lastatmax = -1;
2477 zic_t one = 1;
2478 zic_t y2038_boundary = one << 31;
2479 zic_t max_year0;
2480
2481 max_abbr_len = 2 + max_format_len + max_abbrvar_len;
2482 max_envvar_len = 2 * max_abbr_len + 5 * 9;
2483 startbuf = zic_malloc(max_abbr_len + 1);
2484 ab = zic_malloc(max_abbr_len + 1);
2485 envvar = zic_malloc(max_envvar_len + 1);
2486 INITIALIZE(untiltime);
2487 INITIALIZE(starttime);
2488 /*
2489 ** Now. . .finally. . .generate some useful data!
2490 */
2491 timecnt = 0;
2492 typecnt = 0;
2493 charcnt = 0;
2494 prodstic = zonecount == 1;
2495 /*
2496 ** Thanks to Earl Chew
2497 ** for noting the need to unconditionally initialize startttisstd.
2498 */
2499 startttisstd = false;
2500 startttisgmt = false;
2501 min_year = max_year = EPOCH_YEAR;
2502 if (leapseen) {
2503 updateminmax(leapminyear);
2504 updateminmax(leapmaxyear + (leapmaxyear < ZIC_MAX));
2505 }
2506 for (i = 0; i < zonecount; ++i) {
2507 zp = &zpfirst[i];
2508 if (i < zonecount - 1)
2509 updateminmax(zp->z_untilrule.r_loyear);
2510 for (j = 0; j < zp->z_nrules; ++j) {
2511 rp = &zp->z_rules[j];
2512 if (rp->r_lowasnum)
2513 updateminmax(rp->r_loyear);
2514 if (rp->r_hiwasnum)
2515 updateminmax(rp->r_hiyear);
2516 if (rp->r_lowasnum || rp->r_hiwasnum)
2517 prodstic = false;
2518 }
2519 }
2520 /*
2521 ** Generate lots of data if a rule can't cover all future times.
2522 */
2523 compat = stringzone(envvar, max_envvar_len + 1, zpfirst, zonecount);
2524 version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION;
2525 do_extend = compat < 0 || compat == YEAR_BY_YEAR_ZONE;
2526 if (noise) {
2527 if (!*envvar)
2528 warning("%s %s",
2529 _("no POSIX environment variable for zone"),
2530 zpfirst->z_name);
2531 else if (compat != 0 && compat != YEAR_BY_YEAR_ZONE) {
2532 /* Circa-COMPAT clients, and earlier clients, might
2533 not work for this zone when given dates before
2534 1970 or after 2038. */
2535 warning(_("%s: pre-%d clients may mishandle"
2536 " distant timestamps"),
2537 zpfirst->z_name, compat);
2538 }
2539 }
2540 if (do_extend) {
2541 /*
2542 ** Search through a couple of extra years past the obvious
2543 ** 400, to avoid edge cases. For example, suppose a non-POSIX
2544 ** rule applies from 2012 onwards and has transitions in March
2545 ** and September, plus some one-off transitions in November
2546 ** 2013. If zic looked only at the last 400 years, it would
2547 ** set max_year=2413, with the intent that the 400 years 2014
2548 ** through 2413 will be repeated. The last transition listed
2549 ** in the tzfile would be in 2413-09, less than 400 years
2550 ** after the last one-off transition in 2013-11. Two years
2551 ** might be overkill, but with the kind of edge cases
2552 ** available we're not sure that one year would suffice.
2553 */
2554 enum { years_of_observations = YEARSPERREPEAT + 2 };
2555
2556 if (min_year >= ZIC_MIN + years_of_observations)
2557 min_year -= years_of_observations;
2558 else min_year = ZIC_MIN;
2559 if (max_year <= ZIC_MAX - years_of_observations)
2560 max_year += years_of_observations;
2561 else max_year = ZIC_MAX;
2562 /*
2563 ** Regardless of any of the above,
2564 ** for a "proDSTic" zone which specifies that its rules
2565 ** always have and always will be in effect,
2566 ** we only need one cycle to define the zone.
2567 */
2568 if (prodstic) {
2569 min_year = 1900;
2570 max_year = min_year + years_of_observations;
2571 }
2572 }
2573 /*
2574 ** For the benefit of older systems,
2575 ** generate data from 1900 through 2038.
2576 */
2577 if (min_year > 1900)
2578 min_year = 1900;
2579 max_year0 = max_year;
2580 if (max_year < 2038)
2581 max_year = 2038;
2582 for (i = 0; i < zonecount; ++i) {
2583 /*
2584 ** A guess that may well be corrected later.
2585 */
2586 stdoff = 0;
2587 zp = &zpfirst[i];
2588 usestart = i > 0 && (zp - 1)->z_untiltime > early_time;
2589 useuntil = i < (zonecount - 1);
2590 if (useuntil && zp->z_untiltime <= early_time)
2591 continue;
2592 gmtoff = zp->z_gmtoff;
2593 eat(zp->z_filename, zp->z_linenum);
2594 *startbuf = '\0';
2595 startoff = zp->z_gmtoff;
2596 if (zp->z_nrules == 0) {
2597 stdoff = zp->z_stdoff;
2598 doabbr(startbuf, max_abbr_len + 1, zp,
2599 NULL, zp->z_isdst, stdoff, false);
2600 type = addtype(oadd(zp->z_gmtoff, stdoff),
2601 startbuf, stdoff != 0, startttisstd,
2602 startttisgmt);
2603 if (usestart) {
2604 addtt(starttime, type);
2605 usestart = false;
2606 } else addtt(early_time, type);
2607 } else for (year = min_year; year <= max_year; ++year) {
2608 if (useuntil && year > zp->z_untilrule.r_hiyear)
2609 break;
2610 /*
2611 ** Mark which rules to do in the current year.
2612 ** For those to do, calculate rpytime(rp, year);
2613 */
2614 for (j = 0; j < zp->z_nrules; ++j) {
2615 rp = &zp->z_rules[j];
2616 eats(zp->z_filename, zp->z_linenum,
2617 rp->r_filename, rp->r_linenum);
2618 rp->r_todo = year >= rp->r_loyear &&
2619 year <= rp->r_hiyear &&
2620 yearistype(year, rp->r_yrtype);
2621 if (rp->r_todo) {
2622 rp->r_temp = rpytime(rp, year);
2623 rp->r_todo
2624 = (rp->r_temp < y2038_boundary
2625 || year <= max_year0);
2626 }
2627 }
2628 for ( ; ; ) {
2629 ptrdiff_t k;
2630 zic_t jtime, ktime;
2631 zic_t offset;
2632
2633 INITIALIZE(ktime);
2634 if (useuntil) {
2635 /*
2636 ** Turn untiltime into UT
2637 ** assuming the current gmtoff and
2638 ** stdoff values.
2639 */
2640 untiltime = zp->z_untiltime;
2641 if (!zp->z_untilrule.r_todisgmt)
2642 untiltime = tadd(untiltime,
2643 -gmtoff);
2644 if (!zp->z_untilrule.r_todisstd)
2645 untiltime = tadd(untiltime,
2646 -stdoff);
2647 }
2648 /*
2649 ** Find the rule (of those to do, if any)
2650 ** that takes effect earliest in the year.
2651 */
2652 k = -1;
2653 for (j = 0; j < zp->z_nrules; ++j) {
2654 rp = &zp->z_rules[j];
2655 if (!rp->r_todo)
2656 continue;
2657 eats(zp->z_filename, zp->z_linenum,
2658 rp->r_filename, rp->r_linenum);
2659 offset = rp->r_todisgmt ? 0 : gmtoff;
2660 if (!rp->r_todisstd)
2661 offset = oadd(offset, stdoff);
2662 jtime = rp->r_temp;
2663 if (jtime == min_time ||
2664 jtime == max_time)
2665 continue;
2666 jtime = tadd(jtime, -offset);
2667 if (k < 0 || jtime < ktime) {
2668 k = j;
2669 ktime = jtime;
2670 } else if (jtime == ktime) {
2671 char const *dup_rules_msg =
2672 _("two rules for same instant");
2673 eats(zp->z_filename, zp->z_linenum,
2674 rp->r_filename, rp->r_linenum);
2675 warning("%s", dup_rules_msg);
2676 rp = &zp->z_rules[k];
2677 eats(zp->z_filename, zp->z_linenum,
2678 rp->r_filename, rp->r_linenum);
2679 error("%s", dup_rules_msg);
2680 }
2681 }
2682 if (k < 0)
2683 break; /* go on to next year */
2684 rp = &zp->z_rules[k];
2685 rp->r_todo = false;
2686 if (useuntil && ktime >= untiltime)
2687 break;
2688 stdoff = rp->r_stdoff;
2689 if (usestart && ktime == starttime)
2690 usestart = false;
2691 if (usestart) {
2692 if (ktime < starttime) {
2693 startoff = oadd(zp->z_gmtoff,
2694 stdoff);
2695 doabbr(startbuf,
2696 max_abbr_len + 1,
2697 zp,
2698 rp->r_abbrvar,
2699 rp->r_isdst,
2700 rp->r_stdoff,
2701 false);
2702 continue;
2703 }
2704 if (*startbuf == '\0' &&
2705 startoff == oadd(zp->z_gmtoff,
2706 stdoff)) {
2707 doabbr(startbuf,
2708 max_abbr_len + 1,
2709 zp,
2710 rp->r_abbrvar,
2711 rp->r_isdst,
2712 rp->r_stdoff,
2713 false);
2714 }
2715 }
2716 eats(zp->z_filename, zp->z_linenum,
2717 rp->r_filename, rp->r_linenum);
2718 doabbr(ab, max_abbr_len + 1, zp, rp->r_abbrvar,
2719 rp->r_isdst, rp->r_stdoff, false);
2720 offset = oadd(zp->z_gmtoff, rp->r_stdoff);
2721 type = addtype(offset, ab, rp->r_isdst,
2722 rp->r_todisstd, rp->r_todisgmt);
2723 if (rp->r_hiyear == ZIC_MAX
2724 && ! (0 <= lastatmax
2725 && ktime < attypes[lastatmax].at))
2726 lastatmax = timecnt;
2727 addtt(ktime, type);
2728 }
2729 }
2730 if (usestart) {
2731 if (*startbuf == '\0' &&
2732 zp->z_format != NULL &&
2733 strchr(zp->z_format, '%') == NULL &&
2734 strchr(zp->z_format, '/') == NULL)
2735 strncpy(startbuf, zp->z_format,
2736 max_abbr_len + 1 - 1);
2737 eat(zp->z_filename, zp->z_linenum);
2738 if (*startbuf == '\0')
2739 error(_("can't determine time zone abbreviation to use just after until time"));
2740 else addtt(starttime,
2741 addtype(startoff, startbuf,
2742 startoff != zp->z_gmtoff,
2743 startttisstd,
2744 startttisgmt));
2745 }
2746 /*
2747 ** Now we may get to set starttime for the next zone line.
2748 */
2749 if (useuntil) {
2750 startttisstd = zp->z_untilrule.r_todisstd;
2751 startttisgmt = zp->z_untilrule.r_todisgmt;
2752 starttime = zp->z_untiltime;
2753 if (!startttisstd)
2754 starttime = tadd(starttime, -stdoff);
2755 if (!startttisgmt)
2756 starttime = tadd(starttime, -gmtoff);
2757 }
2758 }
2759 if (0 <= lastatmax)
2760 attypes[lastatmax].dontmerge = true;
2761 if (do_extend) {
2762 /*
2763 ** If we're extending the explicitly listed observations
2764 ** for 400 years because we can't fill the POSIX-TZ field,
2765 ** check whether we actually ended up explicitly listing
2766 ** observations through that period. If there aren't any
2767 ** near the end of the 400-year period, add a redundant
2768 ** one at the end of the final year, to make it clear
2769 ** that we are claiming to have definite knowledge of
2770 ** the lack of transitions up to that point.
2771 */
2772 struct rule xr;
2773 struct attype *lastat;
2774 memset(&xr, 0, sizeof(xr));
2775 xr.r_month = TM_JANUARY;
2776 xr.r_dycode = DC_DOM;
2777 xr.r_dayofmonth = 1;
2778 xr.r_tod = 0;
2779 for (lastat = &attypes[0], i = 1; i < timecnt; i++)
2780 if (attypes[i].at > lastat->at)
2781 lastat = &attypes[i];
2782 if (lastat->at < rpytime(&xr, max_year - 1)) {
2783 addtt(rpytime(&xr, max_year + 1), typecnt-1);
2784 attypes[timecnt - 1].dontmerge = true;
2785 }
2786 }
2787 writezone(zpfirst->z_name, envvar, version);
2788 free(startbuf);
2789 free(ab);
2790 free(envvar);
2791 }
2792
2793 static void
2794 addtt(zic_t starttime, int type)
2795 {
2796 if (starttime <= early_time
2797 || (timecnt == 1 && attypes[0].at < early_time)) {
2798 gmtoffs[0] = gmtoffs[type];
2799 isdsts[0] = isdsts[type];
2800 ttisstds[0] = ttisstds[type];
2801 ttisgmts[0] = ttisgmts[type];
2802 if (abbrinds[type] != 0)
2803 strcpy(chars, &chars[abbrinds[type]]);
2804 abbrinds[0] = 0;
2805 charcnt = strlen(chars) + 1;
2806 typecnt = 1;
2807 timecnt = 0;
2808 type = 0;
2809 }
2810 attypes = growalloc(attypes, sizeof *attypes, timecnt, &timecnt_alloc);
2811 attypes[timecnt].at = starttime;
2812 attypes[timecnt].dontmerge = false;
2813 attypes[timecnt].type = type;
2814 ++timecnt;
2815 }
2816
2817 static int
2818 addtype(zic_t gmtoff, char const *abbr, bool isdst, bool ttisstd, bool ttisgmt)
2819 {
2820 int i, j;
2821
2822 /*
2823 ** See if there's already an entry for this zone type.
2824 ** If so, just return its index.
2825 */
2826 for (i = 0; i < typecnt; ++i) {
2827 if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
2828 strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
2829 ttisstd == ttisstds[i] &&
2830 ttisgmt == ttisgmts[i])
2831 return i;
2832 }
2833 /*
2834 ** There isn't one; add a new one, unless there are already too
2835 ** many.
2836 */
2837 if (typecnt >= TZ_MAX_TYPES) {
2838 error(_("too many local time types"));
2839 exit(EXIT_FAILURE);
2840 }
2841 if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) {
2842 error(_("UT offset out of range"));
2843 exit(EXIT_FAILURE);
2844 }
2845 gmtoffs[i] = gmtoff;
2846 isdsts[i] = isdst;
2847 ttisstds[i] = ttisstd;
2848 ttisgmts[i] = ttisgmt;
2849
2850 for (j = 0; j < charcnt; ++j)
2851 if (strcmp(&chars[j], abbr) == 0)
2852 break;
2853 if (j == charcnt)
2854 newabbr(abbr);
2855 abbrinds[i] = j;
2856 ++typecnt;
2857 return i;
2858 }
2859
2860 static void
2861 leapadd(zic_t t, bool positive, int rolling, int count)
2862 {
2863 int i, j;
2864
2865 if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) {
2866 error(_("too many leap seconds"));
2867 exit(EXIT_FAILURE);
2868 }
2869 for (i = 0; i < leapcnt; ++i)
2870 if (t <= trans[i])
2871 break;
2872 do {
2873 for (j = leapcnt; j > i; --j) {
2874 trans[j] = trans[j - 1];
2875 corr[j] = corr[j - 1];
2876 roll[j] = roll[j - 1];
2877 }
2878 trans[i] = t;
2879 corr[i] = positive ? 1 : -count;
2880 roll[i] = rolling;
2881 ++leapcnt;
2882 } while (positive && --count != 0);
2883 }
2884
2885 static void
2886 adjleap(void)
2887 {
2888 int i;
2889 zic_t last = 0;
2890 zic_t prevtrans = 0;
2891
2892 /*
2893 ** propagate leap seconds forward
2894 */
2895 for (i = 0; i < leapcnt; ++i) {
2896 if (trans[i] - prevtrans < 28 * SECSPERDAY) {
2897 error(_("Leap seconds too close together"));
2898 exit(EXIT_FAILURE);
2899 }
2900 prevtrans = trans[i];
2901 trans[i] = tadd(trans[i], last);
2902 last = corr[i] += last;
2903 }
2904 }
2905
2906 static char *
2907 shellquote(char *b, char const *s)
2908 {
2909 *b++ = '\'';
2910 while (*s) {
2911 if (*s == '\'')
2912 *b++ = '\'', *b++ = '\\', *b++ = '\'';
2913 *b++ = *s++;
2914 }
2915 *b++ = '\'';
2916 return b;
2917 }
2918
2919 static bool
2920 yearistype(zic_t year, const char *type)
2921 {
2922 char *buf;
2923 char *b;
2924 int result;
2925 size_t len;
2926
2927 if (type == NULL || *type == '\0')
2928 return true;
2929 buf = zic_malloc(len = 1 + 4 * strlen(yitcommand) + 2
2930 + INT_STRLEN_MAXIMUM(zic_t) + 2 + 4 * strlen(type) + 2);
2931 b = shellquote(buf, yitcommand);
2932 *b++ = ' ';
2933 b += snprintf(b, len - (b - buf), "%"PRIdZIC, year);
2934 *b++ = ' ';
2935 b = shellquote(b, type);
2936 *b = '\0';
2937 result = system(buf);
2938 if (WIFEXITED(result)) {
2939 int status = WEXITSTATUS(result);
2940 if (status <= 1) {
2941 free(buf);
2942 return status == 0;
2943 }
2944 }
2945 error(_("Wild result from command execution"));
2946 fprintf(stderr, _("%s: command was '%s', result was %d\n"),
2947 progname, buf, result);
2948 exit(EXIT_FAILURE);
2949 }
2950
2951 /* Is A a space character in the C locale? */
2952 static bool
2953 is_space(char a)
2954 {
2955 switch (a) {
2956 default:
2957 return false;
2958 case ' ': case '\f': case '\n': case '\r': case '\t': case '\v':
2959 return true;
2960 }
2961 }
2962
2963 /* Is A an alphabetic character in the C locale? */
2964 static bool
2965 is_alpha(char a)
2966 {
2967 switch (a) {
2968 default:
2969 return 0;
2970 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
2971 case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
2972 case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
2973 case 'V': case 'W': case 'X': case 'Y': case 'Z':
2974 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
2975 case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
2976 case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
2977 case 'v': case 'w': case 'x': case 'y': case 'z':
2978 return true;
2979 }
2980 }
2981
2982 /* If A is an uppercase character in the C locale, return its lowercase
2983 counterpart. Otherwise, return A. */
2984 static char
2985 lowerit(char a)
2986 {
2987 switch (a) {
2988 default: return a;
2989 case 'A': return 'a'; case 'B': return 'b'; case 'C': return 'c';
2990 case 'D': return 'd'; case 'E': return 'e'; case 'F': return 'f';
2991 case 'G': return 'g'; case 'H': return 'h'; case 'I': return 'i';
2992 case 'J': return 'j'; case 'K': return 'k'; case 'L': return 'l';
2993 case 'M': return 'm'; case 'N': return 'n'; case 'O': return 'o';
2994 case 'P': return 'p'; case 'Q': return 'q'; case 'R': return 'r';
2995 case 'S': return 's'; case 'T': return 't'; case 'U': return 'u';
2996 case 'V': return 'v'; case 'W': return 'w'; case 'X': return 'x';
2997 case 'Y': return 'y'; case 'Z': return 'z';
2998 }
2999 }
3000
3001 /* case-insensitive equality */
3002 static bool
3003 ciequal(const char *ap, const char *bp)
3004 {
3005 while (lowerit(*ap) == lowerit(*bp++))
3006 if (*ap++ == '\0')
3007 return true;
3008 return false;
3009 }
3010
3011 static bool
3012 itsabbr(const char *abbr, const char *word)
3013 {
3014 if (lowerit(*abbr) != lowerit(*word))
3015 return false;
3016 ++word;
3017 while (*++abbr != '\0')
3018 do {
3019 if (*word == '\0')
3020 return false;
3021 } while (lowerit(*word++) != lowerit(*abbr));
3022 return true;
3023 }
3024
3025 /* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case. */
3026
3027 static bool
3028 ciprefix(char const *abbr, char const *word)
3029 {
3030 do
3031 if (!*abbr)
3032 return true;
3033 while (lowerit(*abbr++) == lowerit(*word++));
3034
3035 return false;
3036 }
3037
3038 static const struct lookup *
3039 byword(const char *word, const struct lookup *table)
3040 {
3041 const struct lookup * foundlp;
3042 const struct lookup * lp;
3043
3044 if (word == NULL || table == NULL)
3045 return NULL;
3046
3047 /* If TABLE is LASTS and the word starts with "last" followed
3048 by a non-'-', skip the "last" and look in WDAY_NAMES instead.
3049 Warn about any usage of the undocumented prefix "last-". */
3050 if (table == lasts && ciprefix("last", word) && word[4]) {
3051 if (word[4] == '-')
3052 warning(_("\"%s\" is undocumented; use \"last%s\" instead"),
3053 word, word + 5);
3054 else {
3055 word += 4;
3056 table = wday_names;
3057 }
3058 }
3059
3060 /*
3061 ** Look for exact match.
3062 */
3063 for (lp = table; lp->l_word != NULL; ++lp)
3064 if (ciequal(word, lp->l_word))
3065 return lp;
3066 /*
3067 ** Look for inexact match.
3068 */
3069 foundlp = NULL;
3070 for (lp = table; lp->l_word != NULL; ++lp)
3071 if (ciprefix(word, lp->l_word)) {
3072 if (foundlp == NULL)
3073 foundlp = lp;
3074 else return NULL; /* multiple inexact matches */
3075 }
3076
3077 /* Warn about any backward-compatibility issue with pre-2017c zic. */
3078 if (foundlp) {
3079 bool pre_2017c_match = false;
3080 for (lp = table; lp->l_word; lp++)
3081 if (itsabbr(word, lp->l_word)) {
3082 if (pre_2017c_match) {
3083 warning(_("\"%s\" is ambiguous in pre-2017c zic"), word);
3084 break;
3085 }
3086 pre_2017c_match = true;
3087 }
3088 }
3089
3090 return foundlp;
3091 }
3092
3093 static char **
3094 getfields(char *cp)
3095 {
3096 char * dp;
3097 char ** array;
3098 int nsubs;
3099
3100 if (cp == NULL)
3101 return NULL;
3102 array = zic_malloc(size_product(strlen(cp) + 1, sizeof *array));
3103 nsubs = 0;
3104 for ( ; ; ) {
3105 while (is_space(*cp))
3106 ++cp;
3107 if (*cp == '\0' || *cp == '#')
3108 break;
3109 array[nsubs++] = dp = cp;
3110 do {
3111 if ((*dp = *cp++) != '"')
3112 ++dp;
3113 else while ((*dp = *cp++) != '"')
3114 if (*dp != '\0')
3115 ++dp;
3116 else {
3117 error(_("Odd number of quotation marks"));
3118 exit(EXIT_FAILURE);
3119 }
3120 } while (*cp && *cp != '#' && !is_space(*cp));
3121 if (is_space(*cp))
3122 ++cp;
3123 *dp = '\0';
3124 }
3125 array[nsubs] = NULL;
3126 return array;
3127 }
3128
3129 static _Noreturn void
3130 time_overflow(void)
3131 {
3132 error(_("time overflow"));
3133 exit(EXIT_FAILURE);
3134 }
3135
3136 static ATTRIBUTE_PURE zic_t
3137 oadd(zic_t t1, zic_t t2)
3138 {
3139 if (t1 < 0 ? t2 < ZIC_MIN - t1 : ZIC_MAX - t1 < t2)
3140 time_overflow();
3141 return t1 + t2;
3142 }
3143
3144 static ATTRIBUTE_PURE zic_t
3145 tadd(zic_t t1, zic_t t2)
3146 {
3147 if (t1 < 0) {
3148 if (t2 < min_time - t1) {
3149 if (t1 != min_time)
3150 time_overflow();
3151 return min_time;
3152 }
3153 } else {
3154 if (max_time - t1 < t2) {
3155 if (t1 != max_time)
3156 time_overflow();
3157 return max_time;
3158 }
3159 }
3160 return t1 + t2;
3161 }
3162
3163 /*
3164 ** Given a rule, and a year, compute the date (in seconds since January 1,
3165 ** 1970, 00:00 LOCAL time) in that year that the rule refers to.
3166 */
3167
3168 static zic_t
3169 rpytime(const struct rule *rp, zic_t wantedy)
3170 {
3171 int m, i;
3172 zic_t dayoff; /* with a nod to Margaret O. */
3173 zic_t t, y;
3174
3175 if (wantedy == ZIC_MIN)
3176 return min_time;
3177 if (wantedy == ZIC_MAX)
3178 return max_time;
3179 dayoff = 0;
3180 m = TM_JANUARY;
3181 y = EPOCH_YEAR;
3182 while (wantedy != y) {
3183 if (wantedy > y) {
3184 i = len_years[isleap(y)];
3185 ++y;
3186 } else {
3187 --y;
3188 i = -len_years[isleap(y)];
3189 }
3190 dayoff = oadd(dayoff, i);
3191 }
3192 while (m != rp->r_month) {
3193 i = len_months[isleap(y)][m];
3194 dayoff = oadd(dayoff, i);
3195 ++m;
3196 }
3197 i = rp->r_dayofmonth;
3198 if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
3199 if (rp->r_dycode == DC_DOWLEQ)
3200 --i;
3201 else {
3202 error(_("use of 2/29 in non leap-year"));
3203 exit(EXIT_FAILURE);
3204 }
3205 }
3206 --i;
3207 dayoff = oadd(dayoff, i);
3208 if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
3209 zic_t wday;
3210
3211 #define LDAYSPERWEEK ((zic_t) DAYSPERWEEK)
3212 wday = EPOCH_WDAY;
3213 /*
3214 ** Don't trust mod of negative numbers.
3215 */
3216 if (dayoff >= 0)
3217 wday = (wday + dayoff) % LDAYSPERWEEK;
3218 else {
3219 wday -= ((-dayoff) % LDAYSPERWEEK);
3220 if (wday < 0)
3221 wday += LDAYSPERWEEK;
3222 }
3223 while (wday != rp->r_wday)
3224 if (rp->r_dycode == DC_DOWGEQ) {
3225 dayoff = oadd(dayoff, (zic_t) 1);
3226 if (++wday >= LDAYSPERWEEK)
3227 wday = 0;
3228 ++i;
3229 } else {
3230 dayoff = oadd(dayoff, (zic_t) -1);
3231 if (--wday < 0)
3232 wday = LDAYSPERWEEK - 1;
3233 --i;
3234 }
3235 if (i < 0 || i >= len_months[isleap(y)][m]) {
3236 if (noise)
3237 warning(_("rule goes past start/end of month; \
3238 will not work with pre-2004 versions of zic"));
3239 }
3240 }
3241 if (dayoff < min_time / SECSPERDAY)
3242 return min_time;
3243 if (dayoff > max_time / SECSPERDAY)
3244 return max_time;
3245 t = (zic_t) dayoff * SECSPERDAY;
3246 return tadd(t, rp->r_tod);
3247 }
3248
3249 static void
3250 newabbr(const char *string)
3251 {
3252 int i;
3253
3254 if (strcmp(string, GRANDPARENTED) != 0) {
3255 const char * cp;
3256 const char * mp;
3257
3258 cp = string;
3259 mp = NULL;
3260 while (is_alpha(*cp) || ('0' <= *cp && *cp <= '9')
3261 || *cp == '-' || *cp == '+')
3262 ++cp;
3263 if (noise && cp - string < 3)
3264 mp = _("time zone abbreviation has fewer than 3 characters");
3265 if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN)
3266 mp = _("time zone abbreviation has too many characters");
3267 if (*cp != '\0')
3268 mp = _("time zone abbreviation differs from POSIX standard");
3269 if (mp != NULL)
3270 warning("%s (%s)", mp, string);
3271 }
3272 i = strlen(string) + 1;
3273 if (charcnt + i > TZ_MAX_CHARS) {
3274 error(_("too many, or too long, time zone abbreviations"));
3275 exit(EXIT_FAILURE);
3276 }
3277 strncpy(&chars[charcnt], string, sizeof(chars) - charcnt - 1);
3278 charcnt += i;
3279 }
3280
3281 /* Ensure that the directories of ARGNAME exist, by making any missing
3282 ones. If ANCESTORS, do this only for ARGNAME's ancestors; otherwise,
3283 do it for ARGNAME too. Exit with failure if there is trouble.
3284 Do not consider an existing non-directory to be trouble. */
3285 static void
3286 mkdirs(char const *argname, bool ancestors)
3287 {
3288 char * name;
3289 char * cp;
3290
3291 cp = name = ecpyalloc(argname);
3292
3293 /* On MS-Windows systems, do not worry about drive letters or
3294 backslashes, as this should suffice in practice. Time zone
3295 names do not use drive letters and backslashes. If the -d
3296 option of zic does not name an already-existing directory,
3297 it can use slashes to separate the already-existing
3298 ancestor prefix from the to-be-created subdirectories. */
3299
3300 /* Do not mkdir a root directory, as it must exist. */
3301 while (*cp == '/')
3302 cp++;
3303
3304 while (cp && ((cp = strchr(cp, '/')) || !ancestors)) {
3305 if (cp)
3306 *cp = '\0';
3307 /*
3308 ** Try to create it. It's OK if creation fails because
3309 ** the directory already exists, perhaps because some
3310 ** other process just created it. For simplicity do
3311 ** not check first whether it already exists, as that
3312 ** is checked anyway if the mkdir fails.
3313 */
3314 if (mkdir(name, MKDIR_UMASK) != 0) {
3315 /* For speed, skip itsdir if errno == EEXIST. Since
3316 mkdirs is called only after open fails with ENOENT
3317 on a subfile, EEXIST implies itsdir here. */
3318 int err = errno;
3319 if (err != EEXIST && !itsdir(name)) {
3320 error(_("%s: Can't create directory %s: %s"),
3321 progname, name, strerror(err));
3322 exit(EXIT_FAILURE);
3323 }
3324 }
3325 if (cp)
3326 *cp++ = '/';
3327 }
3328 free(name);
3329 }
3330