* gnu/packages/qt.scm (qtbase) [native-inputs]: Add tzdata-for-tests. [arguments]: Set the TZDIR and TZ environment variables, and reinstate the tst_qdate, tst_qtimezone and tst_qdatetime tests in the check phase. (qtbase-5) [source]: Replace qtbase-use-TZDIR.patch with qtbase-5-use-TZDIR.patch. * gnu/packages/patches/qtbase-use-TZDIR.patch: Refresh patch with upstream version, and preserve the old one for qtbase@5 as... * gnu/packages/patches/qtbase-5-use-TZDIR.patch: ... this. * gnu/local.mk (dist_patch_DATA): Register new patch. Series-changes: 2 - Use old TZDIR patch for qtbase@5 (the new one doesn't apply)
		
			
				
	
	
		
			141 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			141 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 1075606f8b2f9e153c82f8e50cbd69cea9c72e87 Mon Sep 17 00:00:00 2001
 | |
| From: Edward Welbourne <edward.welbourne@qt.io>
 | |
| Date: Mon, 11 Sep 2023 11:41:39 +0200
 | |
| Subject: [PATCH] Support the TZDIR environment variable
 | |
| 
 | |
| On Linux / glibc, this overrides the default system location for the
 | |
| zone info. So check for files there first. Break out a function to
 | |
| manage the trying of (now three) zoneinfo directories when opening a
 | |
| file by name relative to there.
 | |
| 
 | |
| Pick-to: 6.6 6.5
 | |
| Task-number: QTBUG-116017
 | |
| Change-Id: I1f97107aabd9015c0a5543639870f1d70654ca67
 | |
| ---
 | |
| * Rebased on top of v6.5.2.
 | |
| 
 | |
|  src/corelib/time/qtimezoneprivate_tz.cpp | 73 ++++++++++++++++--------
 | |
|  1 file changed, 49 insertions(+), 24 deletions(-)
 | |
| 
 | |
| diff --git a/src/corelib/time/qtimezoneprivate_tz.cpp b/src/corelib/time/qtimezoneprivate_tz.cpp
 | |
| index 067191d816..a8b2fc894e 100644
 | |
| --- a/src/corelib/time/qtimezoneprivate_tz.cpp
 | |
| +++ b/src/corelib/time/qtimezoneprivate_tz.cpp
 | |
| @@ -51,17 +51,41 @@ typedef QHash<QByteArray, QTzTimeZone> QTzTimeZoneHash;
 | |
|  
 | |
|  static bool isTzFile(const QString &name);
 | |
|  
 | |
| +// Open a named file under the zone info directory:
 | |
| +static bool openZoneInfo(QString name, QFile *file)
 | |
| +{
 | |
| +    // At least on Linux / glibc (see man 3 tzset), $TZDIR overrides the system
 | |
| +    // default location for zone info:
 | |
| +    const QString tzdir = qEnvironmentVariable("TZDIR");
 | |
| +    if (!tzdir.isEmpty()) {
 | |
| +        file->setFileName(QDir(tzdir).filePath(name));
 | |
| +        if (file->open(QIODevice::ReadOnly))
 | |
| +            return true;
 | |
| +    }
 | |
| +    // Try modern system path first:
 | |
| +    constexpr auto zoneShare = "/usr/share/zoneinfo/"_L1;
 | |
| +    if (tzdir != zoneShare && tzdir != zoneShare.chopped(1)) {
 | |
| +        file->setFileName(zoneShare + name);
 | |
| +        if (file->open(QIODevice::ReadOnly))
 | |
| +            return true;
 | |
| +    }
 | |
| +    // Fall back to legacy system path:
 | |
| +    constexpr auto zoneLib = "/usr/lib/zoneinfo/"_L1;
 | |
| +    if (tzdir != zoneLib && tzdir != zoneLib.chopped(1)) {
 | |
| +        file->setFileName(zoneShare + name);
 | |
| +        if (file->open(QIODevice::ReadOnly))
 | |
| +            return true;
 | |
| +    }
 | |
| +    return false;
 | |
| +}
 | |
| +
 | |
|  // Parse zone.tab table for territory information, read directories to ensure we
 | |
|  // find all installed zones (many are omitted from zone.tab; even more from
 | |
|  // zone1970.tab).
 | |
|  static QTzTimeZoneHash loadTzTimeZones()
 | |
|  {
 | |
| -    QString path = QStringLiteral("/usr/share/zoneinfo/zone.tab");
 | |
| -    if (!QFile::exists(path))
 | |
| -        path = QStringLiteral("/usr/lib/zoneinfo/zone.tab");
 | |
| -
 | |
| -    QFile tzif(path);
 | |
| -    if (!tzif.open(QIODevice::ReadOnly))
 | |
| +    QFile tzif;
 | |
| +    if (!openZoneInfo("zone.tab"_L1, &tzif))
 | |
|          return QTzTimeZoneHash();
 | |
|  
 | |
|      QTzTimeZoneHash zonesHash;
 | |
| @@ -91,6 +115,7 @@ static QTzTimeZoneHash loadTzTimeZones()
 | |
|          }
 | |
|      }
 | |
|  
 | |
| +    const QString path = tzif.fileName();
 | |
|      const qsizetype cut = path.lastIndexOf(u'/');
 | |
|      Q_ASSERT(cut > 0);
 | |
|      const QDir zoneDir = QDir(path.first(cut));
 | |
| @@ -761,20 +786,13 @@ QTzTimeZoneCacheEntry QTzTimeZoneCache::findEntry(const QByteArray &ianaId)
 | |
|          tzif.setFileName(QStringLiteral("/etc/localtime"));
 | |
|          if (!tzif.open(QIODevice::ReadOnly))
 | |
|              return ret;
 | |
| -    } else {
 | |
| -        // Open named tz, try modern path first, if fails try legacy path
 | |
| -        tzif.setFileName("/usr/share/zoneinfo/"_L1 + QString::fromLocal8Bit(ianaId));
 | |
| -        if (!tzif.open(QIODevice::ReadOnly)) {
 | |
| -            tzif.setFileName("/usr/lib/zoneinfo/"_L1 + QString::fromLocal8Bit(ianaId));
 | |
| -            if (!tzif.open(QIODevice::ReadOnly)) {
 | |
| -                // ianaId may be a POSIX rule, taken from $TZ or /etc/TZ
 | |
| -                auto check = validatePosixRule(ianaId);
 | |
| -                if (check.isValid) {
 | |
| -                    ret.m_hasDst = check.hasDst;
 | |
| -                    ret.m_posixRule = ianaId;
 | |
| -                }
 | |
| -                return ret;
 | |
| -            }
 | |
| +    } else if (!openZoneInfo(QString::fromLocal8Bit(ianaId), &tzif)) {
 | |
| +        // ianaId may be a POSIX rule, taken from $TZ or /etc/TZ
 | |
| +        auto check = validatePosixRule(ianaId);
 | |
| +        if (check.isValid) {
 | |
| +            ret.m_hasDst = check.hasDst;
 | |
| +            ret.m_posixRule = ianaId;
 | |
| +            return ret;
 | |
|          }
 | |
|      }
 | |
|  
 | |
| @@ -1317,7 +1335,8 @@ private:
 | |
|      {
 | |
|          // On most distros /etc/localtime is a symlink to a real file so extract
 | |
|          // name from the path
 | |
| -        const auto zoneinfo = "/zoneinfo/"_L1;
 | |
| +        const QString tzdir = qEnvironmentVariable("TZDIR");
 | |
| +        constexpr auto zoneinfo = "/zoneinfo/"_L1;
 | |
|          QString path = QStringLiteral("/etc/localtime");
 | |
|          long iteration = getSymloopMax();
 | |
|          // Symlink may point to another symlink etc. before being under zoneinfo/
 | |
| @@ -1325,9 +1344,15 @@ private:
 | |
|          // symlink, like America/Montreal pointing to America/Toronto
 | |
|          do {
 | |
|              path = QFile::symLinkTarget(path);
 | |
| -            int index = path.indexOf(zoneinfo);
 | |
| -            if (index >= 0) // Found zoneinfo file; extract zone name from path:
 | |
| -                return QStringView{ path }.mid(index + zoneinfo.size()).toUtf8();
 | |
| +            // If it's a zoneinfo file, extract the zone name from its path:
 | |
| +            int index = tzdir.isEmpty() ? -1 : path.indexOf(tzdir);
 | |
| +            if (index >= 0) {
 | |
| +                const auto tail = QStringView{ path }.sliced(index + tzdir.size()).toUtf8();
 | |
| +                return tail.startsWith(u'/') ? tail.sliced(1) : tail;
 | |
| +            }
 | |
| +            index = path.indexOf(zoneinfo);
 | |
| +            if (index >= 0)
 | |
| +                return QStringView{ path }.sliced(index + zoneinfo.size()).toUtf8();
 | |
|          } while (!path.isEmpty() && --iteration > 0);
 | |
|  
 | |
|          return QByteArray();
 | |
| 
 | |
| base-commit: af457a9f0f7eb1a2a7d11f495da508faab91a442
 | |
| -- 
 | |
| 2.41.0
 | |
| 
 |