app/core/ProcessTimeZone.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "ProcessTimeZone.h" | ||
| 2 | |||
| 3 | #include <QFileInfo> | ||
| 4 | #include <QLoggingCategory> | ||
| 5 | #include <QTimeZone> | ||
| 6 | #include <ctime> | ||
| 7 | |||
| 8 |
3/7✓ Branch 2 → 3 taken 3 times.
✗ Branch 2 → 8 not taken.
✓ Branch 4 → 5 taken 3 times.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 3 times.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
|
3 | Q_LOGGING_CATEGORY(lcProcessZone, "mailjd.timezone") |
| 9 | |||
| 10 | namespace { | ||
| 11 | bool g_pinned = false; | ||
| 12 | // F100-26: pin() runs before the log rules exist; its outcome is kept and | ||
| 13 | // written by logPinResult() once they apply (info, hidden by default). | ||
| 14 | QString g_pinResult; | ||
| 15 | |||
| 16 |
2/2✓ Branch 5 → 6 taken 2 times.
✓ Branch 6 → 7 taken 2 times.
|
4 | QString readLocaltimeLink() { return QFileInfo(QStringLiteral("/etc/localtime")).symLinkTarget(); } |
| 17 | |||
| 18 | 3 | void applyTz(const QByteArray &zoneId) { | |
| 19 |
1/1✓ Branch 3 → 4 taken 3 times.
|
3 | qputenv("TZ", zoneId); |
| 20 | 3 | tzset(); // glibc and Qt's local time follow the new TZ from here on | |
| 21 | 3 | } | |
| 22 | } // namespace | ||
| 23 | |||
| 24 | namespace ProcessTimeZone { | ||
| 25 | |||
| 26 | 11 | QByteArray zoneIdFromLink(const QString &linkTarget) { | |
| 27 | 11 | const QString marker = QStringLiteral("/zoneinfo/"); | |
| 28 |
1/1✓ Branch 6 → 7 taken 11 times.
|
11 | const int at = linkTarget.lastIndexOf(marker); |
| 29 |
2/2✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 9 taken 9 times.
|
11 | if (at < 0) return {}; |
| 30 |
1/1✓ Branch 10 → 11 taken 9 times.
|
9 | QString id = linkTarget.mid(at + marker.size()); |
| 31 | // posix/ and right/ are variants of the same zone database. | ||
| 32 |
4/4✓ Branch 12 → 13 taken 9 times.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 13 → 18 taken 8 times.
✓ Branch 14 → 15 taken 1 time.
|
9 | if (id.startsWith(QLatin1String("posix/"))) id = id.mid(6); |
| 33 |
2/4✓ Branch 19 → 20 taken 9 times.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 25 taken 9 times.
✗ Branch 21 → 22 not taken.
|
9 | if (id.startsWith(QLatin1String("right/"))) id = id.mid(6); |
| 34 |
1/1✓ Branch 25 → 26 taken 9 times.
|
9 | const QByteArray bytes = id.toUtf8(); |
| 35 |
3/3✓ Branch 26 → 27 taken 9 times.
✓ Branch 27 → 28 taken 8 times.
✓ Branch 27 → 29 taken 1 time.
|
9 | return QTimeZone::isTimeZoneIdAvailable(bytes) ? bytes : QByteArray(); |
| 36 | 11 | } | |
| 37 | |||
| 38 |
2/2✓ Branch 2 → 3 taken 2 times.
✓ Branch 3 → 4 taken 2 times.
|
2 | QByteArray systemZoneIdFromLink() { return zoneIdFromLink(readLocaltimeLink()); } |
| 39 | |||
| 40 | 2 | void logPinResult() { | |
| 41 |
3/7✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 16 not taken.
✓ Branch 4 → 5 taken 2 times.
✗ Branch 8 → 9 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 14 → 6 not taken.
✓ Branch 14 → 15 taken 2 times.
|
2 | if (!g_pinResult.isEmpty()) qCInfo(lcProcessZone).noquote() << g_pinResult; |
| 42 | 2 | } | |
| 43 | |||
| 44 | 3 | bool pin() { | |
| 45 |
2/2✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 17 taken 2 times.
|
3 | if (!qEnvironmentVariableIsEmpty("TZ")) { |
| 46 |
3/3✓ Branch 4 → 5 taken 1 time.
✓ Branch 5 → 6 taken 1 time.
✓ Branch 9 → 10 taken 1 time.
|
2 | g_pinResult = QStringLiteral("TZ set by the environment: ") + QString::fromLocal8Bit(qgetenv("TZ")); |
| 47 | 1 | return false; | |
| 48 | } | ||
| 49 |
1/1✓ Branch 17 → 18 taken 2 times.
|
2 | const QByteArray zone = systemZoneIdFromLink(); |
| 50 |
1/2✗ Branch 19 → 20 not taken.
✓ Branch 19 → 27 taken 2 times.
|
2 | if (zone.isEmpty()) { |
| 51 | ✗ | g_pinResult = QStringLiteral("/etc/localtime names no zone; TZ stays unset"); | |
| 52 | ✗ | return false; | |
| 53 | } | ||
| 54 |
1/1✓ Branch 27 → 28 taken 2 times.
|
2 | applyTz(zone); |
| 55 | 2 | g_pinned = true; | |
| 56 |
2/2✓ Branch 28 → 29 taken 2 times.
✓ Branch 32 → 33 taken 2 times.
|
4 | g_pinResult = QStringLiteral("TZ pinned to the system zone ") + QString::fromUtf8(zone); |
| 57 | 2 | return true; | |
| 58 | 2 | } | |
| 59 | |||
| 60 | 767 | bool pinned() { return g_pinned; } | |
| 61 | |||
| 62 | } // namespace ProcessTimeZone | ||
| 63 | |||
| 64 | 766 | ProcessTimeZoneWatcher::ProcessTimeZoneWatcher(QObject *parent) | |
| 65 |
2/2✓ Branch 3 → 4 taken 766 times.
✓ Branch 4 → 5 taken 766 times.
|
766 | : QObject(parent), m_zone(qgetenv("TZ")), m_reader(readLocaltimeLink) { |
| 66 |
1/2✓ Branch 7 → 8 taken 766 times.
✗ Branch 7 → 9 not taken.
|
766 | if (!ProcessTimeZone::pinned()) return; // TZ unset or set by the user: nothing to follow |
| 67 | ✗ | m_timer.setInterval(60 * 1000); | |
| 68 | ✗ | connect(&m_timer, &QTimer::timeout, this, &ProcessTimeZoneWatcher::check); | |
| 69 | ✗ | m_timer.start(); | |
| 70 | ✗ | } | |
| 71 | |||
| 72 | 3 | void ProcessTimeZoneWatcher::check() { | |
| 73 |
2/2✓ Branch 2 → 3 taken 3 times.
✓ Branch 3 → 4 taken 3 times.
|
3 | const QByteArray zone = ProcessTimeZone::zoneIdFromLink(m_reader()); |
| 74 |
5/6✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 9 not taken.
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 10 taken 1 time.
✓ Branch 11 → 12 taken 2 times.
✓ Branch 11 → 13 taken 1 time.
|
3 | if (zone.isEmpty() || zone == m_zone) return; |
| 75 |
8/8✓ Branch 13 → 14 taken 1 time.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 18 → 19 taken 1 time.
✓ Branch 19 → 20 taken 1 time.
✓ Branch 20 → 21 taken 1 time.
✓ Branch 21 → 22 taken 1 time.
✓ Branch 25 → 15 taken 1 time.
✓ Branch 25 → 26 taken 1 time.
|
2 | qCInfo(lcProcessZone) << "System time zone changed" << m_zone << "->" << zone; |
| 76 | 1 | m_zone = zone; | |
| 77 |
1/1✓ Branch 27 → 28 taken 1 time.
|
1 | applyTz(zone); |
| 78 |
1/1✓ Branch 28 → 29 taken 1 time.
|
1 | emit changed(zone); |
| 79 | 3 | } | |
| 80 |