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