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