OSDN Git Service

rebase on original ktimezoned implementation
authorIvailo Monev <xakepa10@gmail.com>
Sat, 6 Dec 2014 20:23:17 +0000 (20:23 +0000)
committerIvailo Monev <xakepa10@gmail.com>
Sat, 6 Dec 2014 20:23:17 +0000 (20:23 +0000)
kcontrol/dateandtime/helper.cpp
ktimezoned/ktimezoned.cpp
ktimezoned/ktimezoned.h

index 01cbe58..8eb224a 100644 (file)
@@ -139,7 +139,8 @@ int ClockHelper::tz( const QString& selectedzone )
         }
         QString tz = ZONE_INFO_DIR + selectedzone;
 
-        if (!QFile::remove("/etc/localtime")) {
+        QFile f("/etc/localtime");
+        if (f.exists() && !f.remove()) {
           ret |= TimezoneError;
         }
         if (!QFile::link(tz, "/etc/localtime")) {
index a75c62e..fef5531 100644 (file)
@@ -57,6 +57,7 @@ const int MAX_ZONE_TAB_LINE_LENGTH = 2000;
 
 // Config file entry names
 const char ZONEINFO_DIR[]   = "ZoneinfoDir";   // path to zoneinfo/ directory
+const char ZONE_TAB[]       = "Zonetab";       // path & name of zone.tab
 const char LOCAL_ZONE[]     = "LocalZone";     // name of local time zone
 
 
@@ -97,99 +98,116 @@ void KTimeZoned::init(bool restart)
         config.reparseConfiguration();
     KConfigGroup group(&config, "TimeZones");
     mZoneinfoDir     = group.readEntry(ZONEINFO_DIR);
+    mZoneTab         = group.readEntry(ZONE_TAB);
     mConfigLocalZone = group.readEntry(LOCAL_ZONE);
     if (mZoneinfoDir.length() > 1 && mZoneinfoDir.endsWith('/'))
         mZoneinfoDir.truncate(mZoneinfoDir.length() - 1);   // strip trailing '/'
 
-    // Search for zone.tab
-    if (!findZoneTab())
-        return;
+    // For Unix, read zone.tab.
 
-    // Read zone.tab and create a collection of KTimeZone instances
-    readZoneTab();
+    QString oldZoneinfoDir = mZoneinfoDir;
+    QString oldZoneTab     = mZoneTab;
 
-    mZonetabWatch = new KDirWatch(this);
-    mZonetabWatch->addFile(mZoneTab);
-    connect(mZonetabWatch, SIGNAL(dirty(const QString&)), SLOT(zonetab_Changed(const QString&)));
+    // Open zone.tab if we already know where it is
+    QFile f;
+    if (!mZoneTab.isEmpty() && !mZoneinfoDir.isEmpty())
+    {
+        f.setFileName(mZoneTab);
+        if (!f.open(QIODevice::ReadOnly)) {
+            mZoneTab.clear();
+        }
+    }
+
+    if (mZoneTab.isEmpty() || mZoneinfoDir.isEmpty())
+    {
+        // Search for zone.tab
+        if (!findZoneTab(f))
+            return;
+        mZoneTab = f.fileName();
 
-    // Respect the config above all
-    if (!mConfigLocalZone.isEmpty()) {
-        // We know the local zone from last time.
-        // Check whether the file still matches it.
-        KTimeZone local = mZones.zone(mConfigLocalZone);
-        if (local.isValid())
+        if (mZoneinfoDir != oldZoneinfoDir
+        ||  mZoneTab != oldZoneTab)
         {
-            mLocalZone = mConfigLocalZone;
-            mLocalZoneDataFile = mZoneinfoDir + "/" + mConfigLocalZone;
+            // Update config file and notify interested applications
+            group.writeEntry(ZONEINFO_DIR, mZoneinfoDir);
+            group.writeEntry(ZONE_TAB, mZoneTab);
+            group.sync();
+            QDBusMessage message = QDBusMessage::createSignal("/Daemon", "org.kde.KTimeZoned", "configChanged");
+            QDBusConnection::sessionBus().send(message);
         }
     }
 
+    // Read zone.tab and create a collection of KTimeZone instances
+    readZoneTab(f);
+
+    mZonetabWatch = new KDirWatch(this);
+    mZonetabWatch->addFile(mZoneTab);
+    connect(mZonetabWatch, SIGNAL(dirty(const QString&)), SLOT(zonetab_Changed(const QString&)));
+
     // Find the local system time zone and set up file monitors to detect changes
     findLocalZone();
 }
 
-// Check if the local zone has been updated, and if so, notify interested parties.
+// Check if the local zone has been updated, and if so, write the new
+// zone to the config file and notify interested parties.
 void KTimeZoned::updateLocalZone()
 {
-    kDebug(1221) << "updating timezone" << mLocalZone;
-    KConfig config(QLatin1String("ktimezonedrc"));
-    KConfigGroup group(&config, "TimeZones");
-    mConfigLocalZone = mLocalZone;
-    group.writeEntry(ZONEINFO_DIR, mZoneinfoDir);
-    group.writeEntry(LOCAL_ZONE, mConfigLocalZone);
-    group.sync();
-
-    QDBusMessage message = QDBusMessage::createSignal("/Daemon", "org.kde.KTimeZoned", "configChanged");
-    QDBusConnection::sessionBus().send(message);
+    if (mConfigLocalZone != mLocalZone)
+    {
+        KConfig config(QLatin1String("ktimezonedrc"));
+        KConfigGroup group(&config, "TimeZones");
+        mConfigLocalZone = mLocalZone;
+        group.writeEntry(LOCAL_ZONE, mConfigLocalZone);
+        group.sync();
+
+        QDBusMessage message = QDBusMessage::createSignal("/Daemon", "org.kde.KTimeZoned", "configChanged");
+        QDBusConnection::sessionBus().send(message);
+    }
 }
 
 /*
  * Find the location of the zoneinfo files and store in mZoneinfoDir.
  * Open or if necessary create zone.tab.
  */
-bool KTimeZoned::findZoneTab()
+bool KTimeZoned::findZoneTab(QFile& f)
 {
-    QString zonetabFile = "/zone.tab";
-    QString zoneinfoDir;
-
-    if (!mZoneinfoDir.isEmpty() && QDir(mZoneinfoDir).exists()) {
-        // It has most likely already been set by preferences in the config
-        zoneinfoDir = mZoneinfoDir;
-    }
+    QString ZONE_TAB_FILE = "/zone.tab";
+    QString ZONE_INFO_DIR;
 
     if (QDir("/usr/share/zoneinfo").exists()) {
-        zoneinfoDir = "/usr/share/zoneinfo";
+        ZONE_INFO_DIR = "/usr/share/zoneinfo";
     } else if (QDir("/usr/lib/zoneinfo").exists()) {
-        zoneinfoDir = "/usr/lib/zoneinfo";
+        ZONE_INFO_DIR = "/usr/lib/zoneinfo";
     } else if (QDir("/share/zoneinfo").exists()) {
-        zoneinfoDir = "/share/zoneinfo";
+        ZONE_INFO_DIR = "/share/zoneinfo";
     } else if (QDir("/lib/zoneinfo").exists()) {
-        zoneinfoDir = "/lib/zoneinfo";
+        ZONE_INFO_DIR = "/lib/zoneinfo";
     } else {
         // /usr is kind of standard
-        zoneinfoDir = "/usr/share/zoneinfo";
+        ZONE_INFO_DIR = "/usr/share/zoneinfo";
     }
 
     // Find and open zone.tab - it's all easy except knowing where to look.
     QDir dir;
+    QString zoneinfoDir = ZONE_INFO_DIR;
     // make a note if the dir exists; whether it contains zone.tab or not
     if (dir.exists(zoneinfoDir))
     {
         mZoneinfoDir = zoneinfoDir;
-        if (QFile(zoneinfoDir + zonetabFile).exists())
-            mZoneTab = zoneinfoDir + zonetabFile;
+        f.setFileName(zoneinfoDir + ZONE_TAB_FILE);
+        if (f.open(QIODevice::ReadOnly))
             return true;
-        kDebug(1221) << "Can't find zone tab";
+        kDebug(1221) << "Can't open " << f.fileName();
     }
 
     zoneinfoDir = ::getenv("TZDIR");
     if (!zoneinfoDir.isEmpty() && dir.exists(zoneinfoDir))
     {
         mZoneinfoDir = zoneinfoDir;
-        if (QFile(zoneinfoDir + zonetabFile).exists())
-            mZoneTab = zoneinfoDir + zonetabFile;
+        f.setFileName(zoneinfoDir + ZONE_TAB_FILE);
+        if (f.open(QIODevice::ReadOnly))
             return true;
-        kDebug(1221) << "Can't find zone tab via TZDIR either";
+        kDebug(1221) << "Can't open " << f.fileName();
     }
 
     return false;
@@ -197,16 +215,10 @@ bool KTimeZoned::findZoneTab()
 
 // Parse zone.tab and for each time zone, create a KSystemTimeZone instance.
 // Note that only data needed by this module is specified to KSystemTimeZone.
-bool KTimeZoned::readZoneTab()
+void KTimeZoned::readZoneTab(QFile &f)
 {
-    kDebug(1221) << "reading zone.tab";
     // Parse the already open real or fake zone.tab.
     QRegExp lineSeparator("[ \t]");
-    QFile f(mZoneTab);
-    if (!f.open(QIODevice::ReadOnly)) {
-        return false;
-    }
-    bool success = false;
     if (!mSource)
         mSource = new KSystemTimeZoneSource;
     mZones.clear();
@@ -234,10 +246,6 @@ bool KTimeZoned::readZoneTab()
         mZones.add(KSystemTimeZone(mSource, tokens[2], tokens[0]));
     }
     f.close();
-    if (success) {
-        return true;
-    }
-    return false;
 }
 
 // Find the local time zone, starting from scratch.
@@ -246,41 +254,84 @@ void KTimeZoned::findLocalZone()
     delete mDirWatch;
     mDirWatch = 0;
     mLocalZone.clear();
+    mLocalIdFile.clear();
     mLocalZoneDataFile.clear();
 
-    // First try the checking for TZ envinomental variable.
+    // SOLUTION 1: DEFINITIVE.
+    // First try the simplest solution of checking for well-formed TZ setting.
     const char *envtz = ::getenv("TZ");
-    checkEnv(envtz);
+    if (checkTZ(envtz)) {
+        mSavedTZ = envtz;
+        if (!mLocalZone.isEmpty()) kDebug(1221)<<"TZ: "<<mLocalZone;
+    }
 
+    if (mLocalZone.isEmpty()) {
+        // SOLUTION 2: DEFINITIVE.
+        // BSD & Linux support: local time zone id in /etc/timezone.
+        checkTimezone();
+    }
     if (mLocalZone.isEmpty() && !mZoneinfoDir.isEmpty()) {
+        // SOLUTION 3: DEFINITIVE.
+        // Try to follow any /etc/localtime symlink to a zoneinfo file.
+        // SOLUTION 4: DEFINITIVE.
         // Try to match /etc/localtime against the list of zoneinfo files.
-        // Resolve symlink
-        QFileInfo fi(QFile("/etc/localtime"));
-        if (fi.isSymLink()) {
-            checkLocaltime(fi.canonicalFilePath());
-        } else {
-            checkLocaltime(QLatin1String("/etc/localtime"));
-        }
+        matchZoneFile(QLatin1String("/etc/localtime"));
     }
 
-    // Failsafe, fallback to UTC
     if (mLocalZone.isEmpty()) {
-        mLocalZone = KTimeZone::utc().name();
-        kDebug(1221) << "Failsafe: " << mLocalZone;
+        // The local time zone is not defined by a file.
+        // Watch for creation of /etc/localtime in case it gets created later.
+        mLocalIdFile = QLatin1String("/etc/localtime");
     }
-
-    // Watch for changes in the file defining the local time zone
+    // Watch for changes in the file defining the local time zone so as to be
+    // notified of any change in it.
     mDirWatch = new KDirWatch(this);
-    mDirWatch->addFile("/etc/localtime");
-    if (!mLocalZoneDataFile.isEmpty())
+    mDirWatch->addFile(mLocalIdFile);
+    if (!mLocalZoneDataFile.isEmpty()) {
         mDirWatch->addFile(mLocalZoneDataFile);
-        kDebug(1221) << "watching" << mLocalZoneDataFile;
+    }
     connect(mDirWatch, SIGNAL(dirty(const QString&)), SLOT(localChanged(const QString&)));
     connect(mDirWatch, SIGNAL(deleted(const QString&)), SLOT(localChanged(const QString&)));
     connect(mDirWatch, SIGNAL(created(const QString&)), SLOT(localChanged(const QString&)));
-    mDirWatch->startScan();
 
-    // Finally, if the local zone identity has changed, let the world know
+    if (mLocalZone.isEmpty() && !mZoneinfoDir.isEmpty()) {
+        // SOLUTION 5: HEURISTIC.
+        // None of the deterministic stuff above has worked: try a heuristic. We
+        // try to find a pair of matching time zone abbreviations...that way, we'll
+        // likely return a value in the user's own country.
+        tzset();
+        QByteArray tzname0(tzname[0]);   // store copies, because zone.parse() will change them
+        QByteArray tzname1(tzname[1]);
+        int bestOffset = INT_MAX;
+        KSystemTimeZoneSource::startParseBlock();
+        const KTimeZones::ZoneMap zmap = mZones.zones();
+        for (KTimeZones::ZoneMap::ConstIterator it = zmap.constBegin(), end = zmap.constEnd();  it != end;  ++it) {
+            KTimeZone zone = it.value();
+            int candidateOffset = qAbs(zone.currentOffset(Qt::LocalTime));
+            if (candidateOffset < bestOffset &&  zone.parse()) {
+                QList<QByteArray> abbrs = zone.abbreviations();
+                if (abbrs.contains(tzname0)  &&  abbrs.contains(tzname1)) {
+                    // kDebug(1221) << "local=" << zone.name();
+                    mLocalZone = zone.name();
+                    bestOffset = candidateOffset;
+                    if (!bestOffset)
+                        break;
+                }
+            }
+        }
+        KSystemTimeZoneSource::endParseBlock();
+        if (!mLocalZone.isEmpty()) {
+            kDebug(1221)<<"tzname: "<<mLocalZone;
+        }
+    }
+    if (mLocalZone.isEmpty()) {
+        // SOLUTION 6: FAILSAFE.
+        mLocalZone = KTimeZone::utc().name();
+        if (!mLocalZone.isEmpty()) kDebug(1221)<<"Failsafe: "<<mLocalZone;
+    }
+
+    // Finally, if the local zone identity has changed, store
+    // the new one in the config file.
     updateLocalZone();
 }
 
@@ -301,67 +352,240 @@ void KTimeZoned::zonetab_Changed(const QString& path)
     // Reread zone.tab and recreate the collection of KTimeZone instances,
     // in case any zones have been created or deleted and one of them
     // subsequently becomes the local zone.
-    if (!readZoneTab()) {
+    QFile f;
+    f.setFileName(mZoneTab);
+    if (!f.open(QIODevice::ReadOnly)) {
         kError(1221) << "Could not open zone.tab (" << mZoneTab << ") to reread";
+    } else {
+        readZoneTab(f);
     }
 }
 
 // Called when KDirWatch detects a change
 void KTimeZoned::localChanged(const QString& path)
 {
-    kDebug(1221) << path << "changed";
-    findLocalZone();
+    if (path == mLocalZoneDataFile) {
+        // Only need to update the definition of the local zone,
+        // not its identity.
+        QDBusMessage message = QDBusMessage::createSignal("/Daemon", "org.kde.KTimeZoned", "zoneDefinitionChanged");
+        QList<QVariant> args;
+        args += mLocalZone;
+        message.setArguments(args);
+        QDBusConnection::sessionBus().send(message);
+        return;
+    }
+    QString oldDataFile = mLocalZoneDataFile;
+    const char *envtz = ::getenv("TZ");
+    if (mSavedTZ != envtz) {
+                // TZ has changed - start from scratch again
+                findLocalZone();
+                return;
+    }
+    matchZoneFile(mLocalIdFile);
+    checkTimezone();
+
+    if (oldDataFile != mLocalZoneDataFile) {
+        if (!oldDataFile.isEmpty()) {
+            mDirWatch->removeFile(oldDataFile);
+        }
+        if (!mLocalZoneDataFile.isEmpty()) {
+            mDirWatch->addFile(mLocalZoneDataFile);
+        }
+    }
+    updateLocalZone();
 }
 
-bool KTimeZoned::checkEnv(const char *envZone)
+bool KTimeZoned::checkTZ(const char *envZone)
 {
-    if (!mLocalZone.isEmpty()) {
-        // It has most likely already been set by preferences in the config
-        return true;
-    }
+    // SOLUTION 1: DEFINITIVE.
+    // First try the simplest solution of checking for well-formed TZ setting.
     if (envZone) {
+        if (envZone[0] == '\0') {
+            mLocalZone = KTimeZone::utc().name();
+            mLocalIdFile.clear();
+            mLocalZoneDataFile.clear();
+            return true;
+        }
         if (envZone[0] == ':') {
-            // TZ specified, either relative to zoneinfo/ or absolute.
-            QString tz = QFile::decodeName(envZone + 1);
-            KTimeZone local = mZones.zone(tz);
-            if (!local.isValid()) {
-                return false;
+            // TZ specifies a file name, either relative to zoneinfo/ or absolute.
+            QString TZfile = QFile::decodeName(envZone + 1);
+            if (TZfile.startsWith(mZoneinfoDir)) {
+                // It's an absolute file name in the zoneinfo directory.
+                // Convert it to a file name relative to zoneinfo/.
+                TZfile = TZfile.mid(mZoneinfoDir.length());
             }
-            mLocalZone = tz;
-            if (QFile(tz).exists()) {
-                // Full path.
-                mLocalZoneDataFile = tz;
-            } else {
-                // Relative path.
-                mLocalZoneDataFile = mZoneinfoDir + "/" + tz;
+            if (TZfile.startsWith(QLatin1Char('/'))) {
+                // It's an absolute file name.
+                QString symlink;
+                if (matchZoneFile(TZfile))
+                {
+                    return true;
+                }
+            } else if (!TZfile.isEmpty()) {
+                // It's a file name relative to zoneinfo/
+                mLocalZone = TZfile;
+                if (!mLocalZone.isEmpty())
+                {
+                    mLocalZoneDataFile = mZoneinfoDir + '/' + TZfile;
+                    mLocalIdFile.clear();
+                    return true;
+                }
             }
         }
     }
     return false;
 }
 
-bool KTimeZoned::checkLocaltime(const QString &path)
+bool KTimeZoned::checkTimezone()
 {
-    if (!mLocalZone.isEmpty()) {
-        // It has most likely already been set by preferences in the config
-        return true;
+    // SOLUTION 2: DEFINITIVE.
+    // BSD support.
+    QFile f;
+    f.setFileName(QLatin1String("/etc/timezone"));
+    if (!f.open(QIODevice::ReadOnly)) {
+        return false;
     }
-
-    if (mZoneinfoDir.isEmpty() && !path.indexOf(mZoneinfoDir)) {
-        kDebug(1221) << "relative path passed to checkLocaltime()";
+    // Read the first line of the file.
+    QTextStream ts(&f);
+    ts.setCodec("ISO-8859-1");
+    QString zoneName;
+    if (!ts.atEnd()) {
+        zoneName = ts.readLine();
+    }
+    f.close();
+    if (zoneName.isEmpty()) {
+        return false;
+    }
+    if (!setLocalZone(zoneName)) {
         return false;
     }
+    mLocalIdFile = f.fileName();
+    kDebug(1221)<<"/etc/timezone: "<<mLocalZone;
+    return true;
+}
 
-    // The path could be full path, remove zoneinfo directory reference
-    QString rel = path.mid(mZoneinfoDir.length() + 1);
+bool KTimeZoned::matchZoneFile(const QString &path)
+{
+    // SOLUTION 3: DEFINITIVE.
+    // Try to follow any symlink to a zoneinfo file.
+    // Get the path of the file which the symlink points to.
+    QFile f;
+    f.setFileName(path);
+    QFileInfo fi(f);
+    if (fi.isSymLink()) {
+        // The file is a symlink.
+        QString zoneInfoFileName = fi.canonicalFilePath();
+        QFileInfo fiz(zoneInfoFileName);
+        if (fiz.exists() && fiz.isReadable()) {
+            if (zoneInfoFileName.startsWith(mZoneinfoDir)) {
+                // We've got the zoneinfo file path.
+                // The time zone name is the part of the path after the zoneinfo directory.
+                // Note that some systems (e.g. Gentoo) have zones under zoneinfo which
+                // are not in zone.tab, so don't validate against mZones.
+                mLocalZone = zoneInfoFileName.mid(mZoneinfoDir.length() + 1);
+                // kDebug(1221) << "local=" << mLocalZone;
+            } else {
+                // It isn't a zoneinfo file or a copy thereof.
+                // Use the absolute path as the time zone name.
+                mLocalZone = f.fileName();
+            }
+            mLocalIdFile = f.fileName();
+            mLocalZoneDataFile = zoneInfoFileName;
+            kDebug(1221)<<mLocalIdFile<<": "<<mLocalZone;
+            return true;
+        }
+    }
+    else if (f.open(QIODevice::ReadOnly)) {
+        // SOLUTION 4: DEFINITIVE.
+        // Try to match the file against the list of zoneinfo files.
+
+        KTimeZone local;
+        QString zoneName;
+
+        if (!mConfigLocalZone.isEmpty()) {
+            // We know the local zone from last time.
+            // Check whether the file still matches it.
+            KTimeZone tzone = mZones.zone(mConfigLocalZone);
+            if (tzone.isValid()) {
+                zoneName = local.name();
+            }
+        }
 
-    KTimeZone local = mZones.zone(rel);
-    if (!local.isValid()) {
-        return false;
+        if (!local.isValid() && mHaveCountryCodes) {
+            /* Look for time zones with the user's country code.
+             * This has two advantages: 1) it shortens the search;
+             * 2) it increases the chance of the correctly titled time zone
+             * being found, since multiple time zones can have identical
+             * definitions. For example, Europe/Guernsey is identical to
+             * Europe/London, but the latter is more likely to be the right
+             * zone name for a user with 'gb' country code.
+             */
+            QString country = KGlobal::locale()->country().toUpper();
+            const KTimeZones::ZoneMap zmap = mZones.zones();
+            for (KTimeZones::ZoneMap::ConstIterator zit = zmap.constBegin(), zend = zmap.constEnd();  zit != zend;  ++zit) {
+                KTimeZone tzone = zit.value();
+                if (tzone.countryCode() == country) {
+                    if (tzone.isValid()) {
+                        zoneName = tzone.name();
+                        break;
+                    }
+                }
+            }
+        }
+
+        bool success = false;
+        if (local.isValid()) {
+            // The file matches a zoneinfo file
+            mLocalZone = zoneName;
+            mLocalZoneDataFile = mZoneinfoDir + '/' + zoneName;
+            success = true;
+        } else {
+            // The file doesn't match a zoneinfo file. If it's a TZfile, use it directly.
+            // Read the file type identifier.
+            char buff[4];
+            f.reset();
+            QDataStream str(&f);
+            if (str.readRawData(buff, 4) == 4
+            &&  buff[0] == 'T' && buff[1] == 'Z' && buff[2] == 'i' && buff[3] == 'f')
+            {
+                // Use its absolute path as the zone name.
+                mLocalZone = f.fileName();
+                mLocalZoneDataFile.clear();
+                success = true;
+            }
+        }
+        f.close();
+        if (success) {
+            mLocalIdFile = f.fileName();
+            kDebug(1221)<<mLocalIdFile<<": "<<mLocalZone;
+            return true;
+        }
     }
+    return false;
+}
 
-    mLocalZone = rel;
-    mLocalZoneDataFile = path;
-    kDebug(1221) << mLocalZone;
+// Check whether the zone name is valid, either as a zone in zone.tab or
+// as another file in the zoneinfo directory.
+// If valid, set the local zone information.
+bool KTimeZoned::setLocalZone(const QString &zoneName)
+{
+    KTimeZone local = mZones.zone(zoneName);
+    if (!local.isValid()) {
+        // It isn't a recognised zone in zone.tab.
+        // Note that some systems (e.g. Gentoo) have zones under zoneinfo which
+        // are not in zone.tab, so check if it points to another zone file.
+        if (mZoneinfoDir.isEmpty())
+            return false;
+        QString path = mZoneinfoDir + '/' + zoneName;
+        QFile qf;
+        qf.setFileName(path);
+        QFileInfo fi(qf);
+        if (fi.isSymLink())
+            fi.setFile(fi.canonicalFilePath());
+        if (!fi.exists() || !fi.isReadable())
+            return false;
+    }
+    mLocalZone = zoneName;
+    mLocalZoneDataFile = mZoneinfoDir.isEmpty() ? QString() : mZoneinfoDir + '/' + zoneName;
     return true;
 }
index e376559..6a91011 100644 (file)
@@ -45,28 +45,25 @@ class KTimeZoned : public KTimeZonedBase
         void  localChanged(const QString& path);
 
     private:
-        // How the local time zone is specified
-        enum LocalMethod
-        {
-            Utc,            // use UTC default: no local zone spec was found
-            EnvTz,          // specified in TZ environment variable
-            Localtime,      // specified in /etc/localtime
-        };
-
         /** reimp */
         void  init(bool restart);
-        bool  findZoneTab();
-        bool  readZoneTab();
+        bool  findZoneTab(QFile& f);
+        void  readZoneTab(QFile& f);
         void  findLocalZone();
-        bool  checkEnv(const char *envZone);
-        bool  checkLocaltime(const QString &path);
+        bool  checkTZ(const char *envZone);
+        bool  checkLocaltimeLink();
+        bool  checkLocaltimeFile();
+        bool  checkTimezone();
         void  updateLocalZone();
-        bool  setLocalZone(const QString &path);
+        bool  matchZoneFile(const QString &path);
+        bool  setLocalZone(const QString &zoneName);
 
         QString     mZoneinfoDir;       // path to zoneinfo directory
         QString     mZoneTab;           // path to zone.tab file
+        QByteArray  mSavedTZ;           // last value of TZ if it's used to set local zone
         KSystemTimeZoneSource *mSource;
         KTimeZones  mZones;             // time zones collection
+        QString     mLocalIdFile;       // file containing pointer to local time zone definition
         QString     mLocalZoneDataFile; // zoneinfo file containing local time zone definition
         KDirWatch  *mZonetabWatch;      // watch for zone.tab file changes
         KDirWatch  *mDirWatch;          // watch for time zone definition file changes