From 138d34b9c8aa368dd252d0c46393816c7e372837 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 1 Dec 2017 19:38:20 -0800 Subject: QFileSystemEngine: Work around Android bug in rejecting hardlinks Android Marshmellow intentionally forbids use of hard links. See https://code.google.com/archive/p/android-developer-preview/issues/3150 However, instead of using EPERM or another error code that indicates the hard linking operation itself has a problem but there are no other problems, Android developers stupidly chose to use EACCES, an errno code that only indicates permission problems. In any case, since the call will never succeed, we shouldn't even try. Task-number: QTBUG-64103 Change-Id: I9e2892cb6c374e93bcb7fffd14fc5d1082bd60a3 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/io/qfilesystemengine_unix.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index d77cdc123c..75d0c60288 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -104,6 +104,16 @@ static int statx(int dirfd, const char *pathname, int flag, unsigned mask, struc QT_BEGIN_NAMESPACE +enum { +#ifdef Q_OS_ANDROID + // On Android, the link(2) system call has been observed to always fail + // with EACCES, regardless of whether there are permission problems or not. + SupportsHardlinking = false +#else + SupportsHardlinking = true +#endif +}; + #define emptyFileEntryWarning() emptyFileEntryWarning_(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC) static void emptyFileEntryWarning_(const char *file, int line, const char *function) { @@ -1278,7 +1288,7 @@ bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSy } #endif - if (::link(srcPath, tgtPath) == 0) { + if (SupportsHardlinking && ::link(srcPath, tgtPath) == 0) { if (::unlink(srcPath) == 0) return true; @@ -1292,6 +1302,11 @@ bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSy error = QSystemError(savedErrno, QSystemError::StandardLibraryError); return false; + } else if (!SupportsHardlinking) { + // man 2 link on Linux has: + // EPERM The filesystem containing oldpath and newpath does not + // support the creation of hard links. + errno = EPERM; } switch (errno) { -- cgit v1.2.3