#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <time.h>
#include <limits.h>
#include <errno.h>
#include <stddef.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <fcntl.h>
static const char *ETC_TIMEZONE_FILE = "/etc/timezone";
static const char *ZONEINFO_DIR = "/usr/share/zoneinfo";
static const char *DEFAULT_ZONEINFO_FILE = "/etc/localtime";
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(). NULL is returned if malloc() fails.
*/
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);
}
static char *
findZoneinfoFile(char *buf, size_t size, const char *dir)
{
DIR *dirp = NULL;
struct stat statbuf;
struct dirent *dp = NULL;
struct dirent *entry = NULL;
char *pathname = NULL;
int fd = -1;
char *dbuf = NULL;
char *tz = NULL;
dirp = opendir(dir);
if (dirp == NULL) {
return NULL;
}
entry = (struct dirent *) malloc((size_t) pathconf(dir, _PC_NAME_MAX));
if (entry == NULL) {
(void) closedir(dirp);
return NULL;
}
#if defined(__linux__) || defined(MACOSX) || (defined(__solaris__) \
&& (defined(_POSIX_PTHREAD_SEMANTICS) || defined(_LP64)))
while (readdir_r(dirp, entry, &dp) == 0 && dp != NULL) {
#else
while ((dp = readdir_r(dirp, entry)) != NULL) {
#endif
* Skip '.' and '..' (and possibly other .* files)
*/
if (dp->d_name[0] == '.') {
continue;
}
* Skip "ROC", "posixrules", and "localtime".
*/
if ((strcmp(dp->d_name, "ROC") == 0)
|| (strcmp(dp->d_name, "posixrules") == 0)
#ifdef __solaris__
* Skip the "src" and "tab" directories on Solaris.
*/
|| (strcmp(dp->d_name, "src") == 0)
|| (strcmp(dp->d_name, "tab") == 0)
#endif
|| (strcmp(dp->d_name, "localtime") == 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) {
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 = -1;
}
free((void *) pathname);
pathname = NULL;
}
if (entry != NULL) {
free((void *) entry);
}
if (dirp != NULL) {
(void) closedir(dirp);
}
if (pathname != NULL) {
free((void *) pathname);
}
if (fd != -1) {
(void) close(fd);
}
if (dbuf != NULL) {
free((void *) dbuf);
}
return tz;
}
int main() {
struct stat statbuf;
char *tz = NULL;
FILE *fp;
int fd;
char *buf;
size_t size;
if ((fd = open(DEFAULT_ZONEINFO_FILE, O_RDONLY)) == -1) {
return NULL;
}
if (fstat(fd, &statbuf) == -1) {
(void) close(fd);
return NULL;
}
size = (size_t) statbuf.st_size;
buf = (char *) malloc(size);
if (buf == NULL) {
(void) close(fd);
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);
printf("%s", tz);
free((void *) buf);
return 0;
}