1 /* 2 * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <stdlib.h> 27 #include <stdio.h> 28 #include <strings.h> 29 #include <time.h> 30 #include <limits.h> 31 #include <errno.h> 32 #include <stddef.h> 33 #include <sys/stat.h> 34 #include <sys/types.h> 35 #include <string.h> 36 #include <dirent.h> 37 #include <unistd.h> 38 #ifdef __solaris__ 39 #include <libscf.h> 40 #endif 41 42 #include "jvm.h" 43 44 #define SKIP_SPACE(p) while (*p == ' ' || *p == '\t') p++; 45 46 #if !defined(__solaris__) || defined(__sparcv9) || defined(amd64) 47 #define fileopen fopen 48 #define filegets fgets 49 #define fileclose fclose 50 #endif 51 52 #if defined(__linux__) || defined(_ALLBSD_SOURCE) 53 54 55 static const char *ETC_TIMEZONE_FILE = "/etc/timezone"; 56 static const char *ZONEINFO_DIR = "/usr/share/zoneinfo"; 57 static const char *DEFAULT_ZONEINFO_FILE = "/etc/localtime"; 58 #else 59 #ifdef _AIX 60 static const char *ETC_ENVIRONMENT_FILE = "/etc/environment"; 61 #endif 62 static const char *SYS_INIT_FILE = "/etc/default/init"; 63 static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo"; 64 static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime"; 65 #endif /*__linux__*/ 66 67 /* 68 * Returns a pointer to the zone ID portion of the given zoneinfo file 69 * name, or NULL if the given string doesn't contain "zoneinfo/". 70 */ 71 static char * 72 getZoneName(char *str) 73 { 74 static const char *zidir = "zoneinfo/"; 75 76 char *pos = strstr((const char *)str, zidir); 77 if (pos == NULL) { 78 return NULL; 79 } 80 return pos + strlen(zidir); 81 } 82 83 /* 84 * Returns a path name created from the given 'dir' and 'name' under 85 * UNIX. This function allocates memory for the pathname calling 86 * malloc(). NULL is returned if malloc() fails. 87 */ 88 static char * 89 getPathName(const char *dir, const char *name) { 90 char *path; 91 92 path = (char *) malloc(strlen(dir) + strlen(name) + 2); 93 if (path == NULL) { 94 return NULL; 95 } 96 return strcat(strcat(strcpy(path, dir), "/"), name); 97 } 98 99 /* 100 * Scans the specified directory and its subdirectories to find a 101 * zoneinfo file which has the same content as /etc/localtime on Linux 102 * or /usr/share/lib/zoneinfo/localtime on Solaris given in 'buf'. 103 * If file is symbolic link, then the contents it points to are in buf. 104 * Returns a zone ID if found, otherwise, NULL is returned. 105 */ 106 static char * 107 findZoneinfoFile(char *buf, size_t size, const char *dir) 108 { 109 DIR *dirp = NULL; 110 struct stat statbuf; 111 struct dirent *dp = NULL; 112 struct dirent *entry = NULL; 113 char *pathname = NULL; 114 int fd = -1; 115 char *dbuf = NULL; 116 char *tz = NULL; 117 118 dirp = opendir(dir); 119 if (dirp == NULL) { 120 return NULL; 121 } 122 123 entry = (struct dirent *) malloc((size_t) pathconf(dir, _PC_NAME_MAX)); 124 if (entry == NULL) { 125 (void) closedir(dirp); 126 return NULL; 127 } 128 129 #if defined(_AIX) || defined(__linux__) || defined(MACOSX) || (defined(__solaris__) \ 130 && (defined(_POSIX_PTHREAD_SEMANTICS) || defined(_LP64))) 131 while (readdir_r(dirp, entry, &dp) == 0 && dp != NULL) { 132 #else 133 while ((dp = readdir_r(dirp, entry)) != NULL) { 134 #endif 135 136 /* 137 * Skip '.' and '..' (and possibly other .* files) 138 */ 139 if (dp->d_name[0] == '.') { 140 continue; 141 } 142 143 /* 144 * Skip "ROC", "posixrules", and "localtime". 145 */ 146 if ((strcmp(dp->d_name, "ROC") == 0) 147 || (strcmp(dp->d_name, "posixrules") == 0) 148 #ifdef __solaris__ 149 /* 150 * Skip the "src" and "tab" directories on Solaris. 151 */ 152 || (strcmp(dp->d_name, "src") == 0) 153 || (strcmp(dp->d_name, "tab") == 0) 154 #endif 155 || (strcmp(dp->d_name, "localtime") == 0)) { 156 continue; 157 } 158 159 pathname = getPathName(dir, dp->d_name); 160 if (pathname == NULL) { 161 break; 162 } 163 if (stat(pathname, &statbuf) == -1) { 164 break; 165 } 166 167 if (S_ISDIR(statbuf.st_mode)) { 168 tz = findZoneinfoFile(buf, size, pathname); 169 if (tz != NULL) { 170 break; 171 } 172 } else if (S_ISREG(statbuf.st_mode) && (size_t)statbuf.st_size == size) { 173 dbuf = (char *) malloc(size); 174 if (dbuf == NULL) { 175 break; 176 } 177 if ((fd = open(pathname, O_RDONLY)) == -1) { 178 break; 179 } 180 if (read(fd, dbuf, size) != (ssize_t) size) { 181 break; 182 } 183 if (memcmp(buf, dbuf, size) == 0) { 184 tz = getZoneName(pathname); 185 if (tz != NULL) { 186 tz = strdup(tz); 187 } 188 break; 189 } 190 free((void *) dbuf); 191 dbuf = NULL; 192 (void) close(fd); 193 fd = -1; 194 } 195 free((void *) pathname); 196 pathname = NULL; 197 } 198 199 if (entry != NULL) { 200 free((void *) entry); 201 } 202 if (dirp != NULL) { 203 (void) closedir(dirp); 204 } 205 if (pathname != NULL) { 206 free((void *) pathname); 207 } 208 if (fd != -1) { 209 (void) close(fd); 210 } 211 if (dbuf != NULL) { 212 free((void *) dbuf); 213 } 214 return tz; 215 } 216 217 #if defined(__linux__) || defined(MACOSX) 218 219 /* 220 * Performs Linux specific mapping and returns a zone ID 221 * if found. Otherwise, NULL is returned. 222 */ 223 static char * 224 getPlatformTimeZoneID() 225 { 226 struct stat statbuf; 227 char *tz = NULL; 228 FILE *fp; 229 int fd; 230 char *buf; 231 size_t size; 232 233 #ifdef __linux__ 234 /* 235 * Try reading the /etc/timezone file for Debian distros. There's 236 * no spec of the file format available. This parsing assumes that 237 * there's one line of an Olson tzid followed by a '\n', no 238 * leading or trailing spaces, no comments. 239 */ 240 if ((fp = fopen(ETC_TIMEZONE_FILE, "r")) != NULL) { 241 char line[256]; 242 243 if (fgets(line, sizeof(line), fp) != NULL) { 244 char *p = strchr(line, '\n'); 245 if (p != NULL) { 246 *p = '\0'; 247 } 248 if (strlen(line) > 0) { 249 tz = strdup(line); 250 } 251 } 252 (void) fclose(fp); 253 if (tz != NULL) { 254 return tz; 255 } 256 } 257 #endif /* __linux__ */ 258 259 /* 260 * Next, try /etc/localtime to find the zone ID. 261 */ 262 if (lstat(DEFAULT_ZONEINFO_FILE, &statbuf) == -1) { 263 return NULL; 264 } 265 266 /* 267 * If it's a symlink, get the link name and its zone ID part. (The 268 * older versions of timeconfig created a symlink as described in 269 * the Red Hat man page. It was changed in 1999 to create a copy 270 * of a zoneinfo file. It's no longer possible to get the zone ID 271 * from /etc/localtime.) 272 */ 273 if (S_ISLNK(statbuf.st_mode)) { 274 char linkbuf[PATH_MAX+1]; 275 int len; 276 277 if ((len = readlink(DEFAULT_ZONEINFO_FILE, linkbuf, sizeof(linkbuf)-1)) == -1) { 278 jio_fprintf(stderr, (const char *) "can't get a symlink of %s\n", 279 DEFAULT_ZONEINFO_FILE); 280 return NULL; 281 } 282 linkbuf[len] = '\0'; 283 tz = getZoneName(linkbuf); 284 if (tz != NULL) { 285 tz = strdup(tz); 286 return tz; 287 } 288 } 289 290 /* 291 * If it's a regular file, we need to find out the same zoneinfo file 292 * that has been copied as /etc/localtime. 293 * If initial symbolic link resolution failed, we should treat target 294 * file as a regular file. 295 */ 296 if ((fd = open(DEFAULT_ZONEINFO_FILE, O_RDONLY)) == -1) { 297 return NULL; 298 } 299 if (fstat(fd, &statbuf) == -1) { 300 (void) close(fd); 301 return NULL; 302 } 303 size = (size_t) statbuf.st_size; 304 buf = (char *) malloc(size); 305 if (buf == NULL) { 306 (void) close(fd); 307 return NULL; 308 } 309 310 if (read(fd, buf, size) != (ssize_t) size) { 311 (void) close(fd); 312 free((void *) buf); 313 return NULL; 314 } 315 (void) close(fd); 316 317 tz = findZoneinfoFile(buf, size, ZONEINFO_DIR); 318 free((void *) buf); 319 return tz; 320 } 321 #else 322 #ifdef __solaris__ 323 #if !defined(__sparcv9) && !defined(amd64) 324 325 /* 326 * Those file* functions mimic the UNIX stream io functions. This is 327 * because of the limitation of the number of open files on Solaris 328 * (32-bit mode only) due to the System V ABI. 329 */ 330 331 #define BUFFER_SIZE 4096 332 333 static struct iobuffer { 334 int magic; /* -1 to distinguish from the real FILE */ 335 int fd; /* file descriptor */ 336 char *buffer; /* pointer to buffer */ 337 char *ptr; /* current read pointer */ 338 char *endptr; /* end pointer */ 339 }; 340 341 static int 342 fileclose(FILE *stream) 343 { 344 struct iobuffer *iop = (struct iobuffer *) stream; 345 346 if (iop->magic != -1) { 347 return fclose(stream); 348 } 349 350 if (iop == NULL) { 351 return 0; 352 } 353 close(iop->fd); 354 free((void *)iop->buffer); 355 free((void *)iop); 356 return 0; 357 } 358 359 static FILE * 360 fileopen(const char *fname, const char *fmode) 361 { 362 FILE *fp; 363 int fd; 364 struct iobuffer *iop; 365 366 if ((fp = fopen(fname, fmode)) != NULL) { 367 return fp; 368 } 369 370 /* 371 * It assumes read open. 372 */ 373 if ((fd = open(fname, O_RDONLY)) == -1) { 374 return NULL; 375 } 376 377 /* 378 * Allocate struct iobuffer and its buffer 379 */ 380 iop = malloc(sizeof(struct iobuffer)); 381 if (iop == NULL) { 382 (void) close(fd); 383 errno = ENOMEM; 384 return NULL; 385 } 386 iop->magic = -1; 387 iop->fd = fd; 388 iop->buffer = malloc(BUFFER_SIZE); 389 if (iop->buffer == NULL) { 390 (void) close(fd); 391 free((void *) iop); 392 errno = ENOMEM; 393 return NULL; 394 } 395 iop->ptr = iop->buffer; 396 iop->endptr = iop->buffer; 397 return (FILE *)iop; 398 } 399 400 /* 401 * This implementation assumes that n is large enough and the line 402 * separator is '\n'. 403 */ 404 static char * 405 filegets(char *s, int n, FILE *stream) 406 { 407 struct iobuffer *iop = (struct iobuffer *) stream; 408 char *p; 409 410 if (iop->magic != -1) { 411 return fgets(s, n, stream); 412 } 413 414 p = s; 415 for (;;) { 416 char c; 417 418 if (iop->ptr == iop->endptr) { 419 ssize_t len; 420 421 if ((len = read(iop->fd, (void *)iop->buffer, BUFFER_SIZE)) == -1) { 422 return NULL; 423 } 424 if (len == 0) { 425 *p = 0; 426 if (s == p) { 427 return NULL; 428 } 429 return s; 430 } 431 iop->ptr = iop->buffer; 432 iop->endptr = iop->buffer + len; 433 } 434 c = *iop->ptr++; 435 *p++ = c; 436 if ((p - s) == (n - 1)) { 437 *p = 0; 438 return s; 439 } 440 if (c == '\n') { 441 *p = 0; 442 return s; 443 } 444 } 445 /*NOTREACHED*/ 446 } 447 #endif /* not __sparcv9 */ 448 449 450 /* 451 * Performs Solaris dependent mapping. Returns a zone ID if 452 * found. Otherwise, NULL is returned. Solaris libc looks up 453 * "/etc/default/init" to get the default TZ value if TZ is not defined 454 * as an environment variable. 455 */ 456 static char * 457 getPlatformTimeZoneID() 458 { 459 char *tz = NULL; 460 FILE *fp; 461 462 /* 463 * Try the TZ entry in /etc/default/init. 464 */ 465 if ((fp = fileopen(SYS_INIT_FILE, "r")) != NULL) { 466 char line[256]; 467 char quote = '\0'; 468 469 while (filegets(line, sizeof(line), fp) != NULL) { 470 char *p = line; 471 char *s; 472 char c; 473 474 /* quick check for comment lines */ 475 if (*p == '#') { 476 continue; 477 } 478 if (strncmp(p, "TZ=", 3) == 0) { 479 p += 3; 480 SKIP_SPACE(p); 481 c = *p; 482 if (c == '"' || c == '\'') { 483 quote = c; 484 p++; 485 } 486 487 /* 488 * PSARC/2001/383: quoted string support 489 */ 490 for (s = p; (c = *s) != '\0' && c != '\n'; s++) { 491 /* No '\\' is supported here. */ 492 if (c == quote) { 493 quote = '\0'; 494 break; 495 } 496 if (c == ' ' && quote == '\0') { 497 break; 498 } 499 } 500 if (quote != '\0') { 501 jio_fprintf(stderr, "ZoneInfo: unterminated time zone name in /etc/TIMEZONE\n"); 502 } 503 *s = '\0'; 504 tz = strdup(p); 505 break; 506 } 507 } 508 (void) fileclose(fp); 509 } 510 return tz; 511 } 512 513 #define TIMEZONE_FMRI "svc:/system/timezone:default" 514 #define TIMEZONE_PG "timezone" 515 #define LOCALTIME_PROP "localtime" 516 517 static void 518 cleanupScf(scf_handle_t *h, 519 scf_snapshot_t *snap, 520 scf_instance_t *inst, 521 scf_propertygroup_t *pg, 522 scf_property_t *prop, 523 scf_value_t *val, 524 char *buf) { 525 if (buf != NULL) { 526 free(buf); 527 } 528 if (snap != NULL) { 529 scf_snapshot_destroy(snap); 530 } 531 if (val != NULL) { 532 scf_value_destroy(val); 533 } 534 if (prop != NULL) { 535 scf_property_destroy(prop); 536 } 537 if (pg != NULL) { 538 scf_pg_destroy(pg); 539 } 540 if (inst != NULL) { 541 scf_instance_destroy(inst); 542 } 543 if (h != NULL) { 544 scf_handle_destroy(h); 545 } 546 } 547 548 /* 549 * Retruns a zone ID of Solaris when the TZ value is "localtime". 550 * First, it tries scf. If scf fails, it looks for the same file as 551 * /usr/share/lib/zoneinfo/localtime under /usr/share/lib/zoneinfo/. 552 */ 553 static char * 554 getSolarisDefaultZoneID() { 555 char *tz = NULL; 556 struct stat statbuf; 557 size_t size; 558 char *buf; 559 int fd; 560 /* scf specific variables */ 561 scf_handle_t *h = NULL; 562 scf_snapshot_t *snap = NULL; 563 scf_instance_t *inst = NULL; 564 scf_propertygroup_t *pg = NULL; 565 scf_property_t *prop = NULL; 566 scf_value_t *val = NULL; 567 568 if ((h = scf_handle_create(SCF_VERSION)) != NULL 569 && scf_handle_bind(h) == 0 570 && (inst = scf_instance_create(h)) != NULL 571 && (snap = scf_snapshot_create(h)) != NULL 572 && (pg = scf_pg_create(h)) != NULL 573 && (prop = scf_property_create(h)) != NULL 574 && (val = scf_value_create(h)) != NULL 575 && scf_handle_decode_fmri(h, TIMEZONE_FMRI, NULL, NULL, inst, 576 NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) == 0 577 && scf_instance_get_snapshot(inst, "running", snap) == 0 578 && scf_instance_get_pg_composed(inst, snap, TIMEZONE_PG, pg) == 0 579 && scf_pg_get_property(pg, LOCALTIME_PROP, prop) == 0 580 && scf_property_get_value(prop, val) == 0) { 581 ssize_t len; 582 583 /* Gets the length of the zone ID string */ 584 len = scf_value_get_astring(val, NULL, 0); 585 if (len != -1) { 586 tz = malloc(++len); /* +1 for a null byte */ 587 if (tz != NULL && scf_value_get_astring(val, tz, len) != -1) { 588 cleanupScf(h, snap, inst, pg, prop, val, NULL); 589 return tz; 590 } 591 } 592 } 593 cleanupScf(h, snap, inst, pg, prop, val, tz); 594 595 if (stat(DEFAULT_ZONEINFO_FILE, &statbuf) == -1) { 596 return NULL; 597 } 598 size = (size_t) statbuf.st_size; 599 buf = malloc(size); 600 if (buf == NULL) { 601 return NULL; 602 } 603 if ((fd = open(DEFAULT_ZONEINFO_FILE, O_RDONLY)) == -1) { 604 free((void *) buf); 605 return NULL; 606 } 607 608 if (read(fd, buf, size) != (ssize_t) size) { 609 (void) close(fd); 610 free((void *) buf); 611 return NULL; 612 } 613 (void) close(fd); 614 tz = findZoneinfoFile(buf, size, ZONEINFO_DIR); 615 free((void *) buf); 616 return tz; 617 } 618 #endif /*__solaris__*/ 619 #endif /*__linux__*/ 620 621 #ifdef _AIX 622 static char * 623 getPlatformTimeZoneID() 624 { 625 FILE *fp; 626 char *tz = NULL; 627 char *tz_key = "TZ="; 628 char line[256]; 629 size_t tz_key_len = strlen(tz_key); 630 631 if ((fp = fopen(ETC_ENVIRONMENT_FILE, "r")) != NULL) { 632 while (fgets(line, sizeof(line), fp) != NULL) { 633 char *p = strchr(line, '\n'); 634 if (p != NULL) { 635 *p = '\0'; 636 } 637 if (0 == strncmp(line, tz_key, tz_key_len)) { 638 tz = strdup(line + tz_key_len); 639 break; 640 } 641 } 642 (void) fclose(fp); 643 } 644 645 return tz; 646 } 647 static char *mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz); 648 #endif 649 650 /* 651 * findJavaTZ_md() maps platform time zone ID to Java time zone ID 652 * using <java_home>/lib/tzmappings. If the TZ value is not found, it 653 * trys some libc implementation dependent mappings. If it still 654 * can't map to a Java time zone ID, it falls back to the GMT+/-hh:mm 655 * form. 656 */ 657 /*ARGSUSED1*/ 658 char * 659 findJavaTZ_md(const char *java_home_dir) 660 { 661 char *tz; 662 char *javatz = NULL; 663 char *freetz = NULL; 664 665 tz = getenv("TZ"); 666 667 #if defined(__linux__) || defined(_ALLBSD_SOURCE) 668 if (tz == NULL) { 669 #else 670 #if defined (__solaris__) || defined(_AIX) 671 if (tz == NULL || *tz == '\0') { 672 #endif 673 #endif 674 tz = getPlatformTimeZoneID(); 675 freetz = tz; 676 } 677 678 /* 679 * Remove any preceding ':' 680 */ 681 if (tz != NULL && *tz == ':') { 682 tz++; 683 } 684 685 #ifdef __solaris__ 686 if (tz != NULL && strcmp(tz, "localtime") == 0) { 687 tz = getSolarisDefaultZoneID(); 688 if (freetz != NULL) { 689 free((void *) freetz); 690 } 691 freetz = tz; 692 } 693 #endif 694 695 if (tz != NULL) { 696 #ifdef __linux__ 697 /* 698 * Ignore "posix/" prefix. 699 */ 700 if (strncmp(tz, "posix/", 6) == 0) { 701 tz += 6; 702 } 703 #endif 704 javatz = strdup(tz); 705 if (freetz != NULL) { 706 free((void *) freetz); 707 } 708 709 #ifdef _AIX 710 freetz = mapPlatformToJavaTimezone(java_home_dir, javatz); 711 if (javatz != NULL) { 712 free((void *) javatz); 713 } 714 javatz = freetz; 715 #endif 716 } 717 718 return javatz; 719 } 720 721 /** 722 * Returns a GMT-offset-based zone ID. (e.g., "GMT-08:00") 723 */ 724 725 #ifdef MACOSX 726 727 char * 728 getGMTOffsetID() 729 { 730 time_t offset; 731 char sign, buf[32]; 732 struct tm *local_tm; 733 time_t clock; 734 time_t currenttime; 735 736 clock = time(NULL); 737 tzset(); 738 local_tm = localtime(&clock); 739 if (local_tm->tm_gmtoff >= 0) { 740 offset = (time_t) local_tm->tm_gmtoff; 741 sign = '+'; 742 } else { 743 offset = (time_t) -local_tm->tm_gmtoff; 744 sign = '-'; 745 } 746 sprintf(buf, (const char *)"GMT%c%02d:%02d", 747 sign, (int)(offset/3600), (int)((offset%3600)/60)); 748 return strdup(buf); 749 } 750 #else 751 752 char * 753 getGMTOffsetID() 754 { 755 time_t offset; 756 char sign, buf[32]; 757 #ifdef __solaris__ 758 struct tm localtm; 759 time_t currenttime; 760 761 currenttime = time(NULL); 762 if (localtime_r(¤ttime, &localtm) == NULL) { 763 return NULL; 764 } 765 766 offset = localtm.tm_isdst ? altzone : timezone; 767 #else 768 offset = timezone; 769 #endif /*__linux__*/ 770 771 if (offset == 0) { 772 return strdup("GMT"); 773 } 774 775 /* Note that the time offset direction is opposite. */ 776 if (offset > 0) { 777 sign = '-'; 778 } else { 779 offset = -offset; 780 sign = '+'; 781 } 782 sprintf(buf, (const char *)"GMT%c%02d:%02d", 783 sign, (int)(offset/3600), (int)((offset%3600)/60)); 784 return strdup(buf); 785 } 786 #endif /* MACOSX */ 787 788 #ifdef _AIX 789 static char * 790 mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) { 791 FILE *tzmapf; 792 char mapfilename[PATH_MAX+1]; 793 char line[256]; 794 int linecount = 0; 795 char temp[100], *temp_tz; 796 char *javatz = NULL; 797 char *str_tmp = NULL; 798 size_t temp_tz_len = 0; 799 800 /* On AIX, the TZ environment variable may end with a comma 801 * followed by modifier fields. These are ignored here. 802 */ 803 strncpy(temp, tz, 100); 804 temp_tz = strtok_r(temp, ",", &str_tmp); 805 806 if(temp_tz == NULL) 807 goto tzerr; 808 809 temp_tz_len = strlen(temp_tz); 810 811 if (strlen(java_home_dir) >= (PATH_MAX - 15)) { 812 jio_fprintf(stderr, "java.home longer than maximum path length \n"); 813 goto tzerr; 814 } 815 816 strncpy(mapfilename, java_home_dir, PATH_MAX); 817 strcat(mapfilename, "/lib/tzmappings"); 818 819 if ((tzmapf = fopen(mapfilename, "r")) == NULL) { 820 jio_fprintf(stderr, "can't open %s\n", mapfilename); 821 goto tzerr; 822 } 823 824 while (fgets(line, sizeof(line), tzmapf) != NULL) { 825 char *p = line; 826 char *sol = line; 827 char *java; 828 int result; 829 830 linecount++; 831 /* 832 * Skip comments and blank lines 833 */ 834 if (*p == '#' || *p == '\n') { 835 continue; 836 } 837 838 /* 839 * Get the first field, platform zone ID 840 */ 841 while (*p != '\0' && *p != '\t') { 842 p++; 843 } 844 if (*p == '\0') { 845 /* mapping table is broken! */ 846 jio_fprintf(stderr, "tzmappings: Illegal format at near line %d.\n", linecount); 847 break; 848 } 849 850 *p++ = '\0'; 851 if ((result = strncmp(temp_tz, sol, temp_tz_len)) == 0) { 852 /* 853 * If this is the current platform zone ID, 854 * take the Java time zone ID (2nd field). 855 */ 856 java = p; 857 while (*p != '\0' && *p != '\n') { 858 p++; 859 } 860 861 if (*p == '\0') { 862 /* mapping table is broken! */ 863 jio_fprintf(stderr, "tzmappings: Illegal format at line %d.\n", linecount); 864 break; 865 } 866 867 *p = '\0'; 868 javatz = strdup(java); 869 break; 870 } else if (result < 0) { 871 break; 872 } 873 } 874 (void) fclose(tzmapf); 875 876 tzerr: 877 if (javatz == NULL) { 878 return getGMTOffsetID(); 879 } 880 881 return javatz; 882 } 883 #endif 884