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