1 /* $NetBSD: zic.c,v 1.71 2018/05/04 15:51:00 christos Exp $ */ 2 /* 3 ** This file is in the public domain, so clarified as of 4 ** 2006-07-17 by Arthur David Olson. 5 */ 6 7 #if HAVE_NBTOOL_CONFIG_H 8 #include "nbtool_config.h" 9 #endif 10 11 #include <sys/cdefs.h> 12 #ifndef lint 13 __RCSID("$NetBSD: zic.c,v 1.71 2018/05/04 15:51:00 christos Exp $"); 14 #endif /* !defined lint */ 15 16 #include "private.h" 17 #include "tzfile.h" 18 19 #include <fcntl.h> 20 #include <locale.h> 21 #include <stdarg.h> 22 #include <stddef.h> 23 #include <stdio.h> 24 #include <unistd.h> 25 #include <util.h> 26 27 #define ZIC_VERSION_PRE_2013 '2' 28 #define ZIC_VERSION '3' 29 30 typedef int_fast64_t zic_t; 31 #define ZIC_MIN INT_FAST64_MIN 32 #define ZIC_MAX INT_FAST64_MAX 33 #define PRIdZIC PRIdFAST64 34 #define SCNdZIC SCNdFAST64 35 36 #ifndef ZIC_MAX_ABBR_LEN_WO_WARN 37 #define ZIC_MAX_ABBR_LEN_WO_WARN 6 38 #endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */ 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 #if HAVE_SYS_STAT_H 48 #include <sys/stat.h> 49 #endif 50 #ifdef S_IRUSR 51 #define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) 52 #else 53 #define MKDIR_UMASK 0755 54 #endif 55 /* Port to native MS-Windows and to ancient UNIX. */ 56 #if !defined S_ISDIR && defined S_IFDIR && defined S_IFMT 57 # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) 58 #endif 59 60 #if HAVE_SYS_WAIT_H 61 #include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */ 62 #endif /* HAVE_SYS_WAIT_H */ 63 64 #ifndef WIFEXITED 65 #define WIFEXITED(status) (((status) & 0xff) == 0) 66 #endif /* !defined WIFEXITED */ 67 #ifndef WEXITSTATUS 68 #define WEXITSTATUS(status) (((status) >> 8) & 0xff) 69 #endif /* !defined WEXITSTATUS */ 70 71 /* The maximum ptrdiff_t value, for pre-C99 platforms. */ 72 #ifndef PTRDIFF_MAX 73 static ptrdiff_t const PTRDIFF_MAX = MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t)); 74 #endif 75 76 /* The type for line numbers. Use PRIdMAX to format them; formerly 77 there was also "#define PRIdLINENO PRIdMAX" and formats used 78 PRIdLINENO, but xgettext cannot grok that. */ 79 typedef intmax_t lineno; 80 81 struct rule { 82 const char * r_filename; 83 lineno r_linenum; 84 const char * r_name; 85 86 zic_t r_loyear; /* for example, 1986 */ 87 zic_t r_hiyear; /* for example, 1986 */ 88 const char * r_yrtype; 89 bool r_lowasnum; 90 bool r_hiwasnum; 91 92 int r_month; /* 0..11 */ 93 94 int r_dycode; /* see below */ 95 int r_dayofmonth; 96 int r_wday; 97 98 zic_t r_tod; /* time from midnight */ 99 bool r_todisstd; /* above is standard time if 1 */ 100 /* or wall clock time if 0 */ 101 bool r_todisgmt; /* above is GMT if 1 */ 102 /* or local time if 0 */ 103 bool r_isdst; /* is this daylight saving time? */ 104 zic_t r_stdoff; /* offset from default time (which is 105 usually standard time) */ 106 const char * r_abbrvar; /* variable part of abbreviation */ 107 108 bool r_todo; /* a rule to do (used in outzone) */ 109 zic_t r_temp; /* used in outzone */ 110 }; 111 112 /* 113 ** r_dycode r_dayofmonth r_wday 114 */ 115 116 #define DC_DOM 0 /* 1..31 */ /* unused */ 117 #define DC_DOWGEQ 1 /* 1..31 */ /* 0..6 (Sun..Sat) */ 118 #define DC_DOWLEQ 2 /* 1..31 */ /* 0..6 (Sun..Sat) */ 119 120 struct zone { 121 const char * z_filename; 122 lineno z_linenum; 123 124 const char * z_name; 125 zic_t z_gmtoff; 126 char * z_rule; 127 const char * z_format; 128 char z_format_specifier; 129 130 bool z_isdst; 131 zic_t z_stdoff; 132 133 struct rule * z_rules; 134 ptrdiff_t z_nrules; 135 136 struct rule z_untilrule; 137 zic_t z_untiltime; 138 }; 139 140 #if !HAVE_POSIX_DECLS 141 extern int getopt(int argc, char * const argv[], 142 const char * options); 143 extern int link(const char * fromname, const char * toname); 144 extern char * optarg; 145 extern int optind; 146 #endif 147 148 #if ! HAVE_LINK 149 # define link(from, to) (errno = ENOTSUP, -1) 150 #endif 151 #if ! HAVE_SYMLINK 152 # define readlink(file, buf, size) (errno = ENOTSUP, -1) 153 # define symlink(from, to) (errno = ENOTSUP, -1) 154 # define S_ISLNK(m) 0 155 #endif 156 #ifndef AT_SYMLINK_FOLLOW 157 # define linkat(fromdir, from, todir, to, flag) \ 158 (itssymlink(from) ? (errno = ENOTSUP, -1) : link(from, to)) 159 #endif 160 161 static void addtt(zic_t starttime, int type); 162 static int addtype(zic_t, char const *, bool, bool, bool); 163 static void leapadd(zic_t, bool, int, int); 164 static void adjleap(void); 165 static void associate(void); 166 static void dolink(const char *, const char *, bool); 167 static char ** getfields(char * buf); 168 static zic_t gethms(const char * string, const char * errstring, 169 bool); 170 static zic_t getstdoff(char *, bool *); 171 static void infile(const char * filename); 172 static void inleap(char ** fields, int nfields); 173 static void inlink(char ** fields, int nfields); 174 static void inrule(char ** fields, int nfields); 175 static bool inzcont(char ** fields, int nfields); 176 static bool inzone(char ** fields, int nfields); 177 static bool inzsub(char **, int, int); 178 static bool itsdir(const char *); 179 static bool itssymlink(const char *); 180 static bool is_alpha(char a); 181 static char lowerit(char); 182 static void mkdirs(char const *, bool); 183 static void newabbr(const char * abbr); 184 static zic_t oadd(zic_t t1, zic_t t2); 185 static void outzone(const struct zone * zp, ptrdiff_t ntzones); 186 static zic_t rpytime(const struct rule * rp, zic_t wantedy); 187 static void rulesub(struct rule * rp, 188 const char * loyearp, const char * hiyearp, 189 const char * typep, const char * monthp, 190 const char * dayp, const char * timep); 191 static zic_t tadd(zic_t t1, zic_t t2); 192 static bool yearistype(zic_t year, const char * type); 193 194 /* Bound on length of what %z can expand to. */ 195 enum { PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1 }; 196 197 /* If true, work around a bug in Qt 5.6.1 and earlier, which mishandles 198 tz binary files whose POSIX-TZ-style strings contain '<'; see 199 QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>. This 200 workaround will no longer be needed when Qt 5.6.1 and earlier are 201 obsolete, say in the year 2021. */ 202 enum { WORK_AROUND_QTBUG_53071 = 1 }; 203 204 static int charcnt; 205 static bool errors; 206 static bool warnings; 207 static const char * filename; 208 static int leapcnt; 209 static bool leapseen; 210 static zic_t leapminyear; 211 static zic_t leapmaxyear; 212 static lineno linenum; 213 static size_t max_abbrvar_len = PERCENT_Z_LEN_BOUND; 214 static size_t max_format_len; 215 static zic_t max_year; 216 static zic_t min_year; 217 static bool noise; 218 static const char * rfilename; 219 static lineno rlinenum; 220 static const char * progname; 221 static ptrdiff_t timecnt; 222 static ptrdiff_t timecnt_alloc; 223 static int typecnt; 224 225 /* 226 ** Line codes. 227 */ 228 229 #define LC_RULE 0 230 #define LC_ZONE 1 231 #define LC_LINK 2 232 #define LC_LEAP 3 233 234 /* 235 ** Which fields are which on a Zone line. 236 */ 237 238 #define ZF_NAME 1 239 #define ZF_GMTOFF 2 240 #define ZF_RULE 3 241 #define ZF_FORMAT 4 242 #define ZF_TILYEAR 5 243 #define ZF_TILMONTH 6 244 #define ZF_TILDAY 7 245 #define ZF_TILTIME 8 246 #define ZONE_MINFIELDS 5 247 #define ZONE_MAXFIELDS 9 248 249 /* 250 ** Which fields are which on a Zone continuation line. 251 */ 252 253 #define ZFC_GMTOFF 0 254 #define ZFC_RULE 1 255 #define ZFC_FORMAT 2 256 #define ZFC_TILYEAR 3 257 #define ZFC_TILMONTH 4 258 #define ZFC_TILDAY 5 259 #define ZFC_TILTIME 6 260 #define ZONEC_MINFIELDS 3 261 #define ZONEC_MAXFIELDS 7 262 263 /* 264 ** Which files are which on a Rule line. 265 */ 266 267 #define RF_NAME 1 268 #define RF_LOYEAR 2 269 #define RF_HIYEAR 3 270 #define RF_COMMAND 4 271 #define RF_MONTH 5 272 #define RF_DAY 6 273 #define RF_TOD 7 274 #define RF_STDOFF 8 275 #define RF_ABBRVAR 9 276 #define RULE_FIELDS 10 277 278 /* 279 ** Which fields are which on a Link line. 280 */ 281 282 #define LF_FROM 1 283 #define LF_TO 2 284 #define LINK_FIELDS 3 285 286 /* 287 ** Which fields are which on a Leap line. 288 */ 289 290 #define LP_YEAR 1 291 #define LP_MONTH 2 292 #define LP_DAY 3 293 #define LP_TIME 4 294 #define LP_CORR 5 295 #define LP_ROLL 6 296 #define LEAP_FIELDS 7 297 298 /* 299 ** Year synonyms. 300 */ 301 302 #define YR_MINIMUM 0 303 #define YR_MAXIMUM 1 304 #define YR_ONLY 2 305 306 static struct rule * rules; 307 static ptrdiff_t nrules; /* number of rules */ 308 static ptrdiff_t nrules_alloc; 309 310 static struct zone * zones; 311 static ptrdiff_t nzones; /* number of zones */ 312 static ptrdiff_t nzones_alloc; 313 314 struct link { 315 const char * l_filename; 316 lineno l_linenum; 317 const char * l_from; 318 const char * l_to; 319 }; 320 321 static struct link * links; 322 static ptrdiff_t nlinks; 323 static ptrdiff_t nlinks_alloc; 324 325 struct lookup { 326 const char * l_word; 327 const int l_value; 328 }; 329 330 static struct lookup const * byword(const char * string, 331 const struct lookup * lp); 332 333 static struct lookup const zi_line_codes[] = { 334 { "Rule", LC_RULE }, 335 { "Zone", LC_ZONE }, 336 { "Link", LC_LINK }, 337 { NULL, 0 } 338 }; 339 static struct lookup const leap_line_codes[] = { 340 { "Leap", LC_LEAP }, 341 { NULL, 0} 342 }; 343 344 static struct lookup const mon_names[] = { 345 { "January", TM_JANUARY }, 346 { "February", TM_FEBRUARY }, 347 { "March", TM_MARCH }, 348 { "April", TM_APRIL }, 349 { "May", TM_MAY }, 350 { "June", TM_JUNE }, 351 { "July", TM_JULY }, 352 { "August", TM_AUGUST }, 353 { "September", TM_SEPTEMBER }, 354 { "October", TM_OCTOBER }, 355 { "November", TM_NOVEMBER }, 356 { "December", TM_DECEMBER }, 357 { NULL, 0 } 358 }; 359 360 static struct lookup const wday_names[] = { 361 { "Sunday", TM_SUNDAY }, 362 { "Monday", TM_MONDAY }, 363 { "Tuesday", TM_TUESDAY }, 364 { "Wednesday", TM_WEDNESDAY }, 365 { "Thursday", TM_THURSDAY }, 366 { "Friday", TM_FRIDAY }, 367 { "Saturday", TM_SATURDAY }, 368 { NULL, 0 } 369 }; 370 371 static struct lookup const lasts[] = { 372 { "last-Sunday", TM_SUNDAY }, 373 { "last-Monday", TM_MONDAY }, 374 { "last-Tuesday", TM_TUESDAY }, 375 { "last-Wednesday", TM_WEDNESDAY }, 376 { "last-Thursday", TM_THURSDAY }, 377 { "last-Friday", TM_FRIDAY }, 378 { "last-Saturday", TM_SATURDAY }, 379 { NULL, 0 } 380 }; 381 382 static struct lookup const begin_years[] = { 383 { "minimum", YR_MINIMUM }, 384 { "maximum", YR_MAXIMUM }, 385 { NULL, 0 } 386 }; 387 388 static struct lookup const end_years[] = { 389 { "minimum", YR_MINIMUM }, 390 { "maximum", YR_MAXIMUM }, 391 { "only", YR_ONLY }, 392 { NULL, 0 } 393 }; 394 395 static struct lookup const leap_types[] = { 396 { "Rolling", true }, 397 { "Stationary", false }, 398 { NULL, 0 } 399 }; 400 401 static const int len_months[2][MONSPERYEAR] = { 402 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 403 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 404 }; 405 406 static const int len_years[2] = { 407 DAYSPERNYEAR, DAYSPERLYEAR 408 }; 409 410 static struct attype { 411 zic_t at; 412 bool dontmerge; 413 unsigned char type; 414 } * attypes; 415 static zic_t gmtoffs[TZ_MAX_TYPES]; 416 static char isdsts[TZ_MAX_TYPES]; 417 static unsigned char abbrinds[TZ_MAX_TYPES]; 418 static bool ttisstds[TZ_MAX_TYPES]; 419 static bool ttisgmts[TZ_MAX_TYPES]; 420 static char chars[TZ_MAX_CHARS]; 421 static zic_t trans[TZ_MAX_LEAPS]; 422 static zic_t corr[TZ_MAX_LEAPS]; 423 static char roll[TZ_MAX_LEAPS]; 424 425 /* 426 ** Memory allocation. 427 */ 428 429 static _Noreturn void 430 memory_exhausted(const char *msg) 431 { 432 fprintf(stderr, _("%s: Memory exhausted: %s\n"), progname, msg); 433 exit(EXIT_FAILURE); 434 } 435 436 static ATTRIBUTE_PURE size_t 437 size_product(size_t nitems, size_t itemsize) 438 { 439 if (SIZE_MAX / itemsize < nitems) 440 memory_exhausted(_("size overflow")); 441 return nitems * itemsize; 442 } 443 444 #if !HAVE_STRDUP 445 static char * 446 strdup(char const *str) 447 { 448 char *result = malloc(strlen(str) + 1); 449 return result ? strcpy(result, str) : result; 450 } 451 #endif 452 453 static void * 454 memcheck(void *ptr) 455 { 456 if (ptr == NULL) 457 memory_exhausted(strerror(errno)); 458 return ptr; 459 } 460 461 static void * ATTRIBUTE_MALLOC 462 zic_malloc(size_t size) 463 { 464 return memcheck(malloc(size)); 465 } 466 467 static void * 468 zic_realloc(void *ptr, size_t size) 469 { 470 return memcheck(realloc(ptr, size)); 471 } 472 473 static char * ATTRIBUTE_MALLOC 474 ecpyalloc(char const *str) 475 { 476 return memcheck(strdup(str)); 477 } 478 479 static void * 480 growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc) 481 { 482 if (nitems < *nitems_alloc) 483 return ptr; 484 else { 485 ptrdiff_t nitems_max = PTRDIFF_MAX - WORK_AROUND_QTBUG_53071; 486 ptrdiff_t amax = (ptrdiff_t)((size_t)nitems_max < SIZE_MAX ? 487 (size_t)nitems_max : SIZE_MAX); 488 if ((amax - 1) / 3 * 2 < *nitems_alloc) 489 memory_exhausted(_("integer overflow")); 490 *nitems_alloc += (*nitems_alloc >> 1) + 1; 491 return zic_realloc(ptr, size_product(*nitems_alloc, itemsize)); 492 } 493 } 494 495 /* 496 ** Error handling. 497 */ 498 499 static void 500 eats(char const *name, lineno num, char const *rname, lineno rnum) 501 { 502 filename = name; 503 linenum = num; 504 rfilename = rname; 505 rlinenum = rnum; 506 } 507 508 static void 509 eat(char const *name, lineno num) 510 { 511 eats(name, num, NULL, -1); 512 } 513 514 static void ATTRIBUTE_FORMAT((printf, 1, 0)) 515 verror(const char *const string, va_list args) 516 { 517 /* 518 ** Match the format of "cc" to allow sh users to 519 ** zic ... 2>&1 | error -t "*" -v 520 ** on BSD systems. 521 */ 522 if (filename) 523 fprintf(stderr, _("\"%s\", line %"PRIdMAX": "), filename, linenum); 524 vfprintf(stderr, string, args); 525 if (rfilename != NULL) 526 fprintf(stderr, _(" (rule from \"%s\", line %"PRIdMAX")"), 527 rfilename, rlinenum); 528 fprintf(stderr, "\n"); 529 } 530 531 static void ATTRIBUTE_FORMAT((printf, 1, 2)) 532 error(const char *const string, ...) 533 { 534 va_list args; 535 va_start(args, string); 536 verror(string, args); 537 va_end(args); 538 errors = true; 539 } 540 541 static void ATTRIBUTE_FORMAT((printf, 1, 2)) 542 warning(const char *const string, ...) 543 { 544 va_list args; 545 fprintf(stderr, _("warning: ")); 546 va_start(args, string); 547 verror(string, args); 548 va_end(args); 549 warnings = true; 550 } 551 552 static void 553 close_file(FILE *stream, char const *dir, char const *name) 554 { 555 char const *e = (ferror(stream) ? _("I/O error") 556 : fclose(stream) != 0 ? strerror(errno) : NULL); 557 if (e) { 558 fprintf(stderr, "%s: %s%s%s%s%s\n", progname, 559 dir ? dir : "", dir ? "/" : "", 560 name ? name : "", name ? ": " : "", 561 e); 562 exit(EXIT_FAILURE); 563 } 564 } 565 566 static _Noreturn void 567 usage(FILE *stream, int status) 568 { 569 fprintf(stream, 570 _("%s: usage is %s [ --version ] [ --help ] [ -v ] \\\n" 571 "\t[ -l localtime ] [ -p posixrules ] [ -d directory ] \\\n" 572 "\t[ -t localtime-link ] [ -L leapseconds ] [ filename ... ]\n\n" 573 "Report bugs to %s.\n"), 574 progname, progname, REPORT_BUGS_TO); 575 if (status == EXIT_SUCCESS) 576 close_file(stream, NULL, NULL); 577 exit(status); 578 } 579 580 /* Change the working directory to DIR, possibly creating DIR and its 581 ancestors. After this is done, all files are accessed with names 582 relative to DIR. */ 583 static void 584 change_directory (char const *dir) 585 { 586 if (chdir(dir) != 0) { 587 int chdir_errno = errno; 588 if (chdir_errno == ENOENT) { 589 mkdirs(dir, false); 590 chdir_errno = chdir(dir) == 0 ? 0 : errno; 591 } 592 if (chdir_errno != 0) { 593 fprintf(stderr, _("%s: Can't chdir to %s: %s\n"), 594 progname, dir, strerror(chdir_errno)); 595 exit(EXIT_FAILURE); 596 } 597 } 598 } 599 600 static const char * psxrules; 601 static const char * lcltime; 602 static const char * directory; 603 static const char * leapsec; 604 static const char * tzdefault; 605 static const char * yitcommand; 606 607 int 608 main(int argc, char **argv) 609 { 610 int c, k; 611 ptrdiff_t i, j; 612 613 #ifdef S_IWGRP 614 umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH)); 615 #endif 616 #if HAVE_GETTEXT 617 setlocale(LC_MESSAGES, ""); 618 #ifdef TZ_DOMAINDIR 619 bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR); 620 #endif /* defined TEXTDOMAINDIR */ 621 textdomain(TZ_DOMAIN); 622 #endif /* HAVE_GETTEXT */ 623 progname = argv[0]; 624 if (TYPE_BIT(zic_t) < 64) { 625 fprintf(stderr, "%s: %s\n", progname, 626 _("wild compilation-time specification of zic_t")); 627 return EXIT_FAILURE; 628 } 629 for (k = 1; k < argc; k++) 630 if (strcmp(argv[k], "--version") == 0) { 631 printf("zic %s%s\n", PKGVERSION, TZVERSION); 632 close_file(stdout, NULL, NULL); 633 return EXIT_SUCCESS; 634 } else if (strcmp(argv[k], "--help") == 0) { 635 usage(stdout, EXIT_SUCCESS); 636 } 637 while ((c = getopt(argc, argv, "d:l:L:p:st:vy:")) != EOF && c != -1) 638 switch (c) { 639 default: 640 usage(stderr, EXIT_FAILURE); 641 case 'd': 642 if (directory == NULL) 643 directory = optarg; 644 else { 645 fprintf(stderr, 646 _("%s: More than one -d option specified\n"), 647 progname); 648 return EXIT_FAILURE; 649 } 650 break; 651 case 'l': 652 if (lcltime == NULL) 653 lcltime = optarg; 654 else { 655 fprintf(stderr, 656 _("%s: More than one -l option specified\n"), 657 progname); 658 return EXIT_FAILURE; 659 } 660 break; 661 case 'p': 662 if (psxrules == NULL) 663 psxrules = optarg; 664 else { 665 fprintf(stderr, 666 _("%s: More than one -p option specified\n"), 667 progname); 668 return EXIT_FAILURE; 669 } 670 break; 671 case 't': 672 if (tzdefault != NULL) { 673 fprintf(stderr, 674 _("%s: More than one -t option" 675 " specified\n"), 676 progname); 677 return EXIT_FAILURE; 678 } 679 tzdefault = optarg; 680 break; 681 case 'y': 682 if (yitcommand == NULL) { 683 warning(_("-y is obsolescent")); 684 yitcommand = optarg; 685 } else { 686 fprintf(stderr, 687 _("%s: More than one -y option specified\n"), 688 progname); 689 return EXIT_FAILURE; 690 } 691 break; 692 case 'L': 693 if (leapsec == NULL) 694 leapsec = optarg; 695 else { 696 fprintf(stderr, 697 _("%s: More than one -L option specified\n"), 698 progname); 699 return EXIT_FAILURE; 700 } 701 break; 702 case 'v': 703 noise = true; 704 break; 705 case 's': 706 warning(_("-s ignored")); 707 break; 708 } 709 if (optind == argc - 1 && strcmp(argv[optind], "=") == 0) 710 usage(stderr, EXIT_FAILURE); /* usage message by request */ 711 if (directory == NULL) 712 directory = TZDIR; 713 if (tzdefault == NULL) 714 tzdefault = TZDEFAULT; 715 if (yitcommand == NULL) 716 yitcommand = "yearistype"; 717 718 if (optind < argc && leapsec != NULL) { 719 infile(leapsec); 720 adjleap(); 721 } 722 723 for (k = optind; k < argc; k++) 724 infile(argv[k]); 725 if (errors) 726 return EXIT_FAILURE; 727 associate(); 728 change_directory(directory); 729 for (i = 0; i < nzones; i = j) { 730 /* 731 ** Find the next non-continuation zone entry. 732 */ 733 for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j) 734 continue; 735 outzone(&zones[i], j - i); 736 } 737 /* 738 ** Make links. 739 */ 740 for (i = 0; i < nlinks; ++i) { 741 eat(links[i].l_filename, links[i].l_linenum); 742 dolink(links[i].l_from, links[i].l_to, false); 743 if (noise) 744 for (j = 0; j < nlinks; ++j) 745 if (strcmp(links[i].l_to, 746 links[j].l_from) == 0) 747 warning(_("link to link")); 748 } 749 if (lcltime != NULL) { 750 eat(_("command line"), 1); 751 dolink(lcltime, tzdefault, true); 752 } 753 if (psxrules != NULL) { 754 eat(_("command line"), 1); 755 dolink(psxrules, TZDEFRULES, true); 756 } 757 if (warnings && (ferror(stderr) || fclose(stderr) != 0)) 758 return EXIT_FAILURE; 759 return errors ? EXIT_FAILURE : EXIT_SUCCESS; 760 } 761 762 static bool 763 componentcheck(char const *name, char const *component, 764 char const *component_end) 765 { 766 enum { component_len_max = 14 }; 767 ptrdiff_t component_len = component_end - component; 768 if (component_len == 0) { 769 if (!*name) 770 error (_("empty file name")); 771 else 772 error (_(component == name 773 ? "file name '%s' begins with '/'" 774 : *component_end 775 ? "file name '%s' contains '//'" 776 : "file name '%s' ends with '/'"), 777 name); 778 return false; 779 } 780 if (0 < component_len && component_len <= 2 781 && component[0] == '.' && component_end[-1] == '.') { 782 int len = component_len; 783 error(_("file name '%s' contains '%.*s' component"), 784 name, len, component); 785 return false; 786 } 787 if (noise) { 788 if (0 < component_len && component[0] == '-') 789 warning(_("file name '%s' component contains leading '-'"), 790 name); 791 if (component_len_max < component_len) 792 warning(_("file name '%s' contains overlength component" 793 " '%.*s...'"), 794 name, component_len_max, component); 795 } 796 return true; 797 } 798 799 static bool 800 namecheck(const char *name) 801 { 802 char const *cp; 803 804 /* Benign characters in a portable file name. */ 805 static char const benign[] = 806 "-/_" 807 "abcdefghijklmnopqrstuvwxyz" 808 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 809 810 /* Non-control chars in the POSIX portable character set, 811 excluding the benign characters. */ 812 static char const printable_and_not_benign[] = 813 " !\"#$%&'()*+,.0123456789:;<=>?@[\\]^`{|}~"; 814 815 char const *component = name; 816 for (cp = name; *cp; cp++) { 817 unsigned char c = *cp; 818 if (noise && !strchr(benign, c)) { 819 warning((strchr(printable_and_not_benign, c) 820 ? _("file name '%s' contains byte '%c'") 821 : _("file name '%s' contains byte '\\%o'")), 822 name, c); 823 } 824 if (c == '/') { 825 if (!componentcheck(name, component, cp)) 826 return false; 827 component = cp + 1; 828 } 829 } 830 return componentcheck(name, component, cp); 831 } 832 833 /* Create symlink contents suitable for symlinking FROM to TO, as a 834 freshly allocated string. FROM should be a relative file name, and 835 is relative to the global variable DIRECTORY. TO can be either 836 relative or absolute. */ 837 static char * 838 relname(char const *from, char const *to) 839 { 840 size_t i, taillen, dotdotetcsize; 841 size_t dir_len = 0, dotdots = 0, linksize = SIZE_MAX; 842 char const *f = from; 843 char *result = NULL; 844 if (*to == '/') { 845 /* Make F absolute too. */ 846 size_t len = strlen(directory); 847 bool needslash = len && directory[len - 1] != '/'; 848 linksize = len + needslash + strlen(from) + 1; 849 f = result = emalloc(linksize); 850 strcpy(result, directory); 851 result[len] = '/'; 852 strcpy(result + len + needslash, from); 853 } 854 for (i = 0; f[i] && f[i] == to[i]; i++) 855 if (f[i] == '/') 856 dir_len = i + 1; 857 for (; to[i]; i++) 858 dotdots += to[i] == '/' && to[i - 1] != '/'; 859 taillen = strlen(f + dir_len); 860 dotdotetcsize = 3 * dotdots + taillen + 1; 861 if (dotdotetcsize <= linksize) { 862 if (!result) 863 result = emalloc(dotdotetcsize); 864 for (i = 0; i < dotdots; i++) 865 memcpy(result + 3 * i, "../", 3); 866 memmove(result + 3 * dotdots, f + dir_len, taillen + 1); 867 } 868 return result; 869 } 870 871 /* Hard link FROM to TO, following any symbolic links. 872 Return 0 if successful, an error number otherwise. */ 873 static int 874 hardlinkerr(char const *from, char const *to) 875 { 876 int r = linkat(AT_FDCWD, from, AT_FDCWD, to, AT_SYMLINK_FOLLOW); 877 return r == 0 ? 0 : errno; 878 } 879 880 static void 881 dolink(char const *fromfield, char const *tofield, bool staysymlink) 882 { 883 bool todirs_made = false; 884 int link_errno; 885 886 /* 887 ** We get to be careful here since 888 ** there's a fair chance of root running us. 889 */ 890 if (itsdir(fromfield)) { 891 fprintf(stderr, _("%s: link from %s/%s failed: %s\n"), 892 progname, directory, fromfield, strerror(EPERM)); 893 exit(EXIT_FAILURE); 894 } 895 if (staysymlink) 896 staysymlink = itssymlink(tofield); 897 if (remove(tofield) == 0) 898 todirs_made = true; 899 else if (errno != ENOENT) { 900 char const *e = strerror(errno); 901 fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"), 902 progname, directory, tofield, e); 903 exit(EXIT_FAILURE); 904 } 905 link_errno = staysymlink ? ENOTSUP : hardlinkerr(fromfield, tofield); 906 if (link_errno == ENOENT && !todirs_made) { 907 mkdirs(tofield, true); 908 todirs_made = true; 909 link_errno = hardlinkerr(fromfield, tofield); 910 } 911 if (link_errno != 0) { 912 bool absolute = *fromfield == '/'; 913 char *linkalloc = absolute ? NULL : relname(fromfield, tofield); 914 char const *contents = absolute ? fromfield : linkalloc; 915 int symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno; 916 if (!todirs_made 917 && (symlink_errno == ENOENT || symlink_errno == ENOTSUP)) { 918 mkdirs(tofield, true); 919 if (symlink_errno == ENOENT) 920 symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno; 921 } 922 free(linkalloc); 923 if (symlink_errno == 0) { 924 if (link_errno != ENOTSUP) 925 warning(_("symbolic link used because hard link failed: %s"), 926 strerror(link_errno)); 927 } else { 928 FILE *fp, *tp; 929 int c; 930 fp = fopen(fromfield, "rb"); 931 if (!fp) { 932 char const *e = strerror(errno); 933 fprintf(stderr, _("%s: Can't read %s/%s: %s\n"), 934 progname, directory, fromfield, e); 935 exit(EXIT_FAILURE); 936 } 937 tp = fopen(tofield, "wb"); 938 if (!tp) { 939 char const *e = strerror(errno); 940 fprintf(stderr, _("%s: Can't create %s/%s: %s\n"), 941 progname, directory, tofield, e); 942 exit(EXIT_FAILURE); 943 } 944 while ((c = getc(fp)) != EOF) 945 putc(c, tp); 946 close_file(fp, directory, fromfield); 947 close_file(tp, directory, tofield); 948 if (link_errno != ENOTSUP) 949 warning(_("copy used because hard link failed: %s"), 950 strerror(link_errno)); 951 else if (symlink_errno != ENOTSUP) 952 warning(_("copy used because symbolic link failed: %s"), 953 strerror(symlink_errno)); 954 } 955 } 956 } 957 958 #define TIME_T_BITS_IN_FILE 64 959 960 static zic_t const min_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE); 961 static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE); 962 963 /* Estimated time of the Big Bang, in seconds since the POSIX epoch. 964 rounded downward to the negation of a power of two that is 965 comfortably outside the error bounds. 966 967 For the time of the Big Bang, see: 968 969 Ade PAR, Aghanim N, Armitage-Caplan C et al. Planck 2013 results. 970 I. Overview of products and scientific results. 971 arXiv:1303.5062 2013-03-20 20:10:01 UTC 972 <https://arxiv.org/pdf/1303.5062v1> [PDF] 973 974 Page 36, Table 9, row Age/Gyr, column Planck+WP+highL+BAO 68% limits 975 gives the value 13.798 plus-or-minus 0.037 billion years. 976 Multiplying this by 1000000000 and then by 31557600 (the number of 977 seconds in an astronomical year) gives a value that is comfortably 978 less than 2**59, so BIG_BANG is - 2**59. 979 980 BIG_BANG is approximate, and may change in future versions. 981 Please do not rely on its exact value. */ 982 983 #ifndef BIG_BANG 984 #define BIG_BANG (- (1LL << 59)) 985 #endif 986 987 /* If true, work around GNOME bug 730332 988 <https://bugzilla.gnome.org/show_bug.cgi?id=730332> 989 by refusing to output time stamps before BIG_BANG. 990 Such time stamps are physically suspect anyway. 991 992 The GNOME bug is scheduled to be fixed in GNOME 3.22, and if so 993 this workaround will no longer be needed when GNOME 3.21 and 994 earlier are obsolete, say in the year 2021. */ 995 enum { WORK_AROUND_GNOME_BUG_730332 = true }; 996 997 static const zic_t early_time = (WORK_AROUND_GNOME_BUG_730332 998 ? BIG_BANG 999 : MINVAL(zic_t, TIME_T_BITS_IN_FILE)); 1000 1001 /* Return true if NAME is a directory. */ 1002 static bool 1003 itsdir(const char *name) 1004 { 1005 struct stat st; 1006 int res = stat(name, &st); 1007 #ifdef S_ISDIR 1008 if (res == 0) 1009 return S_ISDIR(st.st_mode) != 0; 1010 #endif 1011 if (res == 0 || errno == EOVERFLOW) { 1012 size_t n = strlen(name); 1013 char *nameslashdot = emalloc(n + 3); 1014 bool dir; 1015 memcpy(nameslashdot, name, n); 1016 strcpy(&nameslashdot[n], &"/."[! (n && name[n - 1] != '/')]); 1017 dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW; 1018 free(nameslashdot); 1019 return dir; 1020 } 1021 return false; 1022 } 1023 1024 /* Return true if NAME is a symbolic link. */ 1025 static bool 1026 itssymlink(char const *name) 1027 { 1028 char c; 1029 return 0 <= readlink(name, &c, 1); 1030 } 1031 1032 /* 1033 ** Associate sets of rules with zones. 1034 */ 1035 1036 /* 1037 ** Sort by rule name. 1038 */ 1039 1040 static int 1041 rcomp(const void *cp1, const void *cp2) 1042 { 1043 return strcmp(((const struct rule *) cp1)->r_name, 1044 ((const struct rule *) cp2)->r_name); 1045 } 1046 1047 static void 1048 associate(void) 1049 { 1050 struct zone * zp; 1051 struct rule * rp; 1052 ptrdiff_t base, out; 1053 int i, j; 1054 1055 if (nrules != 0) { 1056 qsort(rules, (size_t)nrules, sizeof *rules, rcomp); 1057 for (i = 0; i < nrules - 1; ++i) { 1058 if (strcmp(rules[i].r_name, 1059 rules[i + 1].r_name) != 0) 1060 continue; 1061 if (strcmp(rules[i].r_filename, 1062 rules[i + 1].r_filename) == 0) 1063 continue; 1064 eat(rules[i].r_filename, rules[i].r_linenum); 1065 warning(_("same rule name in multiple files")); 1066 eat(rules[i + 1].r_filename, rules[i + 1].r_linenum); 1067 warning(_("same rule name in multiple files")); 1068 for (j = i + 2; j < nrules; ++j) { 1069 if (strcmp(rules[i].r_name, 1070 rules[j].r_name) != 0) 1071 break; 1072 if (strcmp(rules[i].r_filename, 1073 rules[j].r_filename) == 0) 1074 continue; 1075 if (strcmp(rules[i + 1].r_filename, 1076 rules[j].r_filename) == 0) 1077 continue; 1078 break; 1079 } 1080 i = j - 1; 1081 } 1082 } 1083 for (i = 0; i < nzones; ++i) { 1084 zp = &zones[i]; 1085 zp->z_rules = NULL; 1086 zp->z_nrules = 0; 1087 } 1088 for (base = 0; base < nrules; base = out) { 1089 rp = &rules[base]; 1090 for (out = base + 1; out < nrules; ++out) 1091 if (strcmp(rp->r_name, rules[out].r_name) != 0) 1092 break; 1093 for (i = 0; i < nzones; ++i) { 1094 zp = &zones[i]; 1095 if (strcmp(zp->z_rule, rp->r_name) != 0) 1096 continue; 1097 zp->z_rules = rp; 1098 zp->z_nrules = out - base; 1099 } 1100 } 1101 for (i = 0; i < nzones; ++i) { 1102 zp = &zones[i]; 1103 if (zp->z_nrules == 0) { 1104 /* 1105 ** Maybe we have a local standard time offset. 1106 */ 1107 eat(zp->z_filename, zp->z_linenum); 1108 zp->z_stdoff = getstdoff(zp->z_rule, &zp->z_isdst); 1109 /* 1110 ** Note, though, that if there's no rule, 1111 ** a '%s' in the format is a bad thing. 1112 */ 1113 if (zp->z_format_specifier == 's') 1114 error("%s", _("%s in ruleless zone")); 1115 } 1116 } 1117 if (errors) 1118 exit(EXIT_FAILURE); 1119 } 1120 1121 static void 1122 infile(const char *name) 1123 { 1124 FILE * fp; 1125 char ** fields; 1126 char * cp; 1127 const struct lookup * lp; 1128 int nfields; 1129 bool wantcont; 1130 lineno num; 1131 char buf[BUFSIZ]; 1132 1133 if (strcmp(name, "-") == 0) { 1134 name = _("standard input"); 1135 fp = stdin; 1136 } else if ((fp = fopen(name, "r")) == NULL) { 1137 const char *e = strerror(errno); 1138 1139 fprintf(stderr, _("%s: Can't open %s: %s\n"), 1140 progname, name, e); 1141 exit(EXIT_FAILURE); 1142 } 1143 wantcont = false; 1144 for (num = 1; ; ++num) { 1145 eat(name, num); 1146 if (fgets(buf, (int) sizeof buf, fp) != buf) 1147 break; 1148 cp = strchr(buf, '\n'); 1149 if (cp == NULL) { 1150 error(_("line too long")); 1151 exit(EXIT_FAILURE); 1152 } 1153 *cp = '\0'; 1154 fields = getfields(buf); 1155 nfields = 0; 1156 while (fields[nfields] != NULL) { 1157 static char nada; 1158 1159 if (strcmp(fields[nfields], "-") == 0) 1160 fields[nfields] = &nada; 1161 ++nfields; 1162 } 1163 if (nfields == 0) { 1164 /* nothing to do */ 1165 } else if (wantcont) { 1166 wantcont = inzcont(fields, nfields); 1167 } else { 1168 struct lookup const *line_codes 1169 = name == leapsec ? leap_line_codes : zi_line_codes; 1170 lp = byword(fields[0], line_codes); 1171 if (lp == NULL) 1172 error(_("input line of unknown type")); 1173 else switch (lp->l_value) { 1174 case LC_RULE: 1175 inrule(fields, nfields); 1176 wantcont = false; 1177 break; 1178 case LC_ZONE: 1179 wantcont = inzone(fields, nfields); 1180 break; 1181 case LC_LINK: 1182 inlink(fields, nfields); 1183 wantcont = false; 1184 break; 1185 case LC_LEAP: 1186 inleap(fields, nfields); 1187 wantcont = false; 1188 break; 1189 default: /* "cannot happen" */ 1190 fprintf(stderr, 1191 _("%s: panic: Invalid l_value %d\n"), 1192 progname, lp->l_value); 1193 exit(EXIT_FAILURE); 1194 } 1195 } 1196 free(fields); 1197 } 1198 close_file(fp, NULL, filename); 1199 if (wantcont) 1200 error(_("expected continuation line not found")); 1201 } 1202 1203 /* 1204 ** Convert a string of one of the forms 1205 ** h -h hh:mm -hh:mm hh:mm:ss -hh:mm:ss 1206 ** into a number of seconds. 1207 ** A null string maps to zero. 1208 ** Call error with errstring and return zero on errors. 1209 */ 1210 1211 static zic_t 1212 gethms(char const *string, char const *errstring, bool signable) 1213 { 1214 zic_t hh; 1215 int sign, mm = 0, ss = 0; 1216 char hhx, mmx, ssx, xr = '0', xs; 1217 int tenths = 0; 1218 bool ok = true; 1219 1220 if (string == NULL || *string == '\0') 1221 return 0; 1222 if (!signable) 1223 sign = 1; 1224 else if (*string == '-') { 1225 sign = -1; 1226 ++string; 1227 } else sign = 1; 1228 switch (sscanf(string, 1229 "%"SCNdZIC"%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c", 1230 &hh, &hhx, &mm, &mmx, &ss, &ssx, &tenths, &xr, &xs)) { 1231 default: ok = false; break; 1232 case 8: 1233 ok = '0' <= xr && xr <= '9'; 1234 /* fallthrough */ 1235 case 7: 1236 ok &= ssx == '.'; 1237 if (ok && noise) 1238 warning(_("fractional seconds rejected by" 1239 " pre-2018 versions of zic")); 1240 /* fallthrough */ 1241 case 5: ok &= mmx == ':'; /* fallthrough */ 1242 case 3: ok &= hhx == ':'; /* fallthrough */ 1243 case 1: break; 1244 } 1245 if (!ok) { 1246 error("%s", errstring); 1247 return 0; 1248 } 1249 if (hh < 0 || 1250 mm < 0 || mm >= MINSPERHOUR || 1251 ss < 0 || ss > SECSPERMIN) { 1252 error("%s", errstring); 1253 return 0; 1254 } 1255 if (ZIC_MAX / SECSPERHOUR < hh) { 1256 error(_("time overflow")); 1257 return 0; 1258 } 1259 ss += 5 + ((ss ^ 1) & (xr == '0')) <= tenths; /* Round to even. */ 1260 if (noise && (hh > HOURSPERDAY || 1261 (hh == HOURSPERDAY && (mm != 0 || ss != 0)))) 1262 warning(_("values over 24 hours not handled by pre-2007 versions of zic")); 1263 return oadd(sign * hh * SECSPERHOUR, 1264 sign * (mm * SECSPERMIN + ss)); 1265 } 1266 1267 static zic_t 1268 getstdoff(char *field, bool *isdst) 1269 { 1270 int dst = -1; 1271 zic_t stdoff; 1272 size_t fieldlen = strlen(field); 1273 if (fieldlen != 0) { 1274 char *ep = field + fieldlen - 1; 1275 switch (*ep) { 1276 case 'd': dst = 1; *ep = '\0'; break; 1277 case 's': dst = 0; *ep = '\0'; break; 1278 } 1279 } 1280 stdoff = gethms(field, _("invalid saved time"), true); 1281 *isdst = dst < 0 ? stdoff != 0 : dst; 1282 return stdoff; 1283 } 1284 1285 static void 1286 inrule(char **fields, int nfields) 1287 { 1288 static struct rule r; 1289 1290 if (nfields != RULE_FIELDS) { 1291 error(_("wrong number of fields on Rule line")); 1292 return; 1293 } 1294 if (*fields[RF_NAME] == '\0') { 1295 error(_("nameless rule")); 1296 return; 1297 } 1298 r.r_filename = filename; 1299 r.r_linenum = linenum; 1300 r.r_stdoff = getstdoff(fields[RF_STDOFF], &r.r_isdst); 1301 rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND], 1302 fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]); 1303 r.r_name = ecpyalloc(fields[RF_NAME]); 1304 r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]); 1305 if (max_abbrvar_len < strlen(r.r_abbrvar)) 1306 max_abbrvar_len = strlen(r.r_abbrvar); 1307 rules = growalloc(rules, sizeof *rules, nrules, &nrules_alloc); 1308 rules[nrules++] = r; 1309 } 1310 1311 static bool 1312 inzone(char **fields, int nfields) 1313 { 1314 ptrdiff_t i; 1315 1316 if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) { 1317 error(_("wrong number of fields on Zone line")); 1318 return false; 1319 } 1320 if (lcltime != NULL && strcmp(fields[ZF_NAME], tzdefault) == 0) { 1321 error( 1322 _("\"Zone %s\" line and -l option are mutually exclusive"), 1323 tzdefault); 1324 return false; 1325 } 1326 if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) { 1327 error( 1328 _("\"Zone %s\" line and -p option are mutually exclusive"), 1329 TZDEFRULES); 1330 return false; 1331 } 1332 for (i = 0; i < nzones; ++i) 1333 if (zones[i].z_name != NULL && 1334 strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) { 1335 error(_("duplicate zone name %s" 1336 " (file \"%s\", line %"PRIdMAX")"), 1337 fields[ZF_NAME], 1338 zones[i].z_filename, 1339 zones[i].z_linenum); 1340 return false; 1341 } 1342 return inzsub(fields, nfields, false); 1343 } 1344 1345 static bool 1346 inzcont(char **fields, int nfields) 1347 { 1348 if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) { 1349 error(_("wrong number of fields on Zone continuation line")); 1350 return false; 1351 } 1352 return inzsub(fields, nfields, true); 1353 } 1354 1355 static bool 1356 inzsub(char **fields, int nfields, const int iscont) 1357 { 1358 char * cp; 1359 char * cp1; 1360 static struct zone z; 1361 int i_gmtoff, i_rule, i_format; 1362 int i_untilyear, i_untilmonth; 1363 int i_untilday, i_untiltime; 1364 bool hasuntil; 1365 1366 if (iscont) { 1367 i_gmtoff = ZFC_GMTOFF; 1368 i_rule = ZFC_RULE; 1369 i_format = ZFC_FORMAT; 1370 i_untilyear = ZFC_TILYEAR; 1371 i_untilmonth = ZFC_TILMONTH; 1372 i_untilday = ZFC_TILDAY; 1373 i_untiltime = ZFC_TILTIME; 1374 z.z_name = NULL; 1375 } else if (!namecheck(fields[ZF_NAME])) 1376 return false; 1377 else { 1378 i_gmtoff = ZF_GMTOFF; 1379 i_rule = ZF_RULE; 1380 i_format = ZF_FORMAT; 1381 i_untilyear = ZF_TILYEAR; 1382 i_untilmonth = ZF_TILMONTH; 1383 i_untilday = ZF_TILDAY; 1384 i_untiltime = ZF_TILTIME; 1385 z.z_name = ecpyalloc(fields[ZF_NAME]); 1386 } 1387 z.z_filename = filename; 1388 z.z_linenum = linenum; 1389 z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UT offset"), true); 1390 if ((cp = strchr(fields[i_format], '%')) != 0) { 1391 if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%') 1392 || strchr(fields[i_format], '/')) { 1393 error(_("invalid abbreviation format")); 1394 return false; 1395 } 1396 } 1397 z.z_rule = ecpyalloc(fields[i_rule]); 1398 z.z_format = cp1 = ecpyalloc(fields[i_format]); 1399 z.z_format_specifier = cp ? *cp : '\0'; 1400 if (z.z_format_specifier == 'z') { 1401 if (noise) 1402 warning(_("format '%s' not handled by pre-2015 versions of zic"), 1403 z.z_format); 1404 cp1[cp - fields[i_format]] = 's'; 1405 } 1406 if (max_format_len < strlen(z.z_format)) 1407 max_format_len = strlen(z.z_format); 1408 hasuntil = nfields > i_untilyear; 1409 if (hasuntil) { 1410 z.z_untilrule.r_filename = filename; 1411 z.z_untilrule.r_linenum = linenum; 1412 rulesub(&z.z_untilrule, 1413 fields[i_untilyear], 1414 "only", 1415 "", 1416 (nfields > i_untilmonth) ? 1417 fields[i_untilmonth] : "Jan", 1418 (nfields > i_untilday) ? fields[i_untilday] : "1", 1419 (nfields > i_untiltime) ? fields[i_untiltime] : "0"); 1420 z.z_untiltime = rpytime(&z.z_untilrule, 1421 z.z_untilrule.r_loyear); 1422 if (iscont && nzones > 0 && 1423 z.z_untiltime > min_time && 1424 z.z_untiltime < max_time && 1425 zones[nzones - 1].z_untiltime > min_time && 1426 zones[nzones - 1].z_untiltime < max_time && 1427 zones[nzones - 1].z_untiltime >= z.z_untiltime) { 1428 error(_( 1429 "Zone continuation line end time is not after end time of previous line" 1430 )); 1431 return false; 1432 } 1433 } 1434 zones = growalloc(zones, sizeof *zones, nzones, &nzones_alloc); 1435 zones[nzones++] = z; 1436 /* 1437 ** If there was an UNTIL field on this line, 1438 ** there's more information about the zone on the next line. 1439 */ 1440 return hasuntil; 1441 } 1442 1443 static void 1444 inleap(char **fields, int nfields) 1445 { 1446 const char * cp; 1447 const struct lookup * lp; 1448 zic_t i, j; 1449 zic_t year; 1450 int month, day; 1451 zic_t dayoff, tod; 1452 zic_t t; 1453 char xs; 1454 1455 if (nfields != LEAP_FIELDS) { 1456 error(_("wrong number of fields on Leap line")); 1457 return; 1458 } 1459 dayoff = 0; 1460 cp = fields[LP_YEAR]; 1461 if (sscanf(cp, "%"SCNdZIC"%c", &year, &xs) != 1) { 1462 /* 1463 ** Leapin' Lizards! 1464 */ 1465 error(_("invalid leaping year")); 1466 return; 1467 } 1468 if (!leapseen || leapmaxyear < year) 1469 leapmaxyear = year; 1470 if (!leapseen || leapminyear > year) 1471 leapminyear = year; 1472 leapseen = true; 1473 j = EPOCH_YEAR; 1474 while (j != year) { 1475 if (year > j) { 1476 i = len_years[isleap(j)]; 1477 ++j; 1478 } else { 1479 --j; 1480 i = -len_years[isleap(j)]; 1481 } 1482 dayoff = oadd(dayoff, i); 1483 } 1484 if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) { 1485 error(_("invalid month name")); 1486 return; 1487 } 1488 month = lp->l_value; 1489 j = TM_JANUARY; 1490 while (j != month) { 1491 i = len_months[isleap(year)][j]; 1492 dayoff = oadd(dayoff, i); 1493 ++j; 1494 } 1495 cp = fields[LP_DAY]; 1496 if (sscanf(cp, "%d%c", &day, &xs) != 1 || 1497 day <= 0 || day > len_months[isleap(year)][month]) { 1498 error(_("invalid day of month")); 1499 return; 1500 } 1501 dayoff = oadd(dayoff, day - 1); 1502 if (dayoff < min_time / SECSPERDAY) { 1503 error(_("time too small")); 1504 return; 1505 } 1506 if (dayoff > max_time / SECSPERDAY) { 1507 error(_("time too large")); 1508 return; 1509 } 1510 t = dayoff * SECSPERDAY; 1511 tod = gethms(fields[LP_TIME], _("invalid time of day"), false); 1512 cp = fields[LP_CORR]; 1513 { 1514 bool positive; 1515 int count; 1516 1517 if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */ 1518 positive = false; 1519 count = 1; 1520 } else if (strcmp(cp, "+") == 0) { 1521 positive = true; 1522 count = 1; 1523 } else { 1524 error(_("illegal CORRECTION field on Leap line")); 1525 return; 1526 } 1527 if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) { 1528 error(_( 1529 "illegal Rolling/Stationary field on Leap line" 1530 )); 1531 return; 1532 } 1533 t = tadd(t, tod); 1534 if (t < 0) { 1535 error(_("leap second precedes Epoch")); 1536 return; 1537 } 1538 leapadd(t, positive, lp->l_value, count); 1539 } 1540 } 1541 1542 static void 1543 inlink(char **fields, int nfields) 1544 { 1545 struct link l; 1546 1547 if (nfields != LINK_FIELDS) { 1548 error(_("wrong number of fields on Link line")); 1549 return; 1550 } 1551 if (*fields[LF_FROM] == '\0') { 1552 error(_("blank FROM field on Link line")); 1553 return; 1554 } 1555 if (! namecheck(fields[LF_TO])) 1556 return; 1557 l.l_filename = filename; 1558 l.l_linenum = linenum; 1559 l.l_from = ecpyalloc(fields[LF_FROM]); 1560 l.l_to = ecpyalloc(fields[LF_TO]); 1561 links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc); 1562 links[nlinks++] = l; 1563 } 1564 1565 static void 1566 rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, 1567 const char *typep, const char *monthp, const char *dayp, 1568 const char *timep) 1569 { 1570 const struct lookup * lp; 1571 const char * cp; 1572 char * dp; 1573 char * ep; 1574 char xs; 1575 1576 if ((lp = byword(monthp, mon_names)) == NULL) { 1577 error(_("invalid month name")); 1578 return; 1579 } 1580 rp->r_month = lp->l_value; 1581 rp->r_todisstd = false; 1582 rp->r_todisgmt = false; 1583 dp = ecpyalloc(timep); 1584 if (*dp != '\0') { 1585 ep = dp + strlen(dp) - 1; 1586 switch (lowerit(*ep)) { 1587 case 's': /* Standard */ 1588 rp->r_todisstd = true; 1589 rp->r_todisgmt = false; 1590 *ep = '\0'; 1591 break; 1592 case 'w': /* Wall */ 1593 rp->r_todisstd = false; 1594 rp->r_todisgmt = false; 1595 *ep = '\0'; 1596 break; 1597 case 'g': /* Greenwich */ 1598 case 'u': /* Universal */ 1599 case 'z': /* Zulu */ 1600 rp->r_todisstd = true; 1601 rp->r_todisgmt = true; 1602 *ep = '\0'; 1603 break; 1604 } 1605 } 1606 rp->r_tod = gethms(dp, _("invalid time of day"), false); 1607 free(dp); 1608 /* 1609 ** Year work. 1610 */ 1611 cp = loyearp; 1612 lp = byword(cp, begin_years); 1613 rp->r_lowasnum = lp == NULL; 1614 if (!rp->r_lowasnum) switch (lp->l_value) { 1615 case YR_MINIMUM: 1616 rp->r_loyear = ZIC_MIN; 1617 break; 1618 case YR_MAXIMUM: 1619 rp->r_loyear = ZIC_MAX; 1620 break; 1621 default: /* "cannot happen" */ 1622 fprintf(stderr, 1623 _("%s: panic: Invalid l_value %d\n"), 1624 progname, lp->l_value); 1625 exit(EXIT_FAILURE); 1626 } else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_loyear, &xs) != 1) { 1627 error(_("invalid starting year")); 1628 return; 1629 } 1630 cp = hiyearp; 1631 lp = byword(cp, end_years); 1632 rp->r_hiwasnum = lp == NULL; 1633 if (!rp->r_hiwasnum) switch (lp->l_value) { 1634 case YR_MINIMUM: 1635 rp->r_hiyear = ZIC_MIN; 1636 break; 1637 case YR_MAXIMUM: 1638 rp->r_hiyear = ZIC_MAX; 1639 break; 1640 case YR_ONLY: 1641 rp->r_hiyear = rp->r_loyear; 1642 break; 1643 default: /* "cannot happen" */ 1644 fprintf(stderr, 1645 _("%s: panic: Invalid l_value %d\n"), 1646 progname, lp->l_value); 1647 exit(EXIT_FAILURE); 1648 } else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_hiyear, &xs) != 1) { 1649 error(_("invalid ending year")); 1650 return; 1651 } 1652 if (rp->r_loyear > rp->r_hiyear) { 1653 error(_("starting year greater than ending year")); 1654 return; 1655 } 1656 if (*typep == '\0') 1657 rp->r_yrtype = NULL; 1658 else { 1659 if (rp->r_loyear == rp->r_hiyear) { 1660 error(_("typed single year")); 1661 return; 1662 } 1663 warning(_("year type \"%s\" is obsolete; use \"-\" instead"), 1664 typep); 1665 rp->r_yrtype = ecpyalloc(typep); 1666 } 1667 /* 1668 ** Day work. 1669 ** Accept things such as: 1670 ** 1 1671 ** lastSunday 1672 ** last-Sunday (undocumented; warn about this) 1673 ** Sun<=20 1674 ** Sun>=7 1675 */ 1676 dp = ecpyalloc(dayp); 1677 if ((lp = byword(dp, lasts)) != NULL) { 1678 rp->r_dycode = DC_DOWLEQ; 1679 rp->r_wday = lp->l_value; 1680 rp->r_dayofmonth = len_months[1][rp->r_month]; 1681 } else { 1682 if ((ep = strchr(dp, '<')) != 0) 1683 rp->r_dycode = DC_DOWLEQ; 1684 else if ((ep = strchr(dp, '>')) != 0) 1685 rp->r_dycode = DC_DOWGEQ; 1686 else { 1687 ep = dp; 1688 rp->r_dycode = DC_DOM; 1689 } 1690 if (rp->r_dycode != DC_DOM) { 1691 *ep++ = 0; 1692 if (*ep++ != '=') { 1693 error(_("invalid day of month")); 1694 free(dp); 1695 return; 1696 } 1697 if ((lp = byword(dp, wday_names)) == NULL) { 1698 error(_("invalid weekday name")); 1699 free(dp); 1700 return; 1701 } 1702 rp->r_wday = lp->l_value; 1703 } 1704 if (sscanf(ep, "%d%c", &rp->r_dayofmonth, &xs) != 1 || 1705 rp->r_dayofmonth <= 0 || 1706 (rp->r_dayofmonth > len_months[1][rp->r_month])) { 1707 error(_("invalid day of month")); 1708 free(dp); 1709 return; 1710 } 1711 } 1712 free(dp); 1713 } 1714 1715 static void 1716 convert(const zic_t val, char *const buf) 1717 { 1718 int i; 1719 int shift; 1720 unsigned char *const b = (unsigned char *) buf; 1721 1722 for (i = 0, shift = 24; i < 4; ++i, shift -= 8) 1723 b[i] = val >> shift; 1724 } 1725 1726 static void 1727 convert64(const zic_t val, char *const buf) 1728 { 1729 int i; 1730 int shift; 1731 unsigned char *const b = (unsigned char *) buf; 1732 1733 for (i = 0, shift = 56; i < 8; ++i, shift -= 8) 1734 b[i] = val >> shift; 1735 } 1736 1737 static void 1738 puttzcode(const zic_t val, FILE *const fp) 1739 { 1740 char buf[4]; 1741 1742 convert(val, buf); 1743 fwrite(buf, sizeof buf, (size_t) 1, fp); 1744 } 1745 1746 static void 1747 puttzcode64(const zic_t val, FILE *const fp) 1748 { 1749 char buf[8]; 1750 1751 convert64(val, buf); 1752 fwrite(buf, sizeof buf, (size_t) 1, fp); 1753 } 1754 1755 static int 1756 atcomp(const void *avp, const void *bvp) 1757 { 1758 const zic_t a = ((const struct attype *) avp)->at; 1759 const zic_t b = ((const struct attype *) bvp)->at; 1760 1761 return (a < b) ? -1 : (a > b); 1762 } 1763 1764 static bool 1765 is32(const zic_t x) 1766 { 1767 return INT32_MIN <= x && x <= INT32_MAX; 1768 } 1769 1770 static void 1771 writezone(const char *const name, const char *const string, char version) 1772 { 1773 FILE * fp; 1774 ptrdiff_t i, j; 1775 int leapcnt32, leapi32; 1776 ptrdiff_t timecnt32, timei32; 1777 int pass; 1778 static const struct tzhead tzh0; 1779 static struct tzhead tzh; 1780 bool dir_checked = false; 1781 zic_t one = 1; 1782 zic_t y2038_boundary = one << 31; 1783 ptrdiff_t nats = timecnt + WORK_AROUND_QTBUG_53071; 1784 zic_t *ats = zic_malloc(size_product(nats, sizeof *ats + 1)); 1785 void *typesptr = ats + nats; 1786 unsigned char *types = typesptr; 1787 1788 /* 1789 ** Sort. 1790 */ 1791 if (timecnt > 1) 1792 qsort(attypes, (size_t) timecnt, sizeof *attypes, atcomp); 1793 /* 1794 ** Optimize. 1795 */ 1796 { 1797 ptrdiff_t fromi, toi; 1798 1799 toi = 0; 1800 fromi = 0; 1801 while (fromi < timecnt && attypes[fromi].at < early_time) 1802 ++fromi; 1803 for ( ; fromi < timecnt; ++fromi) { 1804 if (toi > 1 && ((attypes[fromi].at + 1805 gmtoffs[attypes[toi - 1].type]) <= 1806 (attypes[toi - 1].at + 1807 gmtoffs[attypes[toi - 2].type]))) { 1808 attypes[toi - 1].type = 1809 attypes[fromi].type; 1810 continue; 1811 } 1812 if (toi == 0 1813 || attypes[fromi].dontmerge 1814 || attypes[toi - 1].type != attypes[fromi].type) 1815 attypes[toi++] = attypes[fromi]; 1816 } 1817 timecnt = toi; 1818 } 1819 1820 if (noise && timecnt > 1200) { 1821 if (timecnt > TZ_MAX_TIMES) 1822 warning(_("reference clients mishandle" 1823 " more than %d transition times"), 1824 TZ_MAX_TIMES); 1825 else 1826 warning(_("pre-2014 clients may mishandle" 1827 " more than 1200 transition times")); 1828 } 1829 /* 1830 ** Transfer. 1831 */ 1832 for (i = 0; i < timecnt; ++i) { 1833 ats[i] = attypes[i].at; 1834 types[i] = attypes[i].type; 1835 } 1836 1837 /* Work around QTBUG-53071 for time stamps less than y2038_boundary - 1, 1838 by inserting a no-op transition at time y2038_boundary - 1. 1839 This works only for timestamps before the boundary, which 1840 should be good enough in practice as QTBUG-53071 should be 1841 long-dead by 2038. */ 1842 if (WORK_AROUND_QTBUG_53071 && timecnt != 0 1843 && ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<')) { 1844 ats[timecnt] = y2038_boundary - 1; 1845 types[timecnt] = types[timecnt - 1]; 1846 timecnt++; 1847 } 1848 1849 /* 1850 ** Correct for leap seconds. 1851 */ 1852 for (i = 0; i < timecnt; ++i) { 1853 j = leapcnt; 1854 while (--j >= 0) 1855 if (ats[i] > trans[j] - corr[j]) { 1856 ats[i] = tadd(ats[i], corr[j]); 1857 break; 1858 } 1859 } 1860 /* 1861 ** Figure out 32-bit-limited starts and counts. 1862 */ 1863 timecnt32 = timecnt; 1864 timei32 = 0; 1865 leapcnt32 = leapcnt; 1866 leapi32 = 0; 1867 while (timecnt32 > 0 && !is32(ats[timecnt32 - 1])) 1868 --timecnt32; 1869 while (timecnt32 > 0 && !is32(ats[timei32])) { 1870 --timecnt32; 1871 ++timei32; 1872 } 1873 /* 1874 ** Output an INT32_MIN "transition" if appropriate; see below. 1875 */ 1876 if (timei32 > 0 && ats[timei32] > INT32_MIN) { 1877 --timei32; 1878 ++timecnt32; 1879 } 1880 while (leapcnt32 > 0 && !is32(trans[leapcnt32 - 1])) 1881 --leapcnt32; 1882 while (leapcnt32 > 0 && !is32(trans[leapi32])) { 1883 --leapcnt32; 1884 ++leapi32; 1885 } 1886 /* 1887 ** Remove old file, if any, to snap links. 1888 */ 1889 if (remove(name) == 0) 1890 dir_checked = true; 1891 else if (errno != ENOENT) { 1892 const char *e = strerror(errno); 1893 1894 fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"), 1895 progname, directory, name, e); 1896 exit(EXIT_FAILURE); 1897 } 1898 fp = fopen(name, "wb"); 1899 if (!fp) { 1900 int fopen_errno = errno; 1901 if (fopen_errno == ENOENT && !dir_checked) { 1902 mkdirs(name, true); 1903 fp = fopen(name, "wb"); 1904 fopen_errno = errno; 1905 } 1906 if (!fp) { 1907 fprintf(stderr, _("%s: Can't create %s/%s: %s\n"), 1908 progname, directory, name, strerror(fopen_errno)); 1909 exit(EXIT_FAILURE); 1910 } 1911 } 1912 for (pass = 1; pass <= 2; ++pass) { 1913 ptrdiff_t thistimei, thistimecnt, thistimelim; 1914 int thisleapi, thisleapcnt, thisleaplim; 1915 int writetype[TZ_MAX_TYPES]; 1916 int typemap[TZ_MAX_TYPES]; 1917 int thistypecnt; 1918 char thischars[TZ_MAX_CHARS]; 1919 int thischarcnt; 1920 bool toomanytimes; 1921 int indmap[TZ_MAX_CHARS]; 1922 1923 if (pass == 1) { 1924 thistimei = timei32; 1925 thistimecnt = timecnt32; 1926 toomanytimes = thistimecnt >> 31 >> 1 != 0; 1927 thisleapi = leapi32; 1928 thisleapcnt = leapcnt32; 1929 } else { 1930 thistimei = 0; 1931 thistimecnt = timecnt; 1932 toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0; 1933 thisleapi = 0; 1934 thisleapcnt = leapcnt; 1935 } 1936 if (toomanytimes) 1937 error(_("too many transition times")); 1938 thistimelim = thistimei + thistimecnt; 1939 thisleaplim = thisleapi + thisleapcnt; 1940 for (i = 0; i < typecnt; ++i) 1941 writetype[i] = thistimecnt == timecnt; 1942 if (thistimecnt == 0) { 1943 /* 1944 ** No transition times fall in the current 1945 ** (32- or 64-bit) window. 1946 */ 1947 if (typecnt != 0) 1948 writetype[typecnt - 1] = true; 1949 } else { 1950 for (i = thistimei - 1; i < thistimelim; ++i) 1951 if (i >= 0) 1952 writetype[types[i]] = true; 1953 /* 1954 ** For America/Godthab and Antarctica/Palmer 1955 */ 1956 if (thistimei == 0) 1957 writetype[0] = true; 1958 } 1959 #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH 1960 /* 1961 ** For some pre-2011 systems: if the last-to-be-written 1962 ** standard (or daylight) type has an offset different from the 1963 ** most recently used offset, 1964 ** append an (unused) copy of the most recently used type 1965 ** (to help get global "altzone" and "timezone" variables 1966 ** set correctly). 1967 */ 1968 { 1969 int mrudst, mrustd, hidst, histd, type; 1970 1971 hidst = histd = mrudst = mrustd = -1; 1972 for (i = thistimei; i < thistimelim; ++i) { 1973 if (i < 0) 1974 continue; 1975 if (isdsts[types[i]]) 1976 mrudst = types[i]; 1977 else mrustd = types[i]; 1978 } 1979 for (i = 0; i < typecnt; ++i) 1980 if (writetype[i]) { 1981 if (isdsts[i]) 1982 hidst = i; 1983 else histd = i; 1984 } 1985 if (hidst >= 0 && mrudst >= 0 && hidst != mrudst && 1986 gmtoffs[hidst] != gmtoffs[mrudst]) { 1987 isdsts[mrudst] = -1; 1988 type = addtype(gmtoffs[mrudst], 1989 &chars[abbrinds[mrudst]], 1990 true, 1991 ttisstds[mrudst], 1992 ttisgmts[mrudst]); 1993 isdsts[mrudst] = 1; 1994 writetype[type] = true; 1995 } 1996 if (histd >= 0 && mrustd >= 0 && histd != mrustd && 1997 gmtoffs[histd] != gmtoffs[mrustd]) { 1998 isdsts[mrustd] = -1; 1999 type = addtype(gmtoffs[mrustd], 2000 &chars[abbrinds[mrustd]], 2001 false, 2002 ttisstds[mrustd], 2003 ttisgmts[mrustd]); 2004 isdsts[mrustd] = 0; 2005 writetype[type] = true; 2006 } 2007 } 2008 #endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */ 2009 thistypecnt = 0; 2010 for (i = 0; i < typecnt; ++i) 2011 typemap[i] = writetype[i] ? thistypecnt++ : -1; 2012 for (i = 0; i < (int)(sizeof indmap / sizeof indmap[0]); ++i) 2013 indmap[i] = -1; 2014 thischarcnt = 0; 2015 for (i = 0; i < typecnt; ++i) { 2016 char * thisabbr; 2017 2018 if (!writetype[i]) 2019 continue; 2020 if (indmap[abbrinds[i]] >= 0) 2021 continue; 2022 thisabbr = &chars[abbrinds[i]]; 2023 for (j = 0; j < thischarcnt; ++j) 2024 if (strcmp(&thischars[j], thisabbr) == 0) 2025 break; 2026 if (j == thischarcnt) { 2027 strcpy(&thischars[thischarcnt], thisabbr); 2028 thischarcnt += strlen(thisabbr) + 1; 2029 } 2030 indmap[abbrinds[i]] = j; 2031 } 2032 #define DO(field) fwrite(tzh.field, sizeof tzh.field, (size_t) 1, fp) 2033 tzh = tzh0; 2034 memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); 2035 tzh.tzh_version[0] = version; 2036 convert(thistypecnt, tzh.tzh_ttisgmtcnt); 2037 convert(thistypecnt, tzh.tzh_ttisstdcnt); 2038 convert(thisleapcnt, tzh.tzh_leapcnt); 2039 convert(thistimecnt, tzh.tzh_timecnt); 2040 convert(thistypecnt, tzh.tzh_typecnt); 2041 convert(thischarcnt, tzh.tzh_charcnt); 2042 DO(tzh_magic); 2043 DO(tzh_version); 2044 DO(tzh_reserved); 2045 DO(tzh_ttisgmtcnt); 2046 DO(tzh_ttisstdcnt); 2047 DO(tzh_leapcnt); 2048 DO(tzh_timecnt); 2049 DO(tzh_typecnt); 2050 DO(tzh_charcnt); 2051 #undef DO 2052 for (i = thistimei; i < thistimelim; ++i) 2053 if (pass == 1) 2054 /* 2055 ** Output an INT32_MIN "transition" 2056 ** if appropriate; see above. 2057 */ 2058 puttzcode(((ats[i] < INT32_MIN) ? 2059 INT32_MIN : ats[i]), fp); 2060 else puttzcode64(ats[i], fp); 2061 for (i = thistimei; i < thistimelim; ++i) { 2062 unsigned char uc; 2063 2064 uc = typemap[types[i]]; 2065 fwrite(&uc, sizeof uc, (size_t) 1, fp); 2066 } 2067 for (i = 0; i < typecnt; ++i) 2068 if (writetype[i]) { 2069 puttzcode(gmtoffs[i], fp); 2070 putc(isdsts[i], fp); 2071 putc((unsigned char) indmap[abbrinds[i]], fp); 2072 } 2073 if (thischarcnt != 0) 2074 fwrite(thischars, sizeof thischars[0], 2075 (size_t) thischarcnt, fp); 2076 for (i = thisleapi; i < thisleaplim; ++i) { 2077 zic_t todo; 2078 2079 if (roll[i]) { 2080 if (timecnt == 0 || trans[i] < ats[0]) { 2081 j = 0; 2082 while (isdsts[j]) 2083 if (++j >= typecnt) { 2084 j = 0; 2085 break; 2086 } 2087 } else { 2088 j = 1; 2089 while (j < timecnt && 2090 trans[i] >= ats[j]) 2091 ++j; 2092 j = types[j - 1]; 2093 } 2094 todo = tadd(trans[i], -gmtoffs[j]); 2095 } else todo = trans[i]; 2096 if (pass == 1) 2097 puttzcode(todo, fp); 2098 else puttzcode64(todo, fp); 2099 puttzcode(corr[i], fp); 2100 } 2101 for (i = 0; i < typecnt; ++i) 2102 if (writetype[i]) 2103 putc(ttisstds[i], fp); 2104 for (i = 0; i < typecnt; ++i) 2105 if (writetype[i]) 2106 putc(ttisgmts[i], fp); 2107 } 2108 fprintf(fp, "\n%s\n", string); 2109 close_file(fp, directory, name); 2110 free(ats); 2111 } 2112 2113 static char const * 2114 abbroffset(char *buf, zic_t offset) 2115 { 2116 char sign = '+'; 2117 int seconds, minutes; 2118 2119 if (offset < 0) { 2120 offset = -offset; 2121 sign = '-'; 2122 } 2123 2124 seconds = offset % SECSPERMIN; 2125 offset /= SECSPERMIN; 2126 minutes = offset % MINSPERHOUR; 2127 offset /= MINSPERHOUR; 2128 if (100 <= offset) { 2129 error(_("%%z UT offset magnitude exceeds 99:59:59")); 2130 return "%z"; 2131 } else { 2132 char *p = buf; 2133 *p++ = sign; 2134 *p++ = '0' + offset / 10; 2135 *p++ = '0' + offset % 10; 2136 if (minutes | seconds) { 2137 *p++ = '0' + minutes / 10; 2138 *p++ = '0' + minutes % 10; 2139 if (seconds) { 2140 *p++ = '0' + seconds / 10; 2141 *p++ = '0' + seconds % 10; 2142 } 2143 } 2144 *p = '\0'; 2145 return buf; 2146 } 2147 } 2148 2149 static size_t 2150 doabbr(char *abbr, int abbrlen, struct zone const *zp, const char *letters, 2151 bool isdst, zic_t stdoff, bool doquotes) 2152 { 2153 char * cp; 2154 char * slashp; 2155 size_t len; 2156 char const *format = zp->z_format; 2157 2158 slashp = strchr(format, '/'); 2159 if (slashp == NULL) { 2160 char letterbuf[PERCENT_Z_LEN_BOUND + 1]; 2161 if (zp->z_format_specifier == 'z') 2162 letters = abbroffset(letterbuf, zp->z_gmtoff + stdoff); 2163 else if (!letters) 2164 letters = "%s"; 2165 snprintf(abbr, abbrlen, format, letters); 2166 } else if (isdst) { 2167 strlcpy(abbr, slashp + 1, abbrlen); 2168 } else { 2169 memcpy(abbr, format, slashp - format); 2170 abbr[slashp - format] = '\0'; 2171 } 2172 len = strlen(abbr); 2173 if (!doquotes) 2174 return len; 2175 for (cp = abbr; is_alpha(*cp); cp++) 2176 continue; 2177 if (len > 0 && *cp == '\0') 2178 return len; 2179 abbr[len + 2] = '\0'; 2180 abbr[len + 1] = '>'; 2181 memmove(abbr + 1, abbr, len); 2182 abbr[0] = '<'; 2183 return len + 2; 2184 } 2185 2186 static void 2187 updateminmax(const zic_t x) 2188 { 2189 if (min_year > x) 2190 min_year = x; 2191 if (max_year < x) 2192 max_year = x; 2193 } 2194 2195 static int 2196 stringoffset(char *result, zic_t offset) 2197 { 2198 int hours; 2199 int minutes; 2200 int seconds; 2201 bool negative = offset < 0; 2202 int len = negative; 2203 2204 if (negative) { 2205 offset = -offset; 2206 result[0] = '-'; 2207 } 2208 seconds = offset % SECSPERMIN; 2209 offset /= SECSPERMIN; 2210 minutes = offset % MINSPERHOUR; 2211 offset /= MINSPERHOUR; 2212 hours = offset; 2213 if (hours >= HOURSPERDAY * DAYSPERWEEK) { 2214 result[0] = '\0'; 2215 return 0; 2216 } 2217 len += sprintf(result + len, "%d", hours); 2218 if (minutes != 0 || seconds != 0) { 2219 len += sprintf(result + len, ":%02d", minutes); 2220 if (seconds != 0) 2221 len += sprintf(result + len, ":%02d", seconds); 2222 } 2223 return len; 2224 } 2225 2226 static int 2227 stringrule(char *result, const struct rule *const rp, const zic_t dstoff, 2228 const zic_t gmtoff) 2229 { 2230 zic_t tod = rp->r_tod; 2231 int compat = 0; 2232 2233 if (rp->r_dycode == DC_DOM) { 2234 int month, total; 2235 2236 if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY) 2237 return -1; 2238 total = 0; 2239 for (month = 0; month < rp->r_month; ++month) 2240 total += len_months[0][month]; 2241 /* Omit the "J" in Jan and Feb, as that's shorter. */ 2242 if (rp->r_month <= 1) 2243 result += sprintf(result, "%d", total + rp->r_dayofmonth - 1); 2244 else 2245 result += sprintf(result, "J%d", total + rp->r_dayofmonth); 2246 } else { 2247 int week; 2248 int wday = rp->r_wday; 2249 int wdayoff; 2250 2251 if (rp->r_dycode == DC_DOWGEQ) { 2252 wdayoff = (rp->r_dayofmonth - 1) % DAYSPERWEEK; 2253 if (wdayoff) 2254 compat = 2013; 2255 wday -= wdayoff; 2256 tod += wdayoff * SECSPERDAY; 2257 week = 1 + (rp->r_dayofmonth - 1) / DAYSPERWEEK; 2258 } else if (rp->r_dycode == DC_DOWLEQ) { 2259 if (rp->r_dayofmonth == len_months[1][rp->r_month]) 2260 week = 5; 2261 else { 2262 wdayoff = rp->r_dayofmonth % DAYSPERWEEK; 2263 if (wdayoff) 2264 compat = 2013; 2265 wday -= wdayoff; 2266 tod += wdayoff * SECSPERDAY; 2267 week = rp->r_dayofmonth / DAYSPERWEEK; 2268 } 2269 } else return -1; /* "cannot happen" */ 2270 if (wday < 0) 2271 wday += DAYSPERWEEK; 2272 result += sprintf(result, "M%d.%d.%d", 2273 rp->r_month + 1, week, wday); 2274 } 2275 if (rp->r_todisgmt) 2276 tod += gmtoff; 2277 if (rp->r_todisstd && !rp->r_isdst) 2278 tod += dstoff; 2279 if (tod != 2 * SECSPERMIN * MINSPERHOUR) { 2280 *result++ = '/'; 2281 if (! stringoffset(result, tod)) 2282 return -1; 2283 if (tod < 0) { 2284 if (compat < 2013) 2285 compat = 2013; 2286 } else if (SECSPERDAY <= tod) { 2287 if (compat < 1994) 2288 compat = 1994; 2289 } 2290 } 2291 return compat; 2292 } 2293 2294 static int 2295 rule_cmp(struct rule const *a, struct rule const *b) 2296 { 2297 if (!a) 2298 return -!!b; 2299 if (!b) 2300 return 1; 2301 if (a->r_hiyear != b->r_hiyear) 2302 return a->r_hiyear < b->r_hiyear ? -1 : 1; 2303 if (a->r_month - b->r_month != 0) 2304 return a->r_month - b->r_month; 2305 return a->r_dayofmonth - b->r_dayofmonth; 2306 } 2307 2308 enum { YEAR_BY_YEAR_ZONE = 1 }; 2309 2310 static int 2311 stringzone(char *result, const int resultlen, const struct zone *const zpfirst, 2312 const int zonecount) 2313 { 2314 const struct zone * zp; 2315 struct rule * rp; 2316 struct rule * stdrp; 2317 struct rule * dstrp; 2318 ptrdiff_t i; 2319 const char * abbrvar; 2320 int compat = 0; 2321 int c; 2322 size_t len; 2323 int offsetlen; 2324 struct rule stdr, dstr; 2325 2326 result[0] = '\0'; 2327 zp = zpfirst + zonecount - 1; 2328 stdrp = dstrp = NULL; 2329 for (i = 0; i < zp->z_nrules; ++i) { 2330 rp = &zp->z_rules[i]; 2331 if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX) 2332 continue; 2333 if (rp->r_yrtype != NULL) 2334 continue; 2335 if (!rp->r_isdst) { 2336 if (stdrp == NULL) 2337 stdrp = rp; 2338 else return -1; 2339 } else { 2340 if (dstrp == NULL) 2341 dstrp = rp; 2342 else return -1; 2343 } 2344 } 2345 if (stdrp == NULL && dstrp == NULL) { 2346 /* 2347 ** There are no rules running through "max". 2348 ** Find the latest std rule in stdabbrrp 2349 ** and latest rule of any type in stdrp. 2350 */ 2351 struct rule *stdabbrrp = NULL; 2352 for (i = 0; i < zp->z_nrules; ++i) { 2353 rp = &zp->z_rules[i]; 2354 if (!rp->r_isdst && rule_cmp(stdabbrrp, rp) < 0) 2355 stdabbrrp = rp; 2356 if (rule_cmp(stdrp, rp) < 0) 2357 stdrp = rp; 2358 } 2359 /* 2360 ** Horrid special case: if year is 2037, 2361 ** presume this is a zone handled on a year-by-year basis; 2362 ** do not try to apply a rule to the zone. 2363 */ 2364 if (stdrp != NULL && stdrp->r_hiyear == 2037) 2365 return YEAR_BY_YEAR_ZONE; 2366 2367 if (stdrp != NULL && stdrp->r_isdst) { 2368 /* Perpetual DST. */ 2369 dstr.r_month = TM_JANUARY; 2370 dstr.r_dycode = DC_DOM; 2371 dstr.r_dayofmonth = 1; 2372 dstr.r_tod = 0; 2373 dstr.r_todisstd = dstr.r_todisgmt = false; 2374 dstr.r_isdst = stdrp->r_isdst; 2375 dstr.r_stdoff = stdrp->r_stdoff; 2376 dstr.r_abbrvar = stdrp->r_abbrvar; 2377 stdr.r_month = TM_DECEMBER; 2378 stdr.r_dycode = DC_DOM; 2379 stdr.r_dayofmonth = 31; 2380 stdr.r_tod = SECSPERDAY + stdrp->r_stdoff; 2381 stdr.r_todisstd = stdr.r_todisgmt = false; 2382 stdr.r_isdst = false; 2383 stdr.r_stdoff = 0; 2384 stdr.r_abbrvar 2385 = (stdabbrrp ? stdabbrrp->r_abbrvar : ""); 2386 dstrp = &dstr; 2387 stdrp = &stdr; 2388 } 2389 } 2390 if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_isdst)) 2391 return -1; 2392 abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar; 2393 len = doabbr(result, resultlen, zp, abbrvar, false, 0, true); 2394 offsetlen = stringoffset(result + len, -zp->z_gmtoff); 2395 if (! offsetlen) { 2396 result[0] = '\0'; 2397 return -1; 2398 } 2399 len += offsetlen; 2400 if (dstrp == NULL) 2401 return compat; 2402 len += doabbr(result + len, resultlen - len, zp, dstrp->r_abbrvar, 2403 dstrp->r_isdst, dstrp->r_stdoff, true); 2404 if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR) { 2405 offsetlen = stringoffset(result + len, 2406 -(zp->z_gmtoff + dstrp->r_stdoff)); 2407 if (! offsetlen) { 2408 result[0] = '\0'; 2409 return -1; 2410 } 2411 len += offsetlen; 2412 } 2413 result[len++] = ','; 2414 c = stringrule(result + len, dstrp, dstrp->r_stdoff, zp->z_gmtoff); 2415 if (c < 0) { 2416 result[0] = '\0'; 2417 return -1; 2418 } 2419 if (compat < c) 2420 compat = c; 2421 len += strlen(result + len); 2422 result[len++] = ','; 2423 c = stringrule(result + len, stdrp, dstrp->r_stdoff, zp->z_gmtoff); 2424 if (c < 0) { 2425 result[0] = '\0'; 2426 return -1; 2427 } 2428 if (compat < c) 2429 compat = c; 2430 return compat; 2431 } 2432 2433 static void 2434 outzone(const struct zone *zpfirst, ptrdiff_t zonecount) 2435 { 2436 const struct zone * zp; 2437 struct rule * rp; 2438 ptrdiff_t i, j; 2439 bool usestart, useuntil; 2440 zic_t starttime, untiltime; 2441 zic_t gmtoff; 2442 zic_t stdoff; 2443 zic_t year; 2444 zic_t startoff; 2445 bool startttisstd; 2446 bool startttisgmt; 2447 int type; 2448 char * startbuf; 2449 char * ab; 2450 char * envvar; 2451 size_t max_abbr_len; 2452 size_t max_envvar_len; 2453 bool prodstic; /* all rules are min to max */ 2454 int compat; 2455 bool do_extend; 2456 int version; 2457 ptrdiff_t lastatmax = -1; 2458 zic_t one = 1; 2459 zic_t y2038_boundary = one << 31; 2460 zic_t max_year0; 2461 2462 max_abbr_len = 2 + max_format_len + max_abbrvar_len; 2463 max_envvar_len = 2 * max_abbr_len + 5 * 9; 2464 startbuf = zic_malloc(max_abbr_len + 1); 2465 ab = zic_malloc(max_abbr_len + 1); 2466 envvar = zic_malloc(max_envvar_len + 1); 2467 INITIALIZE(untiltime); 2468 INITIALIZE(starttime); 2469 /* 2470 ** Now. . .finally. . .generate some useful data! 2471 */ 2472 timecnt = 0; 2473 typecnt = 0; 2474 charcnt = 0; 2475 prodstic = zonecount == 1; 2476 /* 2477 ** Thanks to Earl Chew 2478 ** for noting the need to unconditionally initialize startttisstd. 2479 */ 2480 startttisstd = false; 2481 startttisgmt = false; 2482 min_year = max_year = EPOCH_YEAR; 2483 if (leapseen) { 2484 updateminmax(leapminyear); 2485 updateminmax(leapmaxyear + (leapmaxyear < ZIC_MAX)); 2486 } 2487 for (i = 0; i < zonecount; ++i) { 2488 zp = &zpfirst[i]; 2489 if (i < zonecount - 1) 2490 updateminmax(zp->z_untilrule.r_loyear); 2491 for (j = 0; j < zp->z_nrules; ++j) { 2492 rp = &zp->z_rules[j]; 2493 if (rp->r_lowasnum) 2494 updateminmax(rp->r_loyear); 2495 if (rp->r_hiwasnum) 2496 updateminmax(rp->r_hiyear); 2497 if (rp->r_lowasnum || rp->r_hiwasnum) 2498 prodstic = false; 2499 } 2500 } 2501 /* 2502 ** Generate lots of data if a rule can't cover all future times. 2503 */ 2504 compat = stringzone(envvar, max_envvar_len + 1, zpfirst, zonecount); 2505 version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION; 2506 do_extend = compat < 0 || compat == YEAR_BY_YEAR_ZONE; 2507 if (noise) { 2508 if (!*envvar) 2509 warning("%s %s", 2510 _("no POSIX environment variable for zone"), 2511 zpfirst->z_name); 2512 else if (compat != 0 && compat != YEAR_BY_YEAR_ZONE) { 2513 /* Circa-COMPAT clients, and earlier clients, might 2514 not work for this zone when given dates before 2515 1970 or after 2038. */ 2516 warning(_("%s: pre-%d clients may mishandle" 2517 " distant timestamps"), 2518 zpfirst->z_name, compat); 2519 } 2520 } 2521 if (do_extend) { 2522 /* 2523 ** Search through a couple of extra years past the obvious 2524 ** 400, to avoid edge cases. For example, suppose a non-POSIX 2525 ** rule applies from 2012 onwards and has transitions in March 2526 ** and September, plus some one-off transitions in November 2527 ** 2013. If zic looked only at the last 400 years, it would 2528 ** set max_year=2413, with the intent that the 400 years 2014 2529 ** through 2413 will be repeated. The last transition listed 2530 ** in the tzfile would be in 2413-09, less than 400 years 2531 ** after the last one-off transition in 2013-11. Two years 2532 ** might be overkill, but with the kind of edge cases 2533 ** available we're not sure that one year would suffice. 2534 */ 2535 enum { years_of_observations = YEARSPERREPEAT + 2 }; 2536 2537 if (min_year >= ZIC_MIN + years_of_observations) 2538 min_year -= years_of_observations; 2539 else min_year = ZIC_MIN; 2540 if (max_year <= ZIC_MAX - years_of_observations) 2541 max_year += years_of_observations; 2542 else max_year = ZIC_MAX; 2543 /* 2544 ** Regardless of any of the above, 2545 ** for a "proDSTic" zone which specifies that its rules 2546 ** always have and always will be in effect, 2547 ** we only need one cycle to define the zone. 2548 */ 2549 if (prodstic) { 2550 min_year = 1900; 2551 max_year = min_year + years_of_observations; 2552 } 2553 } 2554 /* 2555 ** For the benefit of older systems, 2556 ** generate data from 1900 through 2038. 2557 */ 2558 if (min_year > 1900) 2559 min_year = 1900; 2560 max_year0 = max_year; 2561 if (max_year < 2038) 2562 max_year = 2038; 2563 for (i = 0; i < zonecount; ++i) { 2564 /* 2565 ** A guess that may well be corrected later. 2566 */ 2567 stdoff = 0; 2568 zp = &zpfirst[i]; 2569 usestart = i > 0 && (zp - 1)->z_untiltime > early_time; 2570 useuntil = i < (zonecount - 1); 2571 if (useuntil && zp->z_untiltime <= early_time) 2572 continue; 2573 gmtoff = zp->z_gmtoff; 2574 eat(zp->z_filename, zp->z_linenum); 2575 *startbuf = '\0'; 2576 startoff = zp->z_gmtoff; 2577 if (zp->z_nrules == 0) { 2578 stdoff = zp->z_stdoff; 2579 doabbr(startbuf, max_abbr_len + 1, zp, 2580 NULL, zp->z_isdst, stdoff, false); 2581 type = addtype(oadd(zp->z_gmtoff, stdoff), 2582 startbuf, stdoff != 0, startttisstd, 2583 startttisgmt); 2584 if (usestart) { 2585 addtt(starttime, type); 2586 usestart = false; 2587 } else addtt(early_time, type); 2588 } else for (year = min_year; year <= max_year; ++year) { 2589 if (useuntil && year > zp->z_untilrule.r_hiyear) 2590 break; 2591 /* 2592 ** Mark which rules to do in the current year. 2593 ** For those to do, calculate rpytime(rp, year); 2594 */ 2595 for (j = 0; j < zp->z_nrules; ++j) { 2596 rp = &zp->z_rules[j]; 2597 eats(zp->z_filename, zp->z_linenum, 2598 rp->r_filename, rp->r_linenum); 2599 rp->r_todo = year >= rp->r_loyear && 2600 year <= rp->r_hiyear && 2601 yearistype(year, rp->r_yrtype); 2602 if (rp->r_todo) { 2603 rp->r_temp = rpytime(rp, year); 2604 rp->r_todo 2605 = (rp->r_temp < y2038_boundary 2606 || year <= max_year0); 2607 } 2608 } 2609 for ( ; ; ) { 2610 ptrdiff_t k; 2611 zic_t jtime, ktime; 2612 zic_t offset; 2613 2614 INITIALIZE(ktime); 2615 if (useuntil) { 2616 /* 2617 ** Turn untiltime into UT 2618 ** assuming the current gmtoff and 2619 ** stdoff values. 2620 */ 2621 untiltime = zp->z_untiltime; 2622 if (!zp->z_untilrule.r_todisgmt) 2623 untiltime = tadd(untiltime, 2624 -gmtoff); 2625 if (!zp->z_untilrule.r_todisstd) 2626 untiltime = tadd(untiltime, 2627 -stdoff); 2628 } 2629 /* 2630 ** Find the rule (of those to do, if any) 2631 ** that takes effect earliest in the year. 2632 */ 2633 k = -1; 2634 for (j = 0; j < zp->z_nrules; ++j) { 2635 rp = &zp->z_rules[j]; 2636 if (!rp->r_todo) 2637 continue; 2638 eats(zp->z_filename, zp->z_linenum, 2639 rp->r_filename, rp->r_linenum); 2640 offset = rp->r_todisgmt ? 0 : gmtoff; 2641 if (!rp->r_todisstd) 2642 offset = oadd(offset, stdoff); 2643 jtime = rp->r_temp; 2644 if (jtime == min_time || 2645 jtime == max_time) 2646 continue; 2647 jtime = tadd(jtime, -offset); 2648 if (k < 0 || jtime < ktime) { 2649 k = j; 2650 ktime = jtime; 2651 } else if (jtime == ktime) { 2652 char const *dup_rules_msg = 2653 _("two rules for same instant"); 2654 eats(zp->z_filename, zp->z_linenum, 2655 rp->r_filename, rp->r_linenum); 2656 warning("%s", dup_rules_msg); 2657 rp = &zp->z_rules[k]; 2658 eats(zp->z_filename, zp->z_linenum, 2659 rp->r_filename, rp->r_linenum); 2660 error("%s", dup_rules_msg); 2661 } 2662 } 2663 if (k < 0) 2664 break; /* go on to next year */ 2665 rp = &zp->z_rules[k]; 2666 rp->r_todo = false; 2667 if (useuntil && ktime >= untiltime) 2668 break; 2669 stdoff = rp->r_stdoff; 2670 if (usestart && ktime == starttime) 2671 usestart = false; 2672 if (usestart) { 2673 if (ktime < starttime) { 2674 startoff = oadd(zp->z_gmtoff, 2675 stdoff); 2676 doabbr(startbuf, 2677 max_abbr_len + 1, 2678 zp, 2679 rp->r_abbrvar, 2680 rp->r_isdst, 2681 rp->r_stdoff, 2682 false); 2683 continue; 2684 } 2685 if (*startbuf == '\0' && 2686 startoff == oadd(zp->z_gmtoff, 2687 stdoff)) { 2688 doabbr(startbuf, 2689 max_abbr_len + 1, 2690 zp, 2691 rp->r_abbrvar, 2692 rp->r_isdst, 2693 rp->r_stdoff, 2694 false); 2695 } 2696 } 2697 eats(zp->z_filename, zp->z_linenum, 2698 rp->r_filename, rp->r_linenum); 2699 doabbr(ab, max_abbr_len + 1, zp, rp->r_abbrvar, 2700 rp->r_isdst, rp->r_stdoff, false); 2701 offset = oadd(zp->z_gmtoff, rp->r_stdoff); 2702 type = addtype(offset, ab, rp->r_isdst, 2703 rp->r_todisstd, rp->r_todisgmt); 2704 if (rp->r_hiyear == ZIC_MAX 2705 && ! (0 <= lastatmax 2706 && ktime < attypes[lastatmax].at)) 2707 lastatmax = timecnt; 2708 addtt(ktime, type); 2709 } 2710 } 2711 if (usestart) { 2712 if (*startbuf == '\0' && 2713 zp->z_format != NULL && 2714 strchr(zp->z_format, '%') == NULL && 2715 strchr(zp->z_format, '/') == NULL) 2716 strncpy(startbuf, zp->z_format, 2717 max_abbr_len + 1 - 1); 2718 eat(zp->z_filename, zp->z_linenum); 2719 if (*startbuf == '\0') 2720 error(_("can't determine time zone abbreviation to use just after until time")); 2721 else addtt(starttime, 2722 addtype(startoff, startbuf, 2723 startoff != zp->z_gmtoff, 2724 startttisstd, 2725 startttisgmt)); 2726 } 2727 /* 2728 ** Now we may get to set starttime for the next zone line. 2729 */ 2730 if (useuntil) { 2731 startttisstd = zp->z_untilrule.r_todisstd; 2732 startttisgmt = zp->z_untilrule.r_todisgmt; 2733 starttime = zp->z_untiltime; 2734 if (!startttisstd) 2735 starttime = tadd(starttime, -stdoff); 2736 if (!startttisgmt) 2737 starttime = tadd(starttime, -gmtoff); 2738 } 2739 } 2740 if (0 <= lastatmax) 2741 attypes[lastatmax].dontmerge = true; 2742 if (do_extend) { 2743 /* 2744 ** If we're extending the explicitly listed observations 2745 ** for 400 years because we can't fill the POSIX-TZ field, 2746 ** check whether we actually ended up explicitly listing 2747 ** observations through that period. If there aren't any 2748 ** near the end of the 400-year period, add a redundant 2749 ** one at the end of the final year, to make it clear 2750 ** that we are claiming to have definite knowledge of 2751 ** the lack of transitions up to that point. 2752 */ 2753 struct rule xr; 2754 struct attype *lastat; 2755 memset(&xr, 0, sizeof(xr)); 2756 xr.r_month = TM_JANUARY; 2757 xr.r_dycode = DC_DOM; 2758 xr.r_dayofmonth = 1; 2759 xr.r_tod = 0; 2760 for (lastat = &attypes[0], i = 1; i < timecnt; i++) 2761 if (attypes[i].at > lastat->at) 2762 lastat = &attypes[i]; 2763 if (lastat->at < rpytime(&xr, max_year - 1)) { 2764 addtt(rpytime(&xr, max_year + 1), typecnt-1); 2765 attypes[timecnt - 1].dontmerge = true; 2766 } 2767 } 2768 writezone(zpfirst->z_name, envvar, version); 2769 free(startbuf); 2770 free(ab); 2771 free(envvar); 2772 } 2773 2774 static void 2775 addtt(zic_t starttime, int type) 2776 { 2777 if (starttime <= early_time 2778 || (timecnt == 1 && attypes[0].at < early_time)) { 2779 gmtoffs[0] = gmtoffs[type]; 2780 isdsts[0] = isdsts[type]; 2781 ttisstds[0] = ttisstds[type]; 2782 ttisgmts[0] = ttisgmts[type]; 2783 if (abbrinds[type] != 0) 2784 strcpy(chars, &chars[abbrinds[type]]); 2785 abbrinds[0] = 0; 2786 charcnt = strlen(chars) + 1; 2787 typecnt = 1; 2788 timecnt = 0; 2789 type = 0; 2790 } 2791 attypes = growalloc(attypes, sizeof *attypes, timecnt, &timecnt_alloc); 2792 attypes[timecnt].at = starttime; 2793 attypes[timecnt].dontmerge = false; 2794 attypes[timecnt].type = type; 2795 ++timecnt; 2796 } 2797 2798 static int 2799 addtype(zic_t gmtoff, char const *abbr, bool isdst, bool ttisstd, bool ttisgmt) 2800 { 2801 int i, j; 2802 2803 /* 2804 ** See if there's already an entry for this zone type. 2805 ** If so, just return its index. 2806 */ 2807 for (i = 0; i < typecnt; ++i) { 2808 if (gmtoff == gmtoffs[i] && isdst == isdsts[i] && 2809 strcmp(abbr, &chars[abbrinds[i]]) == 0 && 2810 ttisstd == ttisstds[i] && 2811 ttisgmt == ttisgmts[i]) 2812 return i; 2813 } 2814 /* 2815 ** There isn't one; add a new one, unless there are already too 2816 ** many. 2817 */ 2818 if (typecnt >= TZ_MAX_TYPES) { 2819 error(_("too many local time types")); 2820 exit(EXIT_FAILURE); 2821 } 2822 if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) { 2823 error(_("UT offset out of range")); 2824 exit(EXIT_FAILURE); 2825 } 2826 gmtoffs[i] = gmtoff; 2827 isdsts[i] = isdst; 2828 ttisstds[i] = ttisstd; 2829 ttisgmts[i] = ttisgmt; 2830 2831 for (j = 0; j < charcnt; ++j) 2832 if (strcmp(&chars[j], abbr) == 0) 2833 break; 2834 if (j == charcnt) 2835 newabbr(abbr); 2836 abbrinds[i] = j; 2837 ++typecnt; 2838 return i; 2839 } 2840 2841 static void 2842 leapadd(zic_t t, bool positive, int rolling, int count) 2843 { 2844 int i, j; 2845 2846 if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) { 2847 error(_("too many leap seconds")); 2848 exit(EXIT_FAILURE); 2849 } 2850 for (i = 0; i < leapcnt; ++i) 2851 if (t <= trans[i]) 2852 break; 2853 do { 2854 for (j = leapcnt; j > i; --j) { 2855 trans[j] = trans[j - 1]; 2856 corr[j] = corr[j - 1]; 2857 roll[j] = roll[j - 1]; 2858 } 2859 trans[i] = t; 2860 corr[i] = positive ? 1 : -count; 2861 roll[i] = rolling; 2862 ++leapcnt; 2863 } while (positive && --count != 0); 2864 } 2865 2866 static void 2867 adjleap(void) 2868 { 2869 int i; 2870 zic_t last = 0; 2871 zic_t prevtrans = 0; 2872 2873 /* 2874 ** propagate leap seconds forward 2875 */ 2876 for (i = 0; i < leapcnt; ++i) { 2877 if (trans[i] - prevtrans < 28 * SECSPERDAY) { 2878 error(_("Leap seconds too close together")); 2879 exit(EXIT_FAILURE); 2880 } 2881 prevtrans = trans[i]; 2882 trans[i] = tadd(trans[i], last); 2883 last = corr[i] += last; 2884 } 2885 } 2886 2887 static char * 2888 shellquote(char *b, char const *s) 2889 { 2890 *b++ = '\''; 2891 while (*s) { 2892 if (*s == '\'') 2893 *b++ = '\'', *b++ = '\\', *b++ = '\''; 2894 *b++ = *s++; 2895 } 2896 *b++ = '\''; 2897 return b; 2898 } 2899 2900 static bool 2901 yearistype(zic_t year, const char *type) 2902 { 2903 char *buf; 2904 char *b; 2905 int result; 2906 size_t len; 2907 2908 if (type == NULL || *type == '\0') 2909 return true; 2910 buf = zic_malloc(len = 1 + 4 * strlen(yitcommand) + 2 2911 + INT_STRLEN_MAXIMUM(zic_t) + 2 + 4 * strlen(type) + 2); 2912 b = shellquote(buf, yitcommand); 2913 *b++ = ' '; 2914 b += snprintf(b, len - (b - buf), "%"PRIdZIC, year); 2915 *b++ = ' '; 2916 b = shellquote(b, type); 2917 *b = '\0'; 2918 result = system(buf); 2919 if (WIFEXITED(result)) { 2920 int status = WEXITSTATUS(result); 2921 if (status <= 1) { 2922 free(buf); 2923 return status == 0; 2924 } 2925 } 2926 error(_("Wild result from command execution")); 2927 fprintf(stderr, _("%s: command was '%s', result was %d\n"), 2928 progname, buf, result); 2929 exit(EXIT_FAILURE); 2930 } 2931 2932 /* Is A a space character in the C locale? */ 2933 static bool 2934 is_space(char a) 2935 { 2936 switch (a) { 2937 default: 2938 return false; 2939 case ' ': case '\f': case '\n': case '\r': case '\t': case '\v': 2940 return true; 2941 } 2942 } 2943 2944 /* Is A an alphabetic character in the C locale? */ 2945 static bool 2946 is_alpha(char a) 2947 { 2948 switch (a) { 2949 default: 2950 return 0; 2951 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': 2952 case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': 2953 case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': 2954 case 'V': case 'W': case 'X': case 'Y': case 'Z': 2955 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': 2956 case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': 2957 case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': 2958 case 'v': case 'w': case 'x': case 'y': case 'z': 2959 return true; 2960 } 2961 } 2962 2963 /* If A is an uppercase character in the C locale, return its lowercase 2964 counterpart. Otherwise, return A. */ 2965 static char 2966 lowerit(char a) 2967 { 2968 switch (a) { 2969 default: return a; 2970 case 'A': return 'a'; case 'B': return 'b'; case 'C': return 'c'; 2971 case 'D': return 'd'; case 'E': return 'e'; case 'F': return 'f'; 2972 case 'G': return 'g'; case 'H': return 'h'; case 'I': return 'i'; 2973 case 'J': return 'j'; case 'K': return 'k'; case 'L': return 'l'; 2974 case 'M': return 'm'; case 'N': return 'n'; case 'O': return 'o'; 2975 case 'P': return 'p'; case 'Q': return 'q'; case 'R': return 'r'; 2976 case 'S': return 's'; case 'T': return 't'; case 'U': return 'u'; 2977 case 'V': return 'v'; case 'W': return 'w'; case 'X': return 'x'; 2978 case 'Y': return 'y'; case 'Z': return 'z'; 2979 } 2980 } 2981 2982 /* case-insensitive equality */ 2983 static bool 2984 ciequal(const char *ap, const char *bp) 2985 { 2986 while (lowerit(*ap) == lowerit(*bp++)) 2987 if (*ap++ == '\0') 2988 return true; 2989 return false; 2990 } 2991 2992 static bool 2993 itsabbr(const char *abbr, const char *word) 2994 { 2995 if (lowerit(*abbr) != lowerit(*word)) 2996 return false; 2997 ++word; 2998 while (*++abbr != '\0') 2999 do { 3000 if (*word == '\0') 3001 return false; 3002 } while (lowerit(*word++) != lowerit(*abbr)); 3003 return true; 3004 } 3005 3006 /* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case. */ 3007 3008 static bool 3009 ciprefix(char const *abbr, char const *word) 3010 { 3011 do 3012 if (!*abbr) 3013 return true; 3014 while (lowerit(*abbr++) == lowerit(*word++)); 3015 3016 return false; 3017 } 3018 3019 static const struct lookup * 3020 byword(const char *word, const struct lookup *table) 3021 { 3022 const struct lookup * foundlp; 3023 const struct lookup * lp; 3024 3025 if (word == NULL || table == NULL) 3026 return NULL; 3027 3028 /* If TABLE is LASTS and the word starts with "last" followed 3029 by a non-'-', skip the "last" and look in WDAY_NAMES instead. 3030 Warn about any usage of the undocumented prefix "last-". */ 3031 if (table == lasts && ciprefix("last", word) && word[4]) { 3032 if (word[4] == '-') 3033 warning(_("\"%s\" is undocumented; use \"last%s\" instead"), 3034 word, word + 5); 3035 else { 3036 word += 4; 3037 table = wday_names; 3038 } 3039 } 3040 3041 /* 3042 ** Look for exact match. 3043 */ 3044 for (lp = table; lp->l_word != NULL; ++lp) 3045 if (ciequal(word, lp->l_word)) 3046 return lp; 3047 /* 3048 ** Look for inexact match. 3049 */ 3050 foundlp = NULL; 3051 for (lp = table; lp->l_word != NULL; ++lp) 3052 if (ciprefix(word, lp->l_word)) { 3053 if (foundlp == NULL) 3054 foundlp = lp; 3055 else return NULL; /* multiple inexact matches */ 3056 } 3057 3058 /* Warn about any backward-compatibility issue with pre-2017c zic. */ 3059 if (foundlp) { 3060 bool pre_2017c_match = false; 3061 for (lp = table; lp->l_word; lp++) 3062 if (itsabbr(word, lp->l_word)) { 3063 if (pre_2017c_match) { 3064 warning(_("\"%s\" is ambiguous in pre-2017c zic"), word); 3065 break; 3066 } 3067 pre_2017c_match = true; 3068 } 3069 } 3070 3071 return foundlp; 3072 } 3073 3074 static char ** 3075 getfields(char *cp) 3076 { 3077 char * dp; 3078 char ** array; 3079 int nsubs; 3080 3081 if (cp == NULL) 3082 return NULL; 3083 array = zic_malloc(size_product(strlen(cp) + 1, sizeof *array)); 3084 nsubs = 0; 3085 for ( ; ; ) { 3086 while (is_space(*cp)) 3087 ++cp; 3088 if (*cp == '\0' || *cp == '#') 3089 break; 3090 array[nsubs++] = dp = cp; 3091 do { 3092 if ((*dp = *cp++) != '"') 3093 ++dp; 3094 else while ((*dp = *cp++) != '"') 3095 if (*dp != '\0') 3096 ++dp; 3097 else { 3098 error(_("Odd number of quotation marks")); 3099 exit(EXIT_FAILURE); 3100 } 3101 } while (*cp && *cp != '#' && !is_space(*cp)); 3102 if (is_space(*cp)) 3103 ++cp; 3104 *dp = '\0'; 3105 } 3106 array[nsubs] = NULL; 3107 return array; 3108 } 3109 3110 static _Noreturn void 3111 time_overflow(void) 3112 { 3113 error(_("time overflow")); 3114 exit(EXIT_FAILURE); 3115 } 3116 3117 static ATTRIBUTE_PURE zic_t 3118 oadd(zic_t t1, zic_t t2) 3119 { 3120 if (t1 < 0 ? t2 < ZIC_MIN - t1 : ZIC_MAX - t1 < t2) 3121 time_overflow(); 3122 return t1 + t2; 3123 } 3124 3125 static ATTRIBUTE_PURE zic_t 3126 tadd(zic_t t1, zic_t t2) 3127 { 3128 if (t1 < 0) { 3129 if (t2 < min_time - t1) { 3130 if (t1 != min_time) 3131 time_overflow(); 3132 return min_time; 3133 } 3134 } else { 3135 if (max_time - t1 < t2) { 3136 if (t1 != max_time) 3137 time_overflow(); 3138 return max_time; 3139 } 3140 } 3141 return t1 + t2; 3142 } 3143 3144 /* 3145 ** Given a rule, and a year, compute the date (in seconds since January 1, 3146 ** 1970, 00:00 LOCAL time) in that year that the rule refers to. 3147 */ 3148 3149 static zic_t 3150 rpytime(const struct rule *rp, zic_t wantedy) 3151 { 3152 int m, i; 3153 zic_t dayoff; /* with a nod to Margaret O. */ 3154 zic_t t, y; 3155 3156 if (wantedy == ZIC_MIN) 3157 return min_time; 3158 if (wantedy == ZIC_MAX) 3159 return max_time; 3160 dayoff = 0; 3161 m = TM_JANUARY; 3162 y = EPOCH_YEAR; 3163 while (wantedy != y) { 3164 if (wantedy > y) { 3165 i = len_years[isleap(y)]; 3166 ++y; 3167 } else { 3168 --y; 3169 i = -len_years[isleap(y)]; 3170 } 3171 dayoff = oadd(dayoff, i); 3172 } 3173 while (m != rp->r_month) { 3174 i = len_months[isleap(y)][m]; 3175 dayoff = oadd(dayoff, i); 3176 ++m; 3177 } 3178 i = rp->r_dayofmonth; 3179 if (m == TM_FEBRUARY && i == 29 && !isleap(y)) { 3180 if (rp->r_dycode == DC_DOWLEQ) 3181 --i; 3182 else { 3183 error(_("use of 2/29 in non leap-year")); 3184 exit(EXIT_FAILURE); 3185 } 3186 } 3187 --i; 3188 dayoff = oadd(dayoff, i); 3189 if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) { 3190 zic_t wday; 3191 3192 #define LDAYSPERWEEK ((zic_t) DAYSPERWEEK) 3193 wday = EPOCH_WDAY; 3194 /* 3195 ** Don't trust mod of negative numbers. 3196 */ 3197 if (dayoff >= 0) 3198 wday = (wday + dayoff) % LDAYSPERWEEK; 3199 else { 3200 wday -= ((-dayoff) % LDAYSPERWEEK); 3201 if (wday < 0) 3202 wday += LDAYSPERWEEK; 3203 } 3204 while (wday != rp->r_wday) 3205 if (rp->r_dycode == DC_DOWGEQ) { 3206 dayoff = oadd(dayoff, (zic_t) 1); 3207 if (++wday >= LDAYSPERWEEK) 3208 wday = 0; 3209 ++i; 3210 } else { 3211 dayoff = oadd(dayoff, (zic_t) -1); 3212 if (--wday < 0) 3213 wday = LDAYSPERWEEK - 1; 3214 --i; 3215 } 3216 if (i < 0 || i >= len_months[isleap(y)][m]) { 3217 if (noise) 3218 warning(_("rule goes past start/end of month; \ 3219 will not work with pre-2004 versions of zic")); 3220 } 3221 } 3222 if (dayoff < min_time / SECSPERDAY) 3223 return min_time; 3224 if (dayoff > max_time / SECSPERDAY) 3225 return max_time; 3226 t = (zic_t) dayoff * SECSPERDAY; 3227 return tadd(t, rp->r_tod); 3228 } 3229 3230 static void 3231 newabbr(const char *string) 3232 { 3233 int i; 3234 3235 if (strcmp(string, GRANDPARENTED) != 0) { 3236 const char * cp; 3237 const char * mp; 3238 3239 cp = string; 3240 mp = NULL; 3241 while (is_alpha(*cp) || ('0' <= *cp && *cp <= '9') 3242 || *cp == '-' || *cp == '+') 3243 ++cp; 3244 if (noise && cp - string < 3) 3245 mp = _("time zone abbreviation has fewer than 3 characters"); 3246 if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN) 3247 mp = _("time zone abbreviation has too many characters"); 3248 if (*cp != '\0') 3249 mp = _("time zone abbreviation differs from POSIX standard"); 3250 if (mp != NULL) 3251 warning("%s (%s)", mp, string); 3252 } 3253 i = strlen(string) + 1; 3254 if (charcnt + i > TZ_MAX_CHARS) { 3255 error(_("too many, or too long, time zone abbreviations")); 3256 exit(EXIT_FAILURE); 3257 } 3258 strncpy(&chars[charcnt], string, sizeof(chars) - charcnt - 1); 3259 charcnt += i; 3260 } 3261 3262 /* Ensure that the directories of ARGNAME exist, by making any missing 3263 ones. If ANCESTORS, do this only for ARGNAME's ancestors; otherwise, 3264 do it for ARGNAME too. Exit with failure if there is trouble. 3265 Do not consider an existing non-directory to be trouble. */ 3266 static void 3267 mkdirs(char const *argname, bool ancestors) 3268 { 3269 char * name; 3270 char * cp; 3271 3272 cp = name = ecpyalloc(argname); 3273 3274 /* On MS-Windows systems, do not worry about drive letters or 3275 backslashes, as this should suffice in practice. Time zone 3276 names do not use drive letters and backslashes. If the -d 3277 option of zic does not name an already-existing directory, 3278 it can use slashes to separate the already-existing 3279 ancestor prefix from the to-be-created subdirectories. */ 3280 3281 /* Do not mkdir a root directory, as it must exist. */ 3282 while (*cp == '/') 3283 cp++; 3284 3285 while (cp && ((cp = strchr(cp, '/')) || !ancestors)) { 3286 if (cp) 3287 *cp = '\0'; 3288 /* 3289 ** Try to create it. It's OK if creation fails because 3290 ** the directory already exists, perhaps because some 3291 ** other process just created it. For simplicity do 3292 ** not check first whether it already exists, as that 3293 ** is checked anyway if the mkdir fails. 3294 */ 3295 if (mkdir(name, MKDIR_UMASK) != 0) { 3296 /* For speed, skip itsdir if errno == EEXIST. Since 3297 mkdirs is called only after open fails with ENOENT 3298 on a subfile, EEXIST implies itsdir here. */ 3299 int err = errno; 3300 if (err != EEXIST && !itsdir(name)) { 3301 error(_("%s: Can't create directory %s: %s"), 3302 progname, name, strerror(err)); 3303 exit(EXIT_FAILURE); 3304 } 3305 } 3306 if (cp) 3307 *cp++ = '/'; 3308 } 3309 free(name); 3310 } 3311