1 /*
2 * Copyright (c) 1999, 2011, 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
79
80 /*
81 * Returns a path name created from the given 'dir' and 'name' under
82 * UNIX. This function allocates memory for the pathname calling
83 * malloc(). NULL is returned if malloc() fails.
84 */
85 static char *
86 getPathName(const char *dir, const char *name) {
87 char *path;
88
89 path = (char *) malloc(strlen(dir) + strlen(name) + 2);
90 if (path == NULL) {
91 return NULL;
92 }
93 return strcat(strcat(strcpy(path, dir), "/"), name);
94 }
95
96 /*
97 * Scans the specified directory and its subdirectories to find a
98 * zoneinfo file which has the same content as /etc/localtime on Linux
99 * or /usr/share/lib/zoneinfo/localtime (most likely a symbolic link)
100 * on Solaris given in 'buf'. Returns a zone ID if found, otherwise,
101 * NULL is returned.
102 */
103 static char *
104 findZoneinfoFile(char *buf, size_t size, const char *dir)
105 {
106 DIR *dirp = NULL;
107 struct stat statbuf;
108 struct dirent *dp = NULL;
109 struct dirent *entry = NULL;
110 char *pathname = NULL;
111 int fd = -1;
112 char *dbuf = NULL;
113 char *tz = NULL;
114
115 dirp = opendir(dir);
116 if (dirp == NULL) {
117 return NULL;
118 }
119
120 entry = (struct dirent *) malloc((size_t) pathconf(dir, _PC_NAME_MAX));
121 if (entry == NULL) {
209 free((void *) dbuf);
210 }
211 return tz;
212 }
213
214 #if defined(__linux__) || defined(MACOSX)
215
216 /*
217 * Performs Linux specific mapping and returns a zone ID
218 * if found. Otherwise, NULL is returned.
219 */
220 static char *
221 getPlatformTimeZoneID()
222 {
223 struct stat statbuf;
224 char *tz = NULL;
225 FILE *fp;
226 int fd;
227 char *buf;
228 size_t size;
229
230 #ifdef __linux__
231 /*
232 * Try reading the /etc/timezone file for Debian distros. There's
233 * no spec of the file format available. This parsing assumes that
234 * there's one line of an Olson tzid followed by a '\n', no
235 * leading or trailing spaces, no comments.
236 */
237 if ((fp = fopen(ETC_TIMEZONE_FILE, "r")) != NULL) {
238 char line[256];
239
240 if (fgets(line, sizeof(line), fp) != NULL) {
241 char *p = strchr(line, '\n');
242 if (p != NULL) {
243 *p = '\0';
244 }
245 if (strlen(line) > 0) {
246 tz = strdup(line);
247 }
248 }
250 if (tz != NULL) {
251 return tz;
252 }
253 }
254 #endif /* __linux__ */
255
256 /*
257 * Next, try /etc/localtime to find the zone ID.
258 */
259 if (lstat(DEFAULT_ZONEINFO_FILE, &statbuf) == -1) {
260 return NULL;
261 }
262
263 /*
264 * If it's a symlink, get the link name and its zone ID part. (The
265 * older versions of timeconfig created a symlink as described in
266 * the Red Hat man page. It was changed in 1999 to create a copy
267 * of a zoneinfo file. It's no longer possible to get the zone ID
268 * from /etc/localtime.)
269 */
270 if (S_ISLNK(statbuf.st_mode)) {
271 char linkbuf[PATH_MAX+1];
272 int len;
273
274 if ((len = readlink(DEFAULT_ZONEINFO_FILE, linkbuf, sizeof(linkbuf)-1)) == -1) {
275 jio_fprintf(stderr, (const char *) "can't get a symlink of %s\n",
276 DEFAULT_ZONEINFO_FILE);
277 return NULL;
278 }
279 linkbuf[len] = '\0';
280 tz = getZoneName(linkbuf);
281 if (tz != NULL) {
282 tz = strdup(tz);
283 }
284 return tz;
285 }
286
287 /*
288 * If it's a regular file, we need to find out the same zoneinfo file
289 * that has been copied as /etc/localtime.
290 */
291 size = (size_t) statbuf.st_size;
292 buf = (char *) malloc(size);
293 if (buf == NULL) {
294 return NULL;
295 }
296 if ((fd = open(DEFAULT_ZONEINFO_FILE, O_RDONLY)) == -1) {
297 free((void *) buf);
298 return NULL;
299 }
300
301 if (read(fd, buf, size) != (ssize_t) size) {
302 (void) close(fd);
303 free((void *) buf);
304 return NULL;
305 }
306 (void) close(fd);
307
308 tz = findZoneinfoFile(buf, size, ZONEINFO_DIR);
309 free((void *) buf);
310 return tz;
311 }
312 #else
313 #ifdef __solaris__
314 #if !defined(__sparcv9) && !defined(amd64)
315
316 /*
317 * Those file* functions mimic the UNIX stream io functions. This is
318 * because of the limitation of the number of open files on Solaris
319 * (32-bit mode only) due to the System V ABI.
|
1 /*
2 * Copyright (c) 1999, 2012, 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
79
80 /*
81 * Returns a path name created from the given 'dir' and 'name' under
82 * UNIX. This function allocates memory for the pathname calling
83 * malloc(). NULL is returned if malloc() fails.
84 */
85 static char *
86 getPathName(const char *dir, const char *name) {
87 char *path;
88
89 path = (char *) malloc(strlen(dir) + strlen(name) + 2);
90 if (path == NULL) {
91 return NULL;
92 }
93 return strcat(strcat(strcpy(path, dir), "/"), name);
94 }
95
96 /*
97 * Scans the specified directory and its subdirectories to find a
98 * zoneinfo file which has the same content as /etc/localtime on Linux
99 * or /usr/share/lib/zoneinfo/localtime on Solaris given in 'buf'.
100 * If file is symbolic link, then the contents it points to are in buf.
101 * Returns a zone ID if found, otherwise, NULL is returned.
102 */
103 static char *
104 findZoneinfoFile(char *buf, size_t size, const char *dir)
105 {
106 DIR *dirp = NULL;
107 struct stat statbuf;
108 struct dirent *dp = NULL;
109 struct dirent *entry = NULL;
110 char *pathname = NULL;
111 int fd = -1;
112 char *dbuf = NULL;
113 char *tz = NULL;
114
115 dirp = opendir(dir);
116 if (dirp == NULL) {
117 return NULL;
118 }
119
120 entry = (struct dirent *) malloc((size_t) pathconf(dir, _PC_NAME_MAX));
121 if (entry == NULL) {
209 free((void *) dbuf);
210 }
211 return tz;
212 }
213
214 #if defined(__linux__) || defined(MACOSX)
215
216 /*
217 * Performs Linux specific mapping and returns a zone ID
218 * if found. Otherwise, NULL is returned.
219 */
220 static char *
221 getPlatformTimeZoneID()
222 {
223 struct stat statbuf;
224 char *tz = NULL;
225 FILE *fp;
226 int fd;
227 char *buf;
228 size_t size;
229 char linkbuf[PATH_MAX+1];
230
231 #ifdef __linux__
232 /*
233 * Try reading the /etc/timezone file for Debian distros. There's
234 * no spec of the file format available. This parsing assumes that
235 * there's one line of an Olson tzid followed by a '\n', no
236 * leading or trailing spaces, no comments.
237 */
238 if ((fp = fopen(ETC_TIMEZONE_FILE, "r")) != NULL) {
239 char line[256];
240
241 if (fgets(line, sizeof(line), fp) != NULL) {
242 char *p = strchr(line, '\n');
243 if (p != NULL) {
244 *p = '\0';
245 }
246 if (strlen(line) > 0) {
247 tz = strdup(line);
248 }
249 }
251 if (tz != NULL) {
252 return tz;
253 }
254 }
255 #endif /* __linux__ */
256
257 /*
258 * Next, try /etc/localtime to find the zone ID.
259 */
260 if (lstat(DEFAULT_ZONEINFO_FILE, &statbuf) == -1) {
261 return NULL;
262 }
263
264 /*
265 * If it's a symlink, get the link name and its zone ID part. (The
266 * older versions of timeconfig created a symlink as described in
267 * the Red Hat man page. It was changed in 1999 to create a copy
268 * of a zoneinfo file. It's no longer possible to get the zone ID
269 * from /etc/localtime.)
270 */
271 strcpy(linkbuf, DEFAULT_ZONEINFO_FILE);
272 linkbuf[strlen(DEFAULT_ZONEINFO_FILE)] = '\0';
273 if (S_ISLNK(statbuf.st_mode)) {
274 int len;
275
276 if ((len = readlink(DEFAULT_ZONEINFO_FILE, linkbuf, sizeof(linkbuf)-1)) == -1) {
277 jio_fprintf(stderr, (const char *) "can't get a symlink of %s\n",
278 DEFAULT_ZONEINFO_FILE);
279 return NULL;
280 }
281 linkbuf[len] = '\0';
282 tz = getZoneName(linkbuf);
283 if (tz != NULL) {
284 tz = strdup(tz);
285 return tz;
286 }
287 }
288
289 /*
290 * If it's a regular file, we need to find out the same zoneinfo file
291 * that has been copied as /etc/localtime.
292 * If initial symbolic link resolution failed, we should treat target
293 * file as a regular file.
294 */
295 if ((fd = open(linkbuf, O_RDONLY)) == -1) {
296 return NULL;
297 }
298 if (fstat(fd, &statbuf) == -1) {
299 return NULL;
300 }
301 size = (size_t) statbuf.st_size;
302 buf = (char *) malloc(size);
303 if (buf == NULL) {
304 return NULL;
305 }
306
307 if (read(fd, buf, size) != (ssize_t) size) {
308 (void) close(fd);
309 free((void *) buf);
310 return NULL;
311 }
312 (void) close(fd);
313
314 tz = findZoneinfoFile(buf, size, ZONEINFO_DIR);
315 free((void *) buf);
316 return tz;
317 }
318 #else
319 #ifdef __solaris__
320 #if !defined(__sparcv9) && !defined(amd64)
321
322 /*
323 * Those file* functions mimic the UNIX stream io functions. This is
324 * because of the limitation of the number of open files on Solaris
325 * (32-bit mode only) due to the System V ABI.
|