src/solaris/native/java/util/TimeZone_md.c

Print this page

        

*** 51,60 **** --- 51,61 ---- #if defined(__linux__) || defined(_ALLBSD_SOURCE) 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 static const char *SYS_INIT_FILE = "/etc/default/init"; static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo";
*** 92,101 **** --- 93,191 ---- } return strcat(strcat(strcpy(path, dir), "/"), name); } /* + * 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'. * If file is symbolic link, then the contents it points to are in buf. * Returns a zone ID if found, otherwise, NULL is returned.
*** 249,258 **** --- 339,356 ---- (void) fclose(fp); if (tz != NULL) { 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__ */ /* * Next, try /etc/localtime to find the zone ID. */