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