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