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