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

Print this page

        

@@ -94,13 +94,13 @@
 }
 
 /*
  * 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 (most likely a symbolic link)
- * on Solaris given in 'buf'. Returns a zone ID if found, otherwise,
- * NULL is returned.
+ * 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.
  */
 static char *
 findZoneinfoFile(char *buf, size_t size, const char *dir)
 {
     DIR *dirp = NULL;

@@ -224,10 +224,11 @@
     char *tz = NULL;
     FILE *fp;
     int fd;
     char *buf;
     size_t size;
+    char linkbuf[PATH_MAX+1];
 
 #ifdef __linux__
     /*
      * Try reading the /etc/timezone file for Debian distros. There's
      * no spec of the file format available. This parsing assumes that

@@ -265,12 +266,13 @@
      * 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.)
      */
+    strcpy(linkbuf, DEFAULT_ZONEINFO_FILE);
+    linkbuf[strlen(DEFAULT_ZONEINFO_FILE)] = '\0';
     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, (const char *) "can't get a symlink of %s\n",
                         DEFAULT_ZONEINFO_FILE);

@@ -278,24 +280,30 @@
         }
         linkbuf[len] = '\0';
         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. Obtain new statbuf for this (using stat)
      */
+    if (stat(linkbuf, &statbuf) == -1) {
+        return NULL;
+    }
+
     size = (size_t) statbuf.st_size;
     buf = (char *) malloc(size);
     if (buf == NULL) {
         return NULL;
     }
-    if ((fd = open(DEFAULT_ZONEINFO_FILE, O_RDONLY)) == -1) {
+    if ((fd = open(linkbuf, O_RDONLY)) == -1) {
         free((void *) buf);
         return NULL;
     }
 
     if (read(fd, buf, size) != (ssize_t) size) {