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