8134505: Cleanup of "TimeZone_md.c"

Reviewed-by: rriggs, dsamersoff, simonis
This commit is contained in:
Christoph Langer 2015-09-10 17:56:24 +02:00 committed by Volker Simonis
parent 7c9b107d1f
commit 981fa17133

View File

@ -35,14 +35,20 @@
#include <string.h> #include <string.h>
#include <dirent.h> #include <dirent.h>
#include <unistd.h> #include <unistd.h>
#ifdef __solaris__ #if defined(__solaris__)
#include <libscf.h> #include <libscf.h>
#endif #endif
#include "jvm.h" #include "jvm.h"
#include "TimeZone_md.h"
#define SKIP_SPACE(p) while (*p == ' ' || *p == '\t') p++; #define SKIP_SPACE(p) while (*p == ' ' || *p == '\t') p++;
#if defined(_ALLBSD_SOURCE)
#define dirent64 dirent
#define readdir64_r readdir_r
#endif
#if !defined(__solaris__) || defined(__sparcv9) || defined(amd64) #if !defined(__solaris__) || defined(__sparcv9) || defined(amd64)
#define fileopen fopen #define fileopen fopen
#define filegets fgets #define filegets fgets
@ -50,19 +56,20 @@
#endif #endif
#if defined(__linux__) || defined(_ALLBSD_SOURCE) #if defined(__linux__) || defined(_ALLBSD_SOURCE)
static const char *ETC_TIMEZONE_FILE = "/etc/timezone"; static const char *ETC_TIMEZONE_FILE = "/etc/timezone";
static const char *ZONEINFO_DIR = "/usr/share/zoneinfo"; static const char *ZONEINFO_DIR = "/usr/share/zoneinfo";
static const char *DEFAULT_ZONEINFO_FILE = "/etc/localtime"; static const char *DEFAULT_ZONEINFO_FILE = "/etc/localtime";
#else #else
#ifdef _AIX
static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
#endif
static const char *SYS_INIT_FILE = "/etc/default/init"; static const char *SYS_INIT_FILE = "/etc/default/init";
static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo"; static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo";
static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime"; static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime";
#endif /*__linux__*/ #endif /* defined(__linux__) || defined(_ALLBSD_SOURCE) */
#if defined(_AIX)
static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
#endif
#if defined(__linux__) || defined(MACOSX) || defined(__solaris__)
/* /*
* Returns a pointer to the zone ID portion of the given zoneinfo file * Returns a pointer to the zone ID portion of the given zoneinfo file
@ -108,8 +115,8 @@ findZoneinfoFile(char *buf, size_t size, const char *dir)
{ {
DIR *dirp = NULL; DIR *dirp = NULL;
struct stat statbuf; struct stat statbuf;
struct dirent *dp = NULL; struct dirent64 *dp = NULL;
struct dirent *entry = NULL; struct dirent64 *entry = NULL;
char *pathname = NULL; char *pathname = NULL;
int fd = -1; int fd = -1;
char *dbuf = NULL; char *dbuf = NULL;
@ -120,19 +127,13 @@ findZoneinfoFile(char *buf, size_t size, const char *dir)
return NULL; return NULL;
} }
entry = (struct dirent *) malloc((size_t) pathconf(dir, _PC_NAME_MAX)); entry = (struct dirent64 *) malloc((size_t) pathconf(dir, _PC_NAME_MAX));
if (entry == NULL) { if (entry == NULL) {
(void) closedir(dirp); (void) closedir(dirp);
return NULL; return NULL;
} }
#if defined(_AIX) || defined(__linux__) || defined(MACOSX) || (defined(__solaris__) \ while (readdir64_r(dirp, entry, &dp) == 0 && dp != NULL) {
&& (defined(_POSIX_PTHREAD_SEMANTICS) || defined(_LP64)))
while (readdir_r(dirp, entry, &dp) == 0 && dp != NULL) {
#else
while ((dp = readdir_r(dirp, entry)) != NULL) {
#endif
/* /*
* Skip '.' and '..' (and possibly other .* files) * Skip '.' and '..' (and possibly other .* files)
*/ */
@ -145,7 +146,7 @@ findZoneinfoFile(char *buf, size_t size, const char *dir)
*/ */
if ((strcmp(dp->d_name, "ROC") == 0) if ((strcmp(dp->d_name, "ROC") == 0)
|| (strcmp(dp->d_name, "posixrules") == 0) || (strcmp(dp->d_name, "posixrules") == 0)
#ifdef __solaris__ #if defined(__solaris__)
/* /*
* Skip the "src" and "tab" directories on Solaris. * Skip the "src" and "tab" directories on Solaris.
*/ */
@ -230,7 +231,7 @@ getPlatformTimeZoneID()
char *buf; char *buf;
size_t size; size_t size;
#ifdef __linux__ #if defined(__linux__)
/* /*
* Try reading the /etc/timezone file for Debian distros. There's * Try reading the /etc/timezone file for Debian distros. There's
* no spec of the file format available. This parsing assumes that * no spec of the file format available. This parsing assumes that
@ -254,7 +255,7 @@ getPlatformTimeZoneID()
return tz; return tz;
} }
} }
#endif /* __linux__ */ #endif /* defined(__linux__) */
/* /*
* Next, try /etc/localtime to find the zone ID. * Next, try /etc/localtime to find the zone ID.
@ -318,8 +319,9 @@ getPlatformTimeZoneID()
free((void *) buf); free((void *) buf);
return tz; return tz;
} }
#else
#ifdef __solaris__ #elif defined(__solaris__)
#if !defined(__sparcv9) && !defined(amd64) #if !defined(__sparcv9) && !defined(amd64)
/* /*
@ -444,8 +446,7 @@ filegets(char *s, int n, FILE *stream)
} }
/*NOTREACHED*/ /*NOTREACHED*/
} }
#endif /* not __sparcv9 */ #endif /* !defined(__sparcv9) && !defined(amd64) */
/* /*
* Performs Solaris dependent mapping. Returns a zone ID if * Performs Solaris dependent mapping. Returns a zone ID if
@ -546,7 +547,7 @@ cleanupScf(scf_handle_t *h,
} }
/* /*
* Retruns a zone ID of Solaris when the TZ value is "localtime". * Returns a zone ID of Solaris when the TZ value is "localtime".
* First, it tries scf. If scf fails, it looks for the same file as * First, it tries scf. If scf fails, it looks for the same file as
* /usr/share/lib/zoneinfo/localtime under /usr/share/lib/zoneinfo/. * /usr/share/lib/zoneinfo/localtime under /usr/share/lib/zoneinfo/.
*/ */
@ -615,10 +616,11 @@ getSolarisDefaultZoneID() {
free((void *) buf); free((void *) buf);
return tz; return tz;
} }
#endif /*__solaris__*/
#endif /*__linux__*/
#ifdef _AIX #endif /* defined(__solaris__) */
#elif defined(_AIX)
static char * static char *
getPlatformTimeZoneID() getPlatformTimeZoneID()
{ {
@ -644,178 +646,33 @@ getPlatformTimeZoneID()
return tz; return tz;
} }
static char *mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz);
#endif
/*
* 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
* trys 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(const char *java_home_dir)
{
char *tz;
char *javatz = NULL;
char *freetz = NULL;
tz = getenv("TZ");
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
if (tz == NULL) {
#else
#if defined (__solaris__) || defined(_AIX)
if (tz == NULL || *tz == '\0') {
#endif
#endif
tz = getPlatformTimeZoneID();
freetz = tz;
}
/*
* Remove any preceding ':'
*/
if (tz != NULL && *tz == ':') {
tz++;
}
#ifdef __solaris__
if (tz != NULL && strcmp(tz, "localtime") == 0) {
tz = getSolarisDefaultZoneID();
if (freetz != NULL) {
free((void *) freetz);
}
freetz = tz;
}
#endif
if (tz != NULL) {
#ifdef __linux__
/*
* Ignore "posix/" prefix.
*/
if (strncmp(tz, "posix/", 6) == 0) {
tz += 6;
}
#endif
javatz = strdup(tz);
if (freetz != NULL) {
free((void *) freetz);
}
#ifdef _AIX
freetz = mapPlatformToJavaTimezone(java_home_dir, javatz);
if (javatz != NULL) {
free((void *) javatz);
}
javatz = freetz;
#endif
}
return javatz;
}
/**
* Returns a GMT-offset-based zone ID. (e.g., "GMT-08:00")
*/
#ifdef MACOSX
char *
getGMTOffsetID()
{
time_t offset;
char sign, buf[32];
struct tm *local_tm;
time_t clock;
time_t currenttime;
clock = time(NULL);
tzset();
local_tm = localtime(&clock);
if (local_tm->tm_gmtoff >= 0) {
offset = (time_t) local_tm->tm_gmtoff;
sign = '+';
} else {
offset = (time_t) -local_tm->tm_gmtoff;
sign = '-';
}
sprintf(buf, (const char *)"GMT%c%02d:%02d",
sign, (int)(offset/3600), (int)((offset%3600)/60));
return strdup(buf);
}
#else
char *
getGMTOffsetID()
{
time_t offset;
char sign, buf[32];
#ifdef __solaris__
struct tm localtm;
time_t currenttime;
currenttime = time(NULL);
if (localtime_r(&currenttime, &localtm) == NULL) {
return NULL;
}
offset = localtm.tm_isdst ? altzone : timezone;
#else
offset = timezone;
#endif /*__linux__*/
if (offset == 0) {
return strdup("GMT");
}
/* Note that the time offset direction is opposite. */
if (offset > 0) {
sign = '-';
} else {
offset = -offset;
sign = '+';
}
sprintf(buf, (const char *)"GMT%c%02d:%02d",
sign, (int)(offset/3600), (int)((offset%3600)/60));
return strdup(buf);
}
#endif /* MACOSX */
#ifdef _AIX
static char * static char *
mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) { mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) {
FILE *tzmapf; FILE *tzmapf;
char mapfilename[PATH_MAX + 1]; char mapfilename[PATH_MAX + 1];
char line[256]; char line[256];
int linecount = 0; int linecount = 0;
char temp[100], *temp_tz; char *tz_buf = NULL;
char *temp_tz = NULL;
char *javatz = NULL; char *javatz = NULL;
char *str_tmp = NULL; size_t tz_len = 0;
size_t temp_tz_len = 0;
/* On AIX, the TZ environment variable may end with a comma /* On AIX, the TZ environment variable may end with a comma
* followed by modifier fields. These are ignored here. * followed by modifier fields. These are ignored here. */
*/ temp_tz = strchr(tz, ',');
strncpy(temp, tz, 100); tz_len = (temp_tz == NULL) ? strlen(tz) : temp_tz - tz;
temp_tz = strtok_r(temp, ",", &str_tmp); tz_buf = (char *)malloc(tz_len + 1);
memcpy(tz_buf, tz, tz_len);
tz_buf[tz_len] = 0;
if(temp_tz == NULL) /* Open tzmappings file, with buffer overrun check */
goto tzerr; if ((strlen(java_home_dir) + 15) > PATH_MAX) {
jio_fprintf(stderr, "Path %s/lib/tzmappings exceeds maximum path length\n", java_home_dir);
temp_tz_len = strlen(temp_tz);
if (strlen(java_home_dir) >= (PATH_MAX - 15)) {
jio_fprintf(stderr, "java.home longer than maximum path length \n");
goto tzerr; goto tzerr;
} }
strcpy(mapfilename, java_home_dir);
strncpy(mapfilename, java_home_dir, PATH_MAX);
strcat(mapfilename, "/lib/tzmappings"); strcat(mapfilename, "/lib/tzmappings");
if ((tzmapf = fopen(mapfilename, "r")) == NULL) { if ((tzmapf = fopen(mapfilename, "r")) == NULL) {
jio_fprintf(stderr, "can't open %s\n", mapfilename); jio_fprintf(stderr, "can't open %s\n", mapfilename);
goto tzerr; goto tzerr;
@ -848,7 +705,7 @@ mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) {
} }
*p++ = '\0'; *p++ = '\0';
if ((result = strncmp(temp_tz, sol, temp_tz_len)) == 0) { if ((result = strncmp(tz_buf, sol, tz_len)) == 0) {
/* /*
* If this is the current platform zone ID, * If this is the current platform zone ID,
* take the Java time zone ID (2nd field). * take the Java time zone ID (2nd field).
@ -874,11 +731,150 @@ mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) {
(void) fclose(tzmapf); (void) fclose(tzmapf);
tzerr: tzerr:
if (tz_buf != NULL ) {
free((void *) tz_buf);
}
if (javatz == NULL) { if (javatz == NULL) {
return getGMTOffsetID(); return getGMTOffsetID();
} }
return javatz; return javatz;
} }
#endif /* defined(_AIX) */
/*
* 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
* trys 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(const char *java_home_dir)
{
char *tz;
char *javatz = NULL;
char *freetz = NULL;
tz = getenv("TZ");
if (tz == NULL || *tz == '\0') {
tz = getPlatformTimeZoneID();
freetz = tz;
}
if (tz != NULL) {
/* Ignore preceding ':' */
if (*tz == ':') {
tz++;
}
#if defined(__linux__)
/* Ignore "posix/" prefix on Linux. */
if (strncmp(tz, "posix/", 6) == 0) {
tz += 6;
}
#endif #endif
#if defined(_AIX)
/* On AIX do the platform to Java mapping. */
javatz = mapPlatformToJavaTimezone(java_home_dir, tz);
if (freetz != NULL) {
free((void *) freetz);
}
#else
#if defined(__solaris__)
/* Solaris might use localtime, so handle it here. */
if (strcmp(tz, "localtime") == 0) {
javatz = getSolarisDefaultZoneID();
if (freetz != NULL) {
free((void *) freetz);
}
} else
#endif
if (freetz == NULL) {
/* strdup if we are still working on getenv result. */
javatz = strdup(tz);
} else if (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
}
return javatz;
}
/**
* Returns a GMT-offset-based zone ID. (e.g., "GMT-08:00")
*/
#if defined(MACOSX)
char *
getGMTOffsetID()
{
time_t offset;
char sign, buf[32];
struct tm *local_tm;
time_t clock;
time_t currenttime;
clock = time(NULL);
tzset();
local_tm = localtime(&clock);
if (local_tm->tm_gmtoff >= 0) {
offset = (time_t) local_tm->tm_gmtoff;
sign = '+';
} else {
offset = (time_t) -local_tm->tm_gmtoff;
sign = '-';
}
sprintf(buf, (const char *)"GMT%c%02d:%02d",
sign, (int)(offset/3600), (int)((offset%3600)/60));
return strdup(buf);
}
#else
char *
getGMTOffsetID()
{
time_t offset;
char sign, buf[32];
#if defined(__solaris__)
struct tm localtm;
time_t currenttime;
currenttime = time(NULL);
if (localtime_r(&currenttime, &localtm) == NULL) {
return NULL;
}
offset = localtm.tm_isdst ? altzone : timezone;
#else
offset = timezone;
#endif
if (offset == 0) {
return strdup("GMT");
}
/* Note that the time offset direction is opposite. */
if (offset > 0) {
sign = '-';
} else {
offset = -offset;
sign = '+';
}
sprintf(buf, (const char *)"GMT%c%02d:%02d",
sign, (int)(offset/3600), (int)((offset%3600)/60));
return strdup(buf);
}
#endif /* MACOSX */