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