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