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