diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2017-03-06 17:28:14 +0100 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2017-03-08 11:47:56 +0000 |
commit | e760693b84bc88eba78b1d3e08899ad6b5c80ac5 (patch) | |
tree | 0e96f53585778d0ba9b852023acc9f1e59f1b118 /src/lib/corelib | |
parent | ad96a388f7e31cf7b8260de7631319e5c76613ec (diff) |
Handle sub-second timestamps correctly on Unix
There are file systems that support a more fine-grained resolution than
the traditional second.
[ChangeLog] Sub-second timestamp resolutions are now supported on Unix
systems.
Task-number: QBS-1110
Change-Id: I7c819882497511462d868584eb059ac392b155d9
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'src/lib/corelib')
-rw-r--r-- | src/lib/corelib/jsextensions/file.cpp | 2 | ||||
-rw-r--r-- | src/lib/corelib/tools/fileinfo.cpp | 4 | ||||
-rw-r--r-- | src/lib/corelib/tools/filetime.cpp | 72 | ||||
-rw-r--r-- | src/lib/corelib/tools/filetime.h | 58 | ||||
-rw-r--r-- | src/lib/corelib/tools/persistence.cpp | 2 |
5 files changed, 78 insertions, 60 deletions
diff --git a/src/lib/corelib/jsextensions/file.cpp b/src/lib/corelib/jsextensions/file.cpp index bb60edce3..4368c4f1b 100644 --- a/src/lib/corelib/jsextensions/file.cpp +++ b/src/lib/corelib/jsextensions/file.cpp @@ -213,7 +213,7 @@ QScriptValue File::js_lastModified(QScriptContext *context, QScriptEngine *engin const FileTime timestamp = FileInfo(filePath).lastModified(); ScriptEngine * const se = static_cast<ScriptEngine *>(engine); se->addFileLastModifiedResult(filePath, timestamp); - return static_cast<qsreal>(timestamp.m_fileTime); + return timestamp.asDouble(); } QScriptValue File::js_makePath(QScriptContext *context, QScriptEngine *engine) diff --git a/src/lib/corelib/tools/fileinfo.cpp b/src/lib/corelib/tools/fileinfo.cpp index 61a0ab8ed..94536f6e3 100644 --- a/src/lib/corelib/tools/fileinfo.cpp +++ b/src/lib/corelib/tools/fileinfo.cpp @@ -341,12 +341,12 @@ bool FileInfo::exists() const FileTime FileInfo::lastModified() const { - return m_stat.st_mtime; + return m_stat.st_mtim; } FileTime FileInfo::lastStatusChange() const { - return m_stat.st_ctime; + return m_stat.st_ctim; } bool FileInfo::isDir() const diff --git a/src/lib/corelib/tools/filetime.cpp b/src/lib/corelib/tools/filetime.cpp index ac917260e..794548f27 100644 --- a/src/lib/corelib/tools/filetime.cpp +++ b/src/lib/corelib/tools/filetime.cpp @@ -45,7 +45,6 @@ #include <QtCore/qt_windows.h> #else #include <QtCore/qdatetime.h> -#include <time.h> #endif namespace qbs { @@ -57,33 +56,55 @@ template<> struct CompileTimeAssert<true> {}; #endif FileTime::FileTime() - : m_fileTime(0) { #ifdef Q_OS_WIN static CompileTimeAssert<sizeof(FileTime::InternalType) == sizeof(FILETIME)> internal_type_has_wrong_size; Q_UNUSED(internal_type_has_wrong_size); + m_fileTime = 0; +#else + m_fileTime = {0, 0}; #endif } -bool FileTime::operator < (const FileTime &rhs) const +FileTime::FileTime(const FileTime::InternalType &ft) : m_fileTime(ft) +{ +#ifndef Q_OS_WIN + if (m_fileTime.tv_sec == 0) + m_fileTime.tv_nsec = 0; // stat() sets only the first member to 0 for non-existing files. +#endif +} + +int FileTime::compare(const FileTime &other) const { #ifdef Q_OS_WIN const FILETIME *const t1 = reinterpret_cast<const FILETIME *>(&m_fileTime); - const FILETIME *const t2 = reinterpret_cast<const FILETIME *>(&rhs.m_fileTime); - return CompareFileTime(t1, t2) < 0; + const FILETIME *const t2 = reinterpret_cast<const FILETIME *>(&other.m_fileTime); + return CompareFileTime(t1, t2); #else - return m_fileTime < rhs.m_fileTime; + if (m_fileTime.tv_sec < other.m_fileTime.tv_sec) + return -1; + if (m_fileTime.tv_sec > other.m_fileTime.tv_sec) + return 1; + if (m_fileTime.tv_nsec < other.m_fileTime.tv_nsec) + return -1; + if (m_fileTime.tv_nsec > other.m_fileTime.tv_nsec) + return 1; + return 0; #endif } void FileTime::clear() { +#ifdef Q_OS_WIN m_fileTime = 0; +#else + m_fileTime = { 0, 0 }; +#endif } bool FileTime::isValid() const { - return m_fileTime != 0; + return *this != FileTime(); } FileTime FileTime::currentTime() @@ -96,7 +117,9 @@ FileTime FileTime::currentTime() SystemTimeToFileTime(&st, ft); return result; #else - return time(0); + InternalType t; + clock_gettime(CLOCK_REALTIME, &t); + return t; #endif } @@ -118,7 +141,16 @@ FileTime FileTime::oldestTime() SystemTimeToFileTime(&st, ft); return result; #else - return 1; + return FileTime({1, 0}); +#endif +} + +double FileTime::asDouble() const +{ +#ifdef Q_OS_WIN + return static_cast<double>(m_fileTime); +#else + return static_cast<double>(m_fileTime.tv_sec); #endif } @@ -135,10 +167,30 @@ QString FileTime::toString() const return result; #else QDateTime dt; - dt.setTime_t(m_fileTime); + dt.setMSecsSinceEpoch(m_fileTime.tv_sec * 1000 + m_fileTime.tv_nsec / 1000000); return dt.toString(); #endif } +void qbs::Internal::FileTime::store(PersistentPool &pool) const +{ +#ifdef Q_OS_WIN + pool.store(static_cast<quint64>(m_fileTime)); +#else + pool.store(static_cast<qint64>(m_fileTime.tv_sec)); + pool.store(static_cast<qint64>(m_fileTime.tv_nsec)); +#endif +} + +void qbs::Internal::FileTime::load(PersistentPool &pool) +{ +#ifdef Q_OS_WIN + m_fileTime = pool.load<quint64>(); +#else + m_fileTime.tv_sec = pool.load<qint64>(); + m_fileTime.tv_nsec = pool.load<qint64>(); +#endif +} + } // namespace Internal } // namespace qbs diff --git a/src/lib/corelib/tools/filetime.h b/src/lib/corelib/tools/filetime.h index 1c8884d9d..83e09cf68 100644 --- a/src/lib/corelib/tools/filetime.h +++ b/src/lib/corelib/tools/filetime.h @@ -56,7 +56,7 @@ class FileTime { public: #if defined(Q_OS_UNIX) - typedef time_t InternalType; + typedef timespec InternalType; #elif defined(Q_OS_WIN) typedef quint64 InternalType; #else @@ -64,19 +64,18 @@ public: #endif FileTime(); - FileTime(const InternalType &ft) - : m_fileTime(ft) - { } + FileTime(const InternalType &ft); void store(PersistentPool &pool) const; void load(PersistentPool &pool); - bool operator < (const FileTime &rhs) const; - bool operator > (const FileTime &rhs) const; - bool operator <= (const FileTime &rhs) const; - bool operator >= (const FileTime &rhs) const; - bool operator == (const FileTime &rhs) const; - bool operator != (const FileTime &rhs) const; + bool operator<(const FileTime &rhs) const { return compare(rhs) < 0; } + bool operator>(const FileTime &rhs) const { return compare(rhs) > 0; } + bool operator<=(const FileTime &rhs) const { return !operator>(rhs); } + bool operator>=(const FileTime &rhs) const { return !operator<(rhs); } + bool operator==(const FileTime &rhs) const { return compare(rhs) == 0; } + bool operator!= (const FileTime &rhs) const { return !operator==(rhs); } + int compare(const FileTime &other) const; void clear(); bool isValid() const; @@ -85,45 +84,12 @@ public: static FileTime currentTime(); static FileTime oldestTime(); - friend class FileInfo; + double asDouble() const; + +private: InternalType m_fileTime; }; -inline void FileTime::store(PersistentPool &pool) const -{ - pool.store(static_cast<quint64>(m_fileTime)); -} - -inline void FileTime::load(PersistentPool &pool) -{ - m_fileTime = pool.load<quint64>(); -} - -inline bool FileTime::operator > (const FileTime &rhs) const -{ - return rhs < *this; -} - -inline bool FileTime::operator <= (const FileTime &rhs) const -{ - return operator < (rhs) || operator == (rhs); -} - -inline bool FileTime::operator >= (const FileTime &rhs) const -{ - return operator > (rhs) || operator == (rhs); -} - -inline bool FileTime::operator == (const FileTime &rhs) const -{ - return m_fileTime == rhs.m_fileTime; -} - -inline bool FileTime::operator != (const FileTime &rhs) const -{ - return !operator==(rhs); -} - } // namespace Internal } // namespace qbs diff --git a/src/lib/corelib/tools/persistence.cpp b/src/lib/corelib/tools/persistence.cpp index 98ac177e9..5e92fa493 100644 --- a/src/lib/corelib/tools/persistence.cpp +++ b/src/lib/corelib/tools/persistence.cpp @@ -50,7 +50,7 @@ namespace qbs { namespace Internal { -static const char QBS_PERSISTENCE_MAGIC[] = "QBSPERSISTENCE-97"; +static const char QBS_PERSISTENCE_MAGIC[] = "QBSPERSISTENCE-98"; PersistentPool::PersistentPool(Logger &logger) : m_logger(logger) { |