aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2018-05-17 18:39:20 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2018-05-18 14:42:08 +0000
commit2aa3131bef6444a800f6e6259cecf44851eb0454 (patch)
treed1d6a254734ca2cea668999ca7f68cc5fa5b4079
parent6acefea159067b2bb512a964f52cf905042a5ad1 (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.cpp8
-rw-r--r--src/lib/corelib/tools/filetime.cpp21
-rw-r--r--src/lib/corelib/tools/filetime.h22
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 {