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