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