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