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 <eskil.abrahamsen-blomfeldt@qt.io>
This commit is contained in:
Thiago Macieira 2017-12-01 19:38:20 -08:00
parent 2c6c044500
commit 138d34b9c8

View File

@ -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) {