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