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