src/java.base/unix/native/libjava/TimeZone_md.c
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 53029 8180809085a4
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
     1 /*
     1 /*
     2  * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    40 #endif
    40 #endif
    41 
    41 
    42 #include "jvm.h"
    42 #include "jvm.h"
    43 #include "TimeZone_md.h"
    43 #include "TimeZone_md.h"
    44 
    44 
       
    45 static char *isFileIdentical(char* buf, size_t size, char *pathname);
       
    46 
    45 #define SKIP_SPACE(p)   while (*p == ' ' || *p == '\t') p++;
    47 #define SKIP_SPACE(p)   while (*p == ' ' || *p == '\t') p++;
    46 
    48 
    47 #define RESTARTABLE(_cmd, _result) do { \
    49 #define RESTARTABLE(_cmd, _result) do { \
    48   do { \
    50   do { \
    49     _result = _cmd; \
    51     _result = _cmd; \
    70 static const char *SYS_INIT_FILE = "/etc/default/init";
    72 static const char *SYS_INIT_FILE = "/etc/default/init";
    71 static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo";
    73 static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo";
    72 static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime";
    74 static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime";
    73 #endif /* defined(__linux__) || defined(_ALLBSD_SOURCE) */
    75 #endif /* defined(__linux__) || defined(_ALLBSD_SOURCE) */
    74 
    76 
       
    77 static const char popularZones[][4] = {"UTC", "GMT"};
       
    78 
    75 #if defined(_AIX)
    79 #if defined(_AIX)
    76 static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
    80 static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
    77 #endif
    81 #endif
    78 
    82 
    79 #if defined(__linux__) || defined(MACOSX) || defined(__solaris__)
    83 #if defined(__linux__) || defined(MACOSX) || defined(__solaris__)
   119  */
   123  */
   120 static char *
   124 static char *
   121 findZoneinfoFile(char *buf, size_t size, const char *dir)
   125 findZoneinfoFile(char *buf, size_t size, const char *dir)
   122 {
   126 {
   123     DIR *dirp = NULL;
   127     DIR *dirp = NULL;
   124     struct stat64 statbuf;
       
   125     struct dirent *dp = NULL;
   128     struct dirent *dp = NULL;
   126     char *pathname = NULL;
   129     char *pathname = NULL;
   127     int fd = -1;
       
   128     char *dbuf = NULL;
       
   129     char *tz = NULL;
   130     char *tz = NULL;
   130     int res;
   131     int res;
       
   132 
       
   133     if (strcmp(dir, ZONEINFO_DIR) == 0) {
       
   134         /* fast path for 1st iteration */
       
   135         for (unsigned int i = 0; i < sizeof (popularZones) / sizeof (popularZones[0]); i++) {
       
   136             pathname = getPathName(dir, popularZones[i]);
       
   137             if (pathname == NULL) {
       
   138                 continue;
       
   139             }
       
   140             tz = isFileIdentical(buf, size, pathname);
       
   141             free((void *) pathname);
       
   142             pathname = NULL;
       
   143             if (tz != NULL) {
       
   144                 return tz;
       
   145             }
       
   146         }
       
   147     }
   131 
   148 
   132     dirp = opendir(dir);
   149     dirp = opendir(dir);
   133     if (dirp == NULL) {
   150     if (dirp == NULL) {
   134         return NULL;
   151         return NULL;
   135     }
   152     }
   160 
   177 
   161         pathname = getPathName(dir, dp->d_name);
   178         pathname = getPathName(dir, dp->d_name);
   162         if (pathname == NULL) {
   179         if (pathname == NULL) {
   163             break;
   180             break;
   164         }
   181         }
   165         RESTARTABLE(stat64(pathname, &statbuf), res);
   182 
   166         if (res == -1) {
   183         tz = isFileIdentical(buf, size, pathname);
   167             break;
       
   168         }
       
   169 
       
   170         if (S_ISDIR(statbuf.st_mode)) {
       
   171             tz = findZoneinfoFile(buf, size, pathname);
       
   172             if (tz != NULL) {
       
   173                 break;
       
   174             }
       
   175         } else if (S_ISREG(statbuf.st_mode) && (size_t)statbuf.st_size == size) {
       
   176             dbuf = (char *) malloc(size);
       
   177             if (dbuf == NULL) {
       
   178                 break;
       
   179             }
       
   180             RESTARTABLE(open(pathname, O_RDONLY), fd);
       
   181             if (fd == -1) {
       
   182                 break;
       
   183             }
       
   184             RESTARTABLE(read(fd, dbuf, size), res);
       
   185             if (res != (ssize_t) size) {
       
   186                 break;
       
   187             }
       
   188             if (memcmp(buf, dbuf, size) == 0) {
       
   189                 tz = getZoneName(pathname);
       
   190                 if (tz != NULL) {
       
   191                     tz = strdup(tz);
       
   192                 }
       
   193                 break;
       
   194             }
       
   195             free((void *) dbuf);
       
   196             dbuf = NULL;
       
   197             (void) close(fd);
       
   198             fd = -1;
       
   199         }
       
   200         free((void *) pathname);
   184         free((void *) pathname);
   201         pathname = NULL;
   185         pathname = NULL;
       
   186         if (tz != NULL) {
       
   187            break;
       
   188         }
   202     }
   189     }
   203 
   190 
   204     if (dirp != NULL) {
   191     if (dirp != NULL) {
   205         (void) closedir(dirp);
   192         (void) closedir(dirp);
   206     }
   193     }
   207     if (pathname != NULL) {
   194     return tz;
   208         free((void *) pathname);
   195 }
   209     }
   196 
   210     if (fd != -1) {
   197 /*
       
   198  * Checks if the file pointed to by pathname matches
       
   199  * the data contents in buf.
       
   200  * Returns a representation of the timezone file name
       
   201  * if file match is found, otherwise NULL.
       
   202  */
       
   203 static char *
       
   204 isFileIdentical(char *buf, size_t size, char *pathname)
       
   205 {
       
   206     char *possibleMatch = NULL;
       
   207     struct stat64 statbuf;
       
   208     char *dbuf = NULL;
       
   209     int fd = -1;
       
   210     int res;
       
   211 
       
   212     RESTARTABLE(stat64(pathname, &statbuf), res);
       
   213     if (res == -1) {
       
   214         return NULL;
       
   215     }
       
   216 
       
   217     if (S_ISDIR(statbuf.st_mode)) {
       
   218         possibleMatch  = findZoneinfoFile(buf, size, pathname);
       
   219     } else if (S_ISREG(statbuf.st_mode) && (size_t)statbuf.st_size == size) {
       
   220         dbuf = (char *) malloc(size);
       
   221         if (dbuf == NULL) {
       
   222             return NULL;
       
   223         }
       
   224         RESTARTABLE(open(pathname, O_RDONLY), fd);
       
   225         if (fd == -1) {
       
   226             goto freedata;
       
   227         }
       
   228         RESTARTABLE(read(fd, dbuf, size), res);
       
   229         if (res != (ssize_t) size) {
       
   230             goto freedata;
       
   231         }
       
   232         if (memcmp(buf, dbuf, size) == 0) {
       
   233             possibleMatch = getZoneName(pathname);
       
   234             if (possibleMatch != NULL) {
       
   235                 possibleMatch = strdup(possibleMatch);
       
   236             }
       
   237         }
       
   238         freedata:
       
   239         free((void *) dbuf);
   211         (void) close(fd);
   240         (void) close(fd);
   212     }
   241     }
   213     if (dbuf != NULL) {
   242     return possibleMatch;
   214         free((void *) dbuf);
       
   215     }
       
   216     return tz;
       
   217 }
   243 }
   218 
   244 
   219 #if defined(__linux__) || defined(MACOSX)
   245 #if defined(__linux__) || defined(MACOSX)
   220 
   246 
   221 /*
   247 /*