/* * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/* * Returns a pointer to the zone ID portion of the given zoneinfo file * name, or NULL if the given string doesn't contain "zoneinfo/".
*/ staticchar *
getZoneName(char *str)
{ staticconstchar *zidir = "zoneinfo/";
/* * Returns a path name created from the given 'dir' and 'name' under * UNIX. This function allocates memory for the pathname calling * malloc(). NULL is returned if malloc() fails.
*/ staticchar *
getPathName(constchar *dir, constchar *name) { char *path;
/* * Scans the specified directory and its subdirectories to find a * zoneinfo file which has the same content as /etc/localtime on Linux * or /usr/share/lib/zoneinfo/localtime on Solaris given in 'buf'. * If file is symbolic link, then the contents it points to are in buf. * Returns a zone ID if found, otherwise, NULL is returned.
*/ staticchar *
findZoneinfoFile(char *buf, size_t size, constchar *dir)
{
DIR *dirp = NULL; struct dirent *dp = NULL; char *pathname = NULL; char *tz = NULL;
if (strcmp(dir, ZONEINFO_DIR) == 0) { /* fast path for 1st iteration */ for (unsignedint i = 0; i < sizeof (popularZones) / sizeof (popularZones[0]); i++) {
pathname = getPathName(dir, popularZones[i]); if (pathname == NULL) { continue;
}
tz = isFileIdentical(buf, size, pathname);
free((void *) pathname);
pathname = NULL; if (tz != NULL) { return tz;
}
}
}
/* * Checks if the file pointed to by pathname matches * the data contents in buf. * Returns a representation of the timezone file name * if file match is found, otherwise NULL.
*/ staticchar *
isFileIdentical(char *buf, size_t size, char *pathname)
{ char *possibleMatch = NULL; struct stat64 statbuf; char *dbuf = NULL; int fd = -1; int res;
/* * Performs Linux specific mapping and returns a zone ID * if found. Otherwise, NULL is returned.
*/ staticchar *
getPlatformTimeZoneID()
{ struct stat64 statbuf; char *tz = NULL;
FILE *fp; int fd; char *buf;
size_t size; int res;
#ifdefined(__linux__) /* * Try reading the /etc/timezone file for Debian distros. There's * no spec of the file format available. This parsing assumes that * there's one line of an Olson tzid followed by a '\n', no * leading or trailing spaces, no comments.
*/ if ((fp = fopen(ETC_TIMEZONE_FILE, "r")) != NULL) { char line[256];
/* * Next, try /etc/localtime to find the zone ID.
*/
RESTARTABLE(lstat64(DEFAULT_ZONEINFO_FILE, &statbuf), res); if (res == -1) { return NULL;
}
/* * If it's a symlink, get the link name and its zone ID part. (The * older versions of timeconfig created a symlink as described in * the Red Hat man page. It was changed in 1999 to create a copy * of a zoneinfo file. It's no longer possible to get the zone ID * from /etc/localtime.)
*/ if (S_ISLNK(statbuf.st_mode)) { char linkbuf[PATH_MAX+1]; int len;
if ((len = readlink(DEFAULT_ZONEINFO_FILE, linkbuf, sizeof(linkbuf)-1)) == -1) {
jio_fprintf(stderr, (constchar *) "can't get a symlink of %s\n",
DEFAULT_ZONEINFO_FILE); return NULL;
}
linkbuf[len] = '\0';
removeDuplicateSlashes(linkbuf);
collapse(linkbuf);
tz = getZoneName(linkbuf); if (tz != NULL) {
tz = strdup(tz); return tz;
}
}
/* * If it's a regular file, we need to find out the same zoneinfo file * that has been copied as /etc/localtime. * If initial symbolic link resolution failed, we should treat target * file as a regular file.
*/
RESTARTABLE(open(DEFAULT_ZONEINFO_FILE, O_RDONLY), fd); if (fd == -1) { return NULL;
}
/* On AIX, the TZ environment variable may end with a comma * followed by modifier fields until early AIX6.1.
* This restriction has been removed from AIX7. */
tz_buf = strdup(tz);
tz_len = strlen(tz_buf);
/* Open tzmappings file, with buffer overrun check */ if ((strlen(java_home_dir) + 15) > PATH_MAX) {
jio_fprintf(stderr, "Path %s/lib/tzmappings exceeds maximum path length\n", java_home_dir); goto tzerr;
}
strcpy(mapfilename, java_home_dir);
strcat(mapfilename, "/lib/tzmappings"); if ((tzmapf = fopen(mapfilename, "r")) == NULL) {
jio_fprintf(stderr, "can't open %s\n", mapfilename); goto tzerr;
}
while (fgets(line, sizeof(line), tzmapf) != NULL) { char *p = line; char *sol = line; char *java; int result;
linecount++; /* * Skip comments and blank lines
*/ if (*p == '#' || *p == '\n') { continue;
}
/* * Get the first field, platform zone ID
*/ while (*p != '\0' && *p != '\t') {
p++;
} if (*p == '\0') { /* mapping table is broken! */
jio_fprintf(stderr, "tzmappings: Illegal format at near line %d.\n", linecount); break;
}
*p++ = '\0'; if ((result = strncmp(tz_buf, sol, tz_len)) == 0) { /* * If this is the current platform zone ID, * take the Java time zone ID (2nd field).
*/
java = p; while (*p != '\0' && *p != '\n') {
p++;
}
if (*p == '\0') { /* mapping table is broken! */
jio_fprintf(stderr, "tzmappings: Illegal format at line %d.\n", linecount); break;
}
/* * findJavaTZ_md() maps platform time zone ID to Java time zone ID * using <java_home>/lib/tzmappings. If the TZ value is not found, it * tries some libc implementation dependent mappings. If it still * can't map to a Java time zone ID, it falls back to the GMT+/-hh:mm * form.
*/ /*ARGSUSED1*/ char *
findJavaTZ_md(constchar *java_home_dir)
{ char *tz; char *javatz = NULL; char *freetz = NULL;
if (tz != NULL) { /* Ignore preceding ':' */ if (*tz == ':') {
tz++;
} #ifdefined(__linux__) /* Ignore "posix/" prefix on Linux. */ if (strncmp(tz, "posix/", 6) == 0) {
tz += 6;
} #endif
#ifdefined(_AIX) /* On AIX do the platform to Java mapping. */
javatz = mapPlatformToJavaTimezone(java_home_dir, tz); if (freetz != NULL) {
free((void *) freetz);
} #else if (freetz == NULL) { /* strdup if we are still working on getenv result. */
javatz = strdup(tz);
} elseif (freetz != tz) { /* strdup and free the old buffer, if we moved the pointer. */
javatz = strdup(tz);
free((void *) freetz);
} else { /* we are good if we already work on a freshly allocated buffer. */
javatz = tz;
} #endif
}
#ifdefined(_AIX) // strftime() with "%z" does not return ISO 8601 format by AIX default. // XPG_SUS_ENV=ON environment variable is required. // But Hotspot does not support XPG_SUS_ENV=ON. // Ignore daylight saving settings to calculate current time difference
localtm.tm_isdst = 0; int gmt_off = (int)(difftime(mktime(&localtm), mktime(&gmt)) / 60.0);
sprintf(buf, (constchar *)"GMT%c%02.2d:%02.2d",
gmt_off < 0 ? '-' : '+' , abs(gmt_off / 60), gmt_off % 60); #else if (strftime(offset, 6, "%z", &localtm) != 5) { return strdup("GMT");
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.