1 /*
2 * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
35 #include <string.h>
36 #include <dirent.h>
37 #include <unistd.h>
38 #if defined(__solaris__)
39 #include <libscf.h>
40 #endif
41
42 #include "jvm.h"
43 #include "TimeZone_md.h"
44
45 #define SKIP_SPACE(p) while (*p == ' ' || *p == '\t') p++;
46
47 #define RESTARTABLE(_cmd, _result) do { \
48 do { \
49 _result = _cmd; \
50 } while((_result == -1) && (errno == EINTR)); \
51 } while(0)
52
53 #if defined(_ALLBSD_SOURCE)
54 #define dirent64 dirent
55 #define readdir64_r readdir_r
56 #endif
57
58 #if !defined(__solaris__) || defined(__sparcv9) || defined(amd64)
59 #define fileopen fopen
60 #define filegets fgets
61 #define fileclose fclose
62 #endif
63
64 #if defined(__linux__) || defined(_ALLBSD_SOURCE)
65 static const char *ETC_TIMEZONE_FILE = "/etc/timezone";
66 static const char *ZONEINFO_DIR = "/usr/share/zoneinfo";
67 static const char *DEFAULT_ZONEINFO_FILE = "/etc/localtime";
68 #else
69 static const char *SYS_INIT_FILE = "/etc/default/init";
70 static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo";
71 static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime";
72 #endif /* defined(__linux__) || defined(_ALLBSD_SOURCE) */
73
74 #if defined(_AIX)
75 static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
105 path = (char *) malloc(strlen(dir) + strlen(name) + 2);
106 if (path == NULL) {
107 return NULL;
108 }
109 return strcat(strcat(strcpy(path, dir), "/"), name);
110 }
111
112 /*
113 * Scans the specified directory and its subdirectories to find a
114 * zoneinfo file which has the same content as /etc/localtime on Linux
115 * or /usr/share/lib/zoneinfo/localtime on Solaris given in 'buf'.
116 * If file is symbolic link, then the contents it points to are in buf.
117 * Returns a zone ID if found, otherwise, NULL is returned.
118 */
119 static char *
120 findZoneinfoFile(char *buf, size_t size, const char *dir)
121 {
122 DIR *dirp = NULL;
123 struct stat statbuf;
124 struct dirent64 *dp = NULL;
125 struct dirent64 *entry = NULL;
126 char *pathname = NULL;
127 int fd = -1;
128 char *dbuf = NULL;
129 char *tz = NULL;
130 int res;
131 long name_max = 0;
132
133 dirp = opendir(dir);
134 if (dirp == NULL) {
135 return NULL;
136 }
137
138 name_max = pathconf(dir, _PC_NAME_MAX);
139 // If pathconf did not work, fall back to a mimimum buffer size.
140 if (name_max < 1024) {
141 name_max = 1024;
142 }
143
144 entry = (struct dirent64 *)malloc(offsetof(struct dirent64, d_name) + name_max + 1);
145 if (entry == NULL) {
146 (void) closedir(dirp);
147 return NULL;
148 }
149
150 while (readdir64_r(dirp, entry, &dp) == 0 && dp != NULL) {
151 /*
152 * Skip '.' and '..' (and possibly other .* files)
153 */
154 if (dp->d_name[0] == '.') {
155 continue;
156 }
157
158 /*
159 * Skip "ROC", "posixrules", and "localtime".
160 */
161 if ((strcmp(dp->d_name, "ROC") == 0)
162 || (strcmp(dp->d_name, "posixrules") == 0)
163 #if defined(__solaris__)
164 /*
165 * Skip the "src" and "tab" directories on Solaris.
166 */
167 || (strcmp(dp->d_name, "src") == 0)
168 || (strcmp(dp->d_name, "tab") == 0)
169 #endif
170 || (strcmp(dp->d_name, "localtime") == 0)) {
197 RESTARTABLE(read(fd, dbuf, size), res);
198 if (res != (ssize_t) size) {
199 break;
200 }
201 if (memcmp(buf, dbuf, size) == 0) {
202 tz = getZoneName(pathname);
203 if (tz != NULL) {
204 tz = strdup(tz);
205 }
206 break;
207 }
208 free((void *) dbuf);
209 dbuf = NULL;
210 (void) close(fd);
211 fd = -1;
212 }
213 free((void *) pathname);
214 pathname = NULL;
215 }
216
217 if (entry != NULL) {
218 free((void *) entry);
219 }
220 if (dirp != NULL) {
221 (void) closedir(dirp);
222 }
223 if (pathname != NULL) {
224 free((void *) pathname);
225 }
226 if (fd != -1) {
227 (void) close(fd);
228 }
229 if (dbuf != NULL) {
230 free((void *) dbuf);
231 }
232 return tz;
233 }
234
235 #if defined(__linux__) || defined(MACOSX)
236
237 /*
238 * Performs Linux specific mapping and returns a zone ID
239 * if found. Otherwise, NULL is returned.
|
1 /*
2 * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
35 #include <string.h>
36 #include <dirent.h>
37 #include <unistd.h>
38 #if defined(__solaris__)
39 #include <libscf.h>
40 #endif
41
42 #include "jvm.h"
43 #include "TimeZone_md.h"
44
45 #define SKIP_SPACE(p) while (*p == ' ' || *p == '\t') p++;
46
47 #define RESTARTABLE(_cmd, _result) do { \
48 do { \
49 _result = _cmd; \
50 } while((_result == -1) && (errno == EINTR)); \
51 } while(0)
52
53 #if defined(_ALLBSD_SOURCE)
54 #define dirent64 dirent
55 #define readdir64 readdir
56 #endif
57
58 #if !defined(__solaris__) || defined(__sparcv9) || defined(amd64)
59 #define fileopen fopen
60 #define filegets fgets
61 #define fileclose fclose
62 #endif
63
64 #if defined(__linux__) || defined(_ALLBSD_SOURCE)
65 static const char *ETC_TIMEZONE_FILE = "/etc/timezone";
66 static const char *ZONEINFO_DIR = "/usr/share/zoneinfo";
67 static const char *DEFAULT_ZONEINFO_FILE = "/etc/localtime";
68 #else
69 static const char *SYS_INIT_FILE = "/etc/default/init";
70 static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo";
71 static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime";
72 #endif /* defined(__linux__) || defined(_ALLBSD_SOURCE) */
73
74 #if defined(_AIX)
75 static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
105 path = (char *) malloc(strlen(dir) + strlen(name) + 2);
106 if (path == NULL) {
107 return NULL;
108 }
109 return strcat(strcat(strcpy(path, dir), "/"), name);
110 }
111
112 /*
113 * Scans the specified directory and its subdirectories to find a
114 * zoneinfo file which has the same content as /etc/localtime on Linux
115 * or /usr/share/lib/zoneinfo/localtime on Solaris given in 'buf'.
116 * If file is symbolic link, then the contents it points to are in buf.
117 * Returns a zone ID if found, otherwise, NULL is returned.
118 */
119 static char *
120 findZoneinfoFile(char *buf, size_t size, const char *dir)
121 {
122 DIR *dirp = NULL;
123 struct stat statbuf;
124 struct dirent64 *dp = NULL;
125 char *pathname = NULL;
126 int fd = -1;
127 char *dbuf = NULL;
128 char *tz = NULL;
129 int res;
130
131 dirp = opendir(dir);
132 if (dirp == NULL) {
133 return NULL;
134 }
135
136 while ((dp = readdir64(dirp)) != NULL) {
137 /*
138 * Skip '.' and '..' (and possibly other .* files)
139 */
140 if (dp->d_name[0] == '.') {
141 continue;
142 }
143
144 /*
145 * Skip "ROC", "posixrules", and "localtime".
146 */
147 if ((strcmp(dp->d_name, "ROC") == 0)
148 || (strcmp(dp->d_name, "posixrules") == 0)
149 #if defined(__solaris__)
150 /*
151 * Skip the "src" and "tab" directories on Solaris.
152 */
153 || (strcmp(dp->d_name, "src") == 0)
154 || (strcmp(dp->d_name, "tab") == 0)
155 #endif
156 || (strcmp(dp->d_name, "localtime") == 0)) {
183 RESTARTABLE(read(fd, dbuf, size), res);
184 if (res != (ssize_t) size) {
185 break;
186 }
187 if (memcmp(buf, dbuf, size) == 0) {
188 tz = getZoneName(pathname);
189 if (tz != NULL) {
190 tz = strdup(tz);
191 }
192 break;
193 }
194 free((void *) dbuf);
195 dbuf = NULL;
196 (void) close(fd);
197 fd = -1;
198 }
199 free((void *) pathname);
200 pathname = NULL;
201 }
202
203 if (dirp != NULL) {
204 (void) closedir(dirp);
205 }
206 if (pathname != NULL) {
207 free((void *) pathname);
208 }
209 if (fd != -1) {
210 (void) close(fd);
211 }
212 if (dbuf != NULL) {
213 free((void *) dbuf);
214 }
215 return tz;
216 }
217
218 #if defined(__linux__) || defined(MACOSX)
219
220 /*
221 * Performs Linux specific mapping and returns a zone ID
222 * if found. Otherwise, NULL is returned.
|