summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qfilesystemengine_unix.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2017-07-26 13:29:45 -0700
committerSimon Hausmann <simon.hausmann@qt.io>2017-08-22 06:56:16 +0000
commit974b3adf8a099ca95fc2eabfc434038ce73f62c8 (patch)
tree0e12ae29af2ec519ef6ef4f9c43cb873482cdbf0 /src/corelib/io/qfilesystemengine_unix.cpp
parent26094982f893b6f655d20cefb678b306be02e5ac (diff)
QFileSystemEngine::cloneFile: add support for fcopyfile(3) on macOS
For some reason, fcopyfile(3) works on directories, so we need to make we aren't operating in one. Change-Id: I81480fdb578d4d43b3fcfffd14d4f2f485348515 Reviewed-by: Jake Petroules <jake.petroules@qt.io>
Diffstat (limited to 'src/corelib/io/qfilesystemengine_unix.cpp')
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp17
1 files changed, 16 insertions, 1 deletions
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 3ba8275dfd..806926d674 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -71,6 +71,7 @@
# if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(101200, 100000, 100000, 30000)
# include <sys/clonefile.h>
# endif
+# include <copyfile.h>
// We cannot include <Foundation/Foundation.h> (it's an Objective-C header), but
// we need these declarations:
Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
@@ -1075,11 +1076,25 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
// static
bool QFileSystemEngine::cloneFile(int srcfd, int dstfd, const QFileSystemMetaData &knownData)
{
+ QT_STATBUF statBuffer;
+ if (knownData.hasFlags(QFileSystemMetaData::PosixStatFlags) &&
+ knownData.isFile()) {
+ statBuffer.st_size = knownData.size();
+ statBuffer.st_mode = S_IFREG;
+ } else if (knownData.hasFlags(QFileSystemMetaData::PosixStatFlags) &&
+ knownData.isDirectory()) {
+ return false; // fcopyfile(3) returns success on directories
+ } else if (QT_FSTAT(srcfd, &statBuffer) == -1 || S_ISDIR(statBuffer.st_mode)) {
+ return false;
+ }
+
#if defined(Q_OS_LINUX)
// try FICLONE (only works on regular files and only on certain fs)
return ::ioctl(dstfd, FICLONE, srcfd) == 0;
+#elif defined(Q_OS_DARWIN)
+ // try fcopyfile
+ return fcopyfile(srcfd, dstfd, nullptr, COPYFILE_DATA | COPYFILE_STAT) == 0;
#else
- Q_UNUSED(srcfd);
Q_UNUSED(dstfd);
return false;
#endif