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