Example #1
0
/* Helper function for getSystemTimeZoneID() that compares the
   zoneinfo_file_path (regular) file with files in the zoneinfo_dir_path until
   it finds a match.  The matching file's name is used to determine the time
   zone ID. */
static QString findZoneinfoFile(QString zoneinfo_file_path,
                                QString zoneinfo_dir_path)
{
    QString zone_id("UNDEF");
    QDir zoneinfo_dir(zoneinfo_dir_path);
    QFileInfoList dirlist = zoneinfo_dir.entryInfoList();
    QFileInfo info;
    QString basename;
    QFileInfo zoneinfo_file_info(zoneinfo_file_path);

    for (QFileInfoList::const_iterator it = dirlist.begin();
         it != dirlist.end(); ++it)
    {
        info = *it;
         // Skip '.' and '..' and other files starting with "." and
         // skip localtime (which is often a link to zoneinfo_file_path)
        basename = info.baseName();
        if (basename.isEmpty() || (basename == "localtime")) {
            continue;
        }
        if (info.isDir())
        {
            zone_id = findZoneinfoFile(zoneinfo_file_path,
                                       info.absoluteFilePath());
            if (zone_id != "UNDEF")
                return zone_id;
        }
        else if (compare_zone_files(zoneinfo_file_info, info))
        {
            zone_id = info.absoluteFilePath();
            break;
        }
    }
    return zone_id;
}
Example #2
0
/*
 * Returns a zone ID of Solaris when the TZ value is "localtime".
 * First, it tries scf. If scf fails, it looks for the same file as
 * /usr/share/lib/zoneinfo/localtime under /usr/share/lib/zoneinfo/.
 */
static char *
getSolarisDefaultZoneID() {
    char *tz = NULL;
    struct stat statbuf;
    size_t size;
    char *buf;
    int fd;
    /* scf specific variables */
    scf_handle_t *h = NULL;
    scf_snapshot_t *snap = NULL;
    scf_instance_t *inst = NULL;
    scf_propertygroup_t *pg = NULL;
    scf_property_t *prop = NULL;
    scf_value_t *val = NULL;

    if ((h = scf_handle_create(SCF_VERSION)) != NULL
        && scf_handle_bind(h) == 0
        && (inst = scf_instance_create(h)) != NULL
        && (snap = scf_snapshot_create(h)) != NULL
        && (pg = scf_pg_create(h)) != NULL
        && (prop = scf_property_create(h)) != NULL
        && (val = scf_value_create(h)) != NULL
        && scf_handle_decode_fmri(h, TIMEZONE_FMRI, NULL, NULL, inst,
                                  NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) == 0
        && scf_instance_get_snapshot(inst, "running", snap) == 0
        && scf_instance_get_pg_composed(inst, snap, TIMEZONE_PG, pg) == 0
        && scf_pg_get_property(pg, LOCALTIME_PROP, prop) == 0
        && scf_property_get_value(prop, val) == 0) {
        ssize_t len;

        /* Gets the length of the zone ID string */
        len = scf_value_get_astring(val, NULL, 0);
        if (len != -1) {
            tz = malloc(++len); /* +1 for a null byte */
            if (tz != NULL && scf_value_get_astring(val, tz, len) != -1) {
                cleanupScf(h, snap, inst, pg, prop, val, NULL);
                return tz;
            }
        }
    }
    cleanupScf(h, snap, inst, pg, prop, val, tz);

    if (stat(DEFAULT_ZONEINFO_FILE, &statbuf) == -1) {
        return NULL;
    }
    size = (size_t) statbuf.st_size;
    buf = malloc(size);
    if (buf == NULL) {
        return NULL;
    }
    if ((fd = open(DEFAULT_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;
}
Example #3
0
/*
 * Performs Linux 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;

#if defined(__linux__)
    /*
     * Try reading the /etc/timezone file for Debian distros. There's
     * no spec of the file format available. This parsing assumes that
     * there's one line of an Olson tzid followed by a '\n', no
     * leading or trailing spaces, no comments.
     */
    if ((fp = fopen(ETC_TIMEZONE_FILE, "r")) != NULL) {
        char line[256];

        if (fgets(line, sizeof(line), fp) != NULL) {
            char *p = strchr(line, '\n');
            if (p != NULL) {
                *p = '\0';
            }
            if (strlen(line) > 0) {
                tz = strdup(line);
            }
        }
        (void) fclose(fp);
        if (tz != NULL) {
            return tz;
        }
    }
#endif /* defined(__linux__) */

    /*
     * Next, try /etc/localtime to find the zone ID.
     */
    if (lstat(DEFAULT_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(DEFAULT_ZONEINFO_FILE, linkbuf, sizeof(linkbuf)-1)) == -1) {
            jio_fprintf(stderr, (const char *) "can't get a symlink of %s\n",
                        DEFAULT_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.
     * If initial symbolic link resolution failed, we should treat target
     * file as a regular file.
     */
    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);
    free((void *) buf);
    return tz;
}
Example #4
0
/*
 * Scans the specified directory and its subdirectories to find a
 * zoneinfo file which has the same content as /etc/localtime on Linux
 * or /usr/share/lib/zoneinfo/localtime on Solaris given in 'buf'.
 * If file is symbolic link, then the contents it points to are 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 dirent64 *dp = NULL;
    struct dirent64 *entry = NULL;
    char *pathname = NULL;
    int fd = -1;
    char *dbuf = NULL;
    char *tz = NULL;

    dirp = opendir(dir);
    if (dirp == NULL) {
        return NULL;
    }

    entry = (struct dirent64 *) malloc((size_t) pathconf(dir, _PC_NAME_MAX));
    if (entry == NULL) {
        (void) closedir(dirp);
        return NULL;
    }

    while (readdir64_r(dirp, entry, &dp) == 0 && dp != NULL) {
        /*
         * 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)
#if defined(__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;
}
Example #5
0
/*
 * Scans the specified directory and its subdirectories to find a
 * zoneinfo file which has the same content as /etc/localtime on Linux
 * or /usr/share/lib/zoneinfo/localtime on Solaris given in 'buf'.
 * If file is symbolic link, then the contents it points to are 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 = 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) {
                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 (entry != NULL) {
        free((void *) entry);
    }
    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;
}

#if defined(__linux__) || defined(MACOSX)

/*
 * Performs Linux 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;

#ifdef __linux__
    /*
     * Try reading the /etc/timezone file for Debian distros. There's
     * no spec of the file format available. This parsing assumes that
     * there's one line of an Olson tzid followed by a '\n', no
     * leading or trailing spaces, no comments.
     */
    if ((fp = fopen(ETC_TIMEZONE_FILE, "r")) != NULL) {
        char line[256];

        if (fgets(line, sizeof(line), fp) != NULL) {
            char *p = strchr(line, '\n');
            if (p != NULL) {
                *p = '\0';
            }
            if (strlen(line) > 0) {
                tz = strdup(line);
            }
        }
        (void) fclose(fp);
        if (tz != NULL) {
            return tz;
        }
    }
#endif /* __linux__ */

    /*
     * Next, try /etc/localtime to find the zone ID.
     */
    if (lstat(DEFAULT_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(DEFAULT_ZONEINFO_FILE, linkbuf, sizeof(linkbuf)-1)) == -1) {
            jio_fprintf(stderr, (const char *) "can't get a symlink of %s\n",
                        DEFAULT_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.
     * If initial symbolic link resolution failed, we should treat target
     * file as a regular file.
     */
    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);
    free((void *) buf);
    return tz;
}
#else
#ifdef __solaris__
#if !defined(__sparcv9) && !defined(amd64)

/*
 * 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     4096

static struct iobuffer {
    int     magic;      /* -1 to distinguish from the real FILE */
    int     fd;         /* file descriptor */
    char    *buffer;    /* pointer to buffer */
    char    *ptr;       /* current read pointer */
    char    *endptr;    /* end pointer */
};

static int
fileclose(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;
}
/*
 * 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;
}
Example #8
0
/* Helper function for getTimeZoneID() that provides an unprocessed time zone
   id obtained using system-dependent means of identifying the system's time
   zone. */
static QString getSystemTimeZoneID(void)
{
    QString zone_id("UNDEF");
#ifdef _WIN32
    // typedef struct _TIME_ZONE_INFORMATION { ...
    // GetTimeZoneInformation();
    // ...
    // Sadly, Windows zone names are different to the (probably Unix)
    // backend's names - "AUS Eastern Standard Time" vs "Australia/Sydney".
    // Translation is not worthwhile. Leave it as UNDEF to check the offset.
#else
    // Try to determine the time zone information by inspecting the system
    // configuration
    QString time_zone_file_path("/etc/timezone");
    QString clock_file_path("/etc/sysconfig/clock");
    QString zoneinfo_file_path("/etc/localtime");
    QString zoneinfo_dir_path("/usr/share/zoneinfo");

    // First, check time_zone_file_path (used by Debian-based systems)
    if (read_time_zone_id(time_zone_file_path, zone_id))
        return zone_id;

    // Next, look for the ZONE entry in clock_file_path (used by Red Hat-based
    // systems)
    if (read_time_zone_id(clock_file_path, zone_id))
        return zone_id;

    // Next check zoneinfo_file_path
    QFile zoneinfo_file(zoneinfo_file_path);
    QFileInfo info(zoneinfo_file);

    if (info.exists() && info.isFile())
    {
        QString tz;
        if (info.isSymLink())
        {
            // The symlink refers to a file whose name contains the zone ID
            tz = info.symLinkTarget();
        }
        else
        {
            // The zoneinfo_file is a copy of the file in the
            // zoneinfo_dir_path, so search for the same file in
            // zoneinfo_dir_path
            tz = findZoneinfoFile(zoneinfo_file_path, zoneinfo_dir_path);
        }
        if (tz != "UNDEF")
        {
            int pos = 0;
            // Get the zone ID from the filename
            // Look for the basename of zoneinfo_dir_path in case it's a
            // relative link
            QString zoneinfo_dirname = zoneinfo_dir_path.section('/', -1);
            if ((pos = tz.indexOf(zoneinfo_dirname)) != -1)
            {
                zone_id = tz.right(tz.size() - (pos + 1) -
                                   zoneinfo_dirname.size());
            }
        }
        else
        {
            // If we still haven't found a time zone, try localtime_r() to at
            // least get the zone name/abbreviation (as opposed to the
            // identifier for the set of rules governing the zone)
            char name[64];
            time_t t;
            struct tm *result = (struct tm *)malloc(sizeof(*result));

            if (result != NULL)
            {
                t = time(NULL);
                localtime_r(&t, result);
                if (result != NULL)
                {
                    if (strftime(name, sizeof(name), "%Z", result) > 0)
                        zone_id = name;
                    free(result);
                }
            }
        }
    }

#endif
    return zone_id;
}