timezone_md.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 570 行
C
570 行
/* * @(#)timezone_md.c 1.16 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */#include <stdlib.h>#include <stdio.h>#include <strings.h>#include <time.h>#include <limits.h>#include <errno.h>#ifdef __linux__#include <string.h>#include <dirent.h>#include <sys/stat.h>#include <sys/types.h>#include <unistd.h>#endif#include "jvm.h"#define SKIP_SPACE(p) while (*p == ' ' || *p == '\t') p++;#if !defined(__solaris__) || defined(__sparcv9)#define fileopen fopen#define filegets fgets#define fileclose fclose#endif#ifdef __linux__static const char *sysconfig_clock_file = "/etc/sysconfig/clock";static const char *zoneinfo_dir = "/usr/share/zoneinfo";static const char *defailt_zoneinfo_file = "/etc/localtime";/* * Returns a point to the zone ID portion of the given zoneinfo file * name. */static char *getZoneName(char *str){ static const char *zidir = "zoneinfo/"; char * pos = strstr((const char *)str, zidir); if (pos == NULL) { return NULL; } return pos + strlen(zidir);}/* * Returns a path name created from the given 'dir' and 'name' under * UNIX. This function allocates memory for the pathname calling * malloc(). */static char *getPathName(const char *dir, const char *name) { char *path; path = (char *) malloc(strlen(dir) + strlen(name) + 2); if (path == NULL) { return NULL; } return strcat(strcat(strcpy(path, dir), "/"), name);}/* * Scans the specified directory and its subdirectories to find a * zoneinfo file which has the same content as /etc/localtime given 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; struct stat statbuf; struct dirent *dp; char *pathname = NULL; int fd = -1; char *dbuf = NULL; char *tz = NULL; dirp = opendir(dir); if (dirp == NULL) { return NULL; } while ((dp = readdir(dirp)) != NULL) { /* * Skip '.' and '..' (and possibly other .* files) */ if (dp->d_name[0] == '.') { continue; } pathname = getPathName(dir, dp->d_name); if (pathname == NULL) { break; } if (stat(pathname, &statbuf) == -1) { break; } if (S_ISDIR(statbuf.st_mode)) { tz = findZoneinfoFile(buf, size, pathname); if (tz != NULL) { break; } } else if (S_ISREG(statbuf.st_mode) && (size_t)statbuf.st_size == size) { dbuf = (char *) malloc(size); if (dbuf == NULL) { break; } if ((fd = open(pathname, O_RDONLY)) == -1) { fd = 0; break; } if (read(fd, dbuf, size) != (ssize_t) size) { break; } if (memcmp(buf, dbuf, size) == 0) { tz = getZoneName(pathname); if (tz != NULL) { tz = strdup(tz); } break; } free((void *) dbuf); dbuf = NULL; (void) close(fd); fd = 0; } free((void *) pathname); pathname = NULL; } if (dirp != NULL) { (void) closedir(dirp); } if (pathname != NULL) { free((void *) pathname); } if (fd != 0) { (void) close(fd); } if (dbuf != NULL) { free((void *) dbuf); } return tz;}/* * Performs libc implementation specific mapping and returns a zone ID * if found. Otherwise, NULL is returned. */static char *getPlatformTimeZoneID(){ struct stat statbuf; char *tz = NULL; FILE *fp; int fd; char *buf; size_t size; /* * First, try the ZONE entry in /etc/sysconfig/clock. However, the * ZONE entry is not set up after initial Red Hat Linux * installation. In case that /etc/localtime is set up without * using timeconfig, there might be inconsistency between * /etc/localtime and the ZONE entry. The inconsistency between * timeconfig and linuxconf is reported as a bug in the Red Hat * web page as of May 1, 2000. */ if ((fp = fopen(sysconfig_clock_file, "r")) != NULL) { char line[256]; while (fgets(line, sizeof(line), fp) != NULL) { char *p = line; char *s; SKIP_SPACE(p); if (*p != 'Z') { continue; } if (strncmp(p, "ZONE=\"", 6) == 0) { p += 6; } else { /* * In case we need to parse it token by token. */ if (strncmp(p, "ZONE", 4) != 0) { continue; } p += 4; SKIP_SPACE(p); if (*p++ != '=') { break; } SKIP_SPACE(p); if (*p++ != '"') { break; } } for (s = p; *s && *s != '"'; s++) ; if (*s != '"') { /* this ZONE entry is broken. */ break; } *s = '\0'; tz = strdup(p); break; } (void) fclose(fp); if (tz != NULL) { return tz; } } /* * Next, try /etc/localtime to find the zone ID. */ if (lstat(defailt_zoneinfo_file, &statbuf) == -1) { return NULL; } /* * If it's a symlink, get the link name and its zone ID part. (The * 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.) */ if (S_ISLNK(statbuf.st_mode)) { char linkbuf[PATH_MAX+1]; int len; if ((len = readlink(defailt_zoneinfo_file, linkbuf, sizeof(linkbuf)-1)) == -1) { jio_fprintf(stderr, (const char *) "can't get a symlink of %s\n", defailt_zoneinfo_file); return NULL; } 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. */ size = (size_t) statbuf.st_size; buf = (char *) malloc(size); if (buf == NULL) { return NULL; } if ((fd = open(defailt_zoneinfo_file, O_RDONLY)) == -1) { free((void *) buf); return NULL; } if (read(fd, buf, size) != (ssize_t) size) { (void) close(fd); free((void *) buf); return NULL; } (void) close(fd); tz = findZoneinfoFile(buf, size, zoneinfo_dir); free((void *) buf); return tz;}#else#ifdef __solaris__#ifndef __sparcv9/* * Those file* functions mimic the UNIX stream io functions. This is * because of the limitation of the number of open files on Solaris * (32-bit mode only) due to the System V ABI. */#define BUFFER_SIZE 4096struct iobuffer { int magic; /* -1 to distinguish from the real FILE */ int fd; /* file discriptor */ char *buffer; /* pointer to buffer */ char *ptr; /* current read pointer */ char *endptr; /* end pointer */};static intfileclose(FILE *stream){ struct iobuffer *iop = (struct iobuffer *) stream; if (iop->magic != -1) { return fclose(stream); } if (iop == NULL) { return 0; } close(iop->fd); free((void *)iop->buffer); free((void *)iop); return 0;}static FILE *fileopen(const char *fname, const char *fmode){ FILE *fp; int fd; struct iobuffer *iop; if ((fp = fopen(fname, fmode)) != NULL) { return fp; } /* * It assumes read open. */ if ((fd = open(fname, O_RDONLY)) == -1) { return NULL; } /* * Allocate struct iobuffer and its buffer */ iop = malloc(sizeof(struct iobuffer)); if (iop == NULL) { (void) close(fd); errno = ENOMEM; return NULL; } iop->magic = -1; iop->fd = fd; iop->buffer = malloc(BUFFER_SIZE); if (iop->buffer == NULL) { (void) close(fd); free((void *) iop); errno = ENOMEM; return NULL; } iop->ptr = iop->buffer; iop->endptr = iop->buffer; return (FILE *)iop;}/* * This implementation assumes that n is large enough and the line * separator is '\n'. */static char *filegets(char *s, int n, FILE *stream){ struct iobuffer *iop = (struct iobuffer *) stream; char *p; if (iop->magic != -1) { return fgets(s, n, stream); } p = s; for (;;) { char c; if (iop->ptr == iop->endptr) { ssize_t len; if ((len = read(iop->fd, (void *)iop->buffer, BUFFER_SIZE)) == -1) { return NULL; } if (len == 0) { *p = 0; if (s == p) { return NULL; } return s; } iop->ptr = iop->buffer; iop->endptr = iop->buffer + len; } c = *iop->ptr++; *p++ = c; if ((p - s) == (n - 1)) { *p = 0; return s; } if (c == '\n') { *p = 0; return s; } } /*NOTREACHED*/}#endif /* not __sparcv9 */static const char *sys_init_file = "/etc/default/init";/* * Performs libc implementation dependent mapping. Returns a zone ID * if found. Otherwise, NULL is returned. Solaris libc looks up * "/etc/default/init" to get a default TZ value if TZ is not defined * as an environment variable. */static char *getPlatformTimeZoneID(){ char *tz = NULL; FILE *fp; /* * Try the TZ entry in /etc/default/init. */ if ((fp = fileopen(sys_init_file, "r")) != NULL) { char line[256]; char quote = '\0'; while (filegets(line, sizeof(line), fp) != NULL) { char *p = line; char *s; char c; /* quick check for comment lines */ if (*p == '#') { continue; } if (strncmp(p, "TZ=", 3) == 0) { p += 3; SKIP_SPACE(p); c = *p; if (c == '"' || c == '\'') { quote = c; p++; } /* * PSARC/2001/383: quoted string support */ for (s = p; (c = *s) != '\0' && c != '\n'; s++) { /* No '\\' is supported here. */ if (c == quote) { quote = '\0'; break; } if (c == ' ' && quote == '\0') { break; } } if (quote != '\0') { jio_fprintf(stderr, "ZoneInfo: unterminated time zone name in /etc/TIMEZONE\n"); } *s = '\0'; tz = strdup(p); break; } } (void) fileclose(fp); } return tz;}#endif#endif/* * findJavaTZ_md() maps platform time zone ID to Java time zone ID * using <java_home>/lib/tzmappings. If the TZ value is not found, it * trys some libc implementation dependent mappings. If it still * can't map to a Java time zone ID, it falls back to the GMT+/-hh:mm * form. `country', which can be null, is not used for UNIX platforms. *//*ARGSUSED1*/char *CVMtimezoneFindJavaTZ(const char *java_home_dir, const char *country){ char *tz; char *javatz = NULL; char *freetz = NULL; tz = getenv("TZ");#ifdef __linux__ if (tz == NULL) {#else#ifdef __solaris__ if (tz == NULL || *tz == '\0') {#endif#endif tz = getPlatformTimeZoneID(); freetz = tz; } if (tz != NULL) { if (*tz == ':') { tz++; }#ifdef __linix__ /* * Ignore "posix/" and "right/" prefix. */ if (strncmp(tz, "posix/", 6) == 0 || strncomp(tz, "right/", 6) == 0) { tz += 6; }#endif javatz = strdup(tz); if (freetz != NULL) { free((void *) freetz); } } return javatz;}/** * Returns a GMT-offset-based time zone ID. (e.g., "GMT-08:00") */char *CVMgetGMTOffsetID(){ time_t offset; char sign, buf[16]; if (timezone == 0) { return strdup("GMT"); } /* Note that the time offset direction is opposite. */ if (timezone > 0) { offset = timezone; sign = '-'; } else { offset = -timezone; sign = '+'; } sprintf(buf, (const char *)"GMT%c%02d:%02d", sign, (int)(offset/3600), (int)((offset%3600)/60)); return strdup(buf);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?