QTimeZonePrivate: prefer /etc/localtime over /etc/timezone

On modern distros (e.g. those using systemd), /etc/localtime is always a
symlink. As that file is actually used by libraries (see tzset(3)),
prefer it over /etc/timezone (which is no longer needed since
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=803144).

This fixes a wrongly reported local timezone when a stale /etc/timezone
file exists. While at it, improve sanity check for localtime symlink.

Change-Id: I8557a58acf21afaeca0d585066304c79a92b5ddb
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Peter Wu 2017-10-28 23:01:58 -07:00
parent bdf1045b71
commit 110e49c9ce

View File

@ -1050,7 +1050,18 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
if (ianaId == "/etc/localtime")
ianaId.clear();
// On Debian Etch and later /etc/localtime is real file with name held in /etc/timezone
// On most distros /etc/localtime is a symlink to a real file so extract name from the path
if (ianaId.isEmpty()) {
const QString path = QFile::symLinkTarget(QStringLiteral("/etc/localtime"));
if (!path.isEmpty()) {
// /etc/localtime is a symlink to the current TZ file, so extract from path
int index = path.indexOf(QLatin1String("/zoneinfo/"));
if (index != -1)
ianaId = path.mid(index + 10).toUtf8();
}
}
// On Debian Etch up to Jessie, /etc/localtime is a regular file while the actual name is in /etc/timezone
if (ianaId.isEmpty()) {
QFile tzif(QStringLiteral("/etc/timezone"));
if (tzif.open(QIODevice::ReadOnly)) {
@ -1061,16 +1072,6 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
}
}
// On other distros /etc/localtime is symlink to real file so can extract name from the path
if (ianaId.isEmpty()) {
const QString path = QFile::symLinkTarget(QStringLiteral("/etc/localtime"));
if (!path.isEmpty()) {
// /etc/localtime is a symlink to the current TZ file, so extract from path
int index = path.indexOf(QLatin1String("/zoneinfo/")) + 10;
ianaId = path.mid(index).toUtf8();
}
}
// On some Red Hat distros /etc/localtime is real file with name held in /etc/sysconfig/clock
// in a line like ZONE="Europe/Oslo" or TIMEZONE="Europe/Oslo"
if (ianaId.isEmpty()) {