QFileSystemEngine: Fix renameat2() failures on non-local filesystems

The RENAME_NOREPLACE flag is supported for all Linux local filesystems,
since that can be easily checked by the VFS layer (it knows which files
exist and which ones don't). For non-local filesystems, the backend
needs support and that might need server-side support too. So we may get
EINVAL errors for those, in which case we fall back to link/unlink,
which in turn can fall back to rename().

EINVAL can also happen if we attempt to make a directory a
subdirectory of itself. In that case, we will attempt to link() it,
which will result in EPERM as we can't hardlink directories. Then we try
rename() again, which should result in the expected EINVAL.

Task-number: QTBUG-64008
Change-Id: Icaa86fc7b54d4b368c0efffd14f09ca23602dd2e
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Thiago Macieira 2017-10-24 13:48:15 -07:00
parent fb59760381
commit ea0e868c48

View File

@ -1261,7 +1261,8 @@ bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSy
// If we're using syscall(), check for ENOSYS;
// if renameat2 came from libc, we don't accept ENOSYS.
if (QT_CONFIG(renameat2) || errno != ENOSYS) {
// We can also get EINVAL for some non-local filesystems.
if ((QT_CONFIG(renameat2) || errno != ENOSYS) && errno != EINVAL) {
error = QSystemError(errno, QSystemError::StandardLibraryError);
return false;
}