diff options
author | Alexandru Croitor <alexandru.croitor@qt.io> | 2018-05-17 18:39:20 +0200 |
---|---|---|
committer | Alexandru Croitor <alexandru.croitor@qt.io> | 2018-05-18 14:42:08 +0000 |
commit | 2aa3131bef6444a800f6e6259cecf44851eb0454 (patch) | |
tree | d1d6a254734ca2cea668999ca7f68cc5fa5b4079 | |
parent | 6acefea159067b2bb512a964f52cf905042a5ad1 (diff) |
Fix FileTime and FileInfo stat times implementation on macOS
This requires a couple of changes:
1) When targeting macOS 10.12+, clock_gettime is available and
can be used directly for FileTime::currentTime().
2) For lower versions, we partially implement the clock_gettime
CLOCK_REALTIME usecase, as it is done in macOS libc sources,
and explicitly use that version.
3) The file stat structure has slightly different field names
on macOS, so the accessed names were adjusted in
FileInfo::lastModified() and FileInfo::lastStatusChange().
Two more things are worth mentioning:
1) Both the stock and custom implementations of clock_gettime()
have 1000nsec = 1microsecond resolution, and not a 1ns one.
2) The stat.st_mtimespec field can store nanosecond values,
but in practice with HFS+ the date resolution is 1 second.
This is not true for APFS, which has a 1ns resolution.
Change-Id: I1ecdc6e9db7a9c1dc5f9a9a0859ec25a34165c4d
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r-- | src/lib/corelib/tools/fileinfo.cpp | 8 | ||||
-rw-r--r-- | src/lib/corelib/tools/filetime.cpp | 21 | ||||
-rw-r--r-- | src/lib/corelib/tools/filetime.h | 22 |
3 files changed, 43 insertions, 8 deletions
diff --git a/src/lib/corelib/tools/fileinfo.cpp b/src/lib/corelib/tools/fileinfo.cpp index c4ba0e5e0..a1571b954 100644 --- a/src/lib/corelib/tools/fileinfo.cpp +++ b/src/lib/corelib/tools/fileinfo.cpp @@ -371,7 +371,9 @@ bool FileInfo::exists() const FileTime FileInfo::lastModified() const { -#if HAS_CLOCK_GETTIME +#if APPLE_STAT_TIMESPEC + return m_stat.st_mtimespec; +#elif HAS_CLOCK_GETTIME return m_stat.st_mtim; #else return m_stat.st_mtime; @@ -380,7 +382,9 @@ FileTime FileInfo::lastModified() const FileTime FileInfo::lastStatusChange() const { -#if HAS_CLOCK_GETTIME +#if APPLE_STAT_TIMESPEC + return m_stat.st_ctimespec; +#elif HAS_CLOCK_GETTIME return m_stat.st_ctim; #else return m_stat.st_ctime; diff --git a/src/lib/corelib/tools/filetime.cpp b/src/lib/corelib/tools/filetime.cpp index 3f7148594..8b34ba81e 100644 --- a/src/lib/corelib/tools/filetime.cpp +++ b/src/lib/corelib/tools/filetime.cpp @@ -55,6 +55,20 @@ template<bool> struct CompileTimeAssert; template<> struct CompileTimeAssert<true> {}; #endif +#ifdef APPLE_CUSTOM_CLOCK_GETTIME +#include <sys/time.h> +// clk_id isn't used, only the CLOCK_REALTIME case is implemented. +int clock_gettime(int /*clk_id*/, struct timespec *t) +{ + struct timeval tv; + // Resolution of gettimeofday is 1000nsecs = 1 microsecond. + int ret = gettimeofday(&tv, NULL); + t->tv_sec = tv.tv_sec; + t->tv_nsec = tv.tv_usec * 1000; + return ret; +} +#endif + FileTime::FileTime() { #ifdef Q_OS_WIN @@ -124,6 +138,13 @@ FileTime FileTime::currentTime() FILETIME *const ft = reinterpret_cast<FILETIME *>(&result.m_fileTime); SystemTimeToFileTime(&st, ft); return result; +#elif defined APPLE_CUSTOM_CLOCK_GETTIME + InternalType t; + // Explicitly use our custom version, so that we don't get an additional unresolved symbol on a + // system that actually provides one, but isn't used due to the minimium deployment target + // being lower. + qbs::Internal::clock_gettime(CLOCK_REALTIME, &t); + return t; #elif HAS_CLOCK_GETTIME InternalType t; clock_gettime(CLOCK_REALTIME, &t); diff --git a/src/lib/corelib/tools/filetime.h b/src/lib/corelib/tools/filetime.h index d68c6ac4a..73e9d4544 100644 --- a/src/lib/corelib/tools/filetime.h +++ b/src/lib/corelib/tools/filetime.h @@ -45,17 +45,27 @@ #include <QtCore/qdatastream.h> #include <QtCore/qdebug.h> -#if defined(Q_OS_UNIX) +#if defined(Q_OS_UNIX) && !defined(__APPLE__) #include <time.h> -#define BUILD_HOST_HAS_CLOCK_GETTIME (_POSIX_C_SOURCE >= 199309L) +#define HAS_CLOCK_GETTIME (_POSIX_C_SOURCE >= 199309L) +#endif // Q_OS_UNIX + #ifdef __APPLE__ + #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 -#define HAS_CLOCK_GETTIME BUILD_HOST_HAS_CLOCK_GETTIME +// macOS 10.12+ ships clock_gettime. +#else +// We implement our own clock_gettime. +#define APPLE_CUSTOM_CLOCK_GETTIME 1 #endif // __MAC_OS_X_VERSION_MIN_REQUIRED -#else // __APPLE__ -#define HAS_CLOCK_GETTIME BUILD_HOST_HAS_CLOCK_GETTIME + +// Either way we have a clock_gettime in the end. +#define HAS_CLOCK_GETTIME 1 + +// Apple stat struct has slightly different names for time fields. +#define APPLE_STAT_TIMESPEC 1 + #endif // __APPLE__ -#endif // Q_OS_UNIX namespace qbs { namespace Internal { |