--- old/src/solaris/native/java/util/TimeZone_md.c 2013-08-23 16:46:52.053736275 -0400 +++ new/src/solaris/native/java/util/TimeZone_md.c 2013-08-23 16:46:51.875734494 -0400 @@ -53,6 +53,7 @@ static const char *ETC_TIMEZONE_FILE = "/etc/timezone"; +static const char *ETC_SYSCONFIG_CLOCK_FILE = "/etc/sysconfig/clock"; static const char *ZONEINFO_DIR = "/usr/share/zoneinfo"; static const char *DEFAULT_ZONEINFO_FILE = "/etc/localtime"; #else @@ -94,6 +95,95 @@ } /* + * Reads the entire contents of a file. The return value is negative if + * an error occurs. + */ +static int +readEntireFile(const char *file_name, char **contents) { + FILE *file = fopen(file_name, "re"); + if (!file) { + return -ENOENT; + } + + char *p = NULL; + + size_t allocated_size = 0; + size_t total_read = 0; + size_t bytes_read = -1; + + for (;;) { + size_t room = allocated_size - total_read; + if (room == 0) { + allocated_size += 256; + char *temp_p = realloc(p, allocated_size); + if (temp_p == NULL) { + return -ENOMEM; + } + p = temp_p; + room = allocated_size - total_read; + } + + bytes_read = fread(p+total_read, 1, room, file); + + if (bytes_read < room) { + if (ferror(file) != 0) { + goto fail; + } + break; + } + + total_read += bytes_read; + } + p[allocated_size-1] = '\0'; + + fclose(file); + *contents = p; + return 0; + +fail: + fclose(file); + return -1; +} + +/* + * Reads the value of ZONE variable from the given clock file. + */ +static char* +readTimeZoneFromSysconfigClock(const char* path) { + + /* + * the file is a shell-script like file with key/value pairs + * that looks like this: + * KEY="VALUE" + */ + + char *contents = NULL; + int r = readEntireFile(path, &contents); + if (r < 0) { + return NULL; + } + + char *start = NULL; + start = strstr(contents, "ZONE=\""); + if (start == NULL) { + goto fail; + } + start = start + strlen("ZONE=\""); + char *end; + end = strchr(start, '"'); + if (end == NULL) { + goto fail; + } + char *tz_name = strndup(start, (end-start)); + free(contents); + return tz_name; + +fail: + free(contents); + return NULL; +} + +/* * 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'. @@ -251,6 +341,14 @@ return tz; } } + + /* + * Try reading the /etc/sysconfig/clock file for Red Hat-like distros. + */ + if ((tz = readTimeZoneFromSysconfigClock(ETC_SYSCONFIG_CLOCK_FILE)) != NULL) { + return tz; + } + #endif /* __linux__ */ /*