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