use renameat2() if available to fix race condition in QFile::rename()

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2021-08-13 23:48:06 +03:00
parent 69d2ac47bf
commit 2269f8f9b0
3 changed files with 8 additions and 0 deletions

View file

@ -461,6 +461,7 @@ katie_check_function(pipe2 "unistd.h")
katie_check_function(accept4 "sys/socket.h")
katie_check_function(paccept "sys/socket.h")
katie_check_function(getdomainname "unistd.h")
katie_check_function(renameat2 "stdio.h")
katie_check_struct(tm tm_gmtoff "time.h")
katie_check_struct(tm tm_zone "time.h")
katie_check_struct(sockaddr_ll sll_addr "netpacket/packet.h")

View file

@ -566,6 +566,7 @@ QFile::rename(const QString &newName)
qWarning("QFile::rename: Empty or null file name");
return false;
}
#ifndef QT_HAVE_RENAMEAT2
if (QFile(newName).exists()) {
// ### Race condition. If a file is moved in after this, it /will/ be
// overwritten. On Unix, the proper solution is to use hardlinks:
@ -573,6 +574,7 @@ QFile::rename(const QString &newName)
d->setError(QFile::RenameError, tr("Destination file exists"));
return false;
}
#endif
unsetError();
close();
if(error() == QFile::NoError) {

View file

@ -387,8 +387,13 @@ bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSy
{
const QByteArray spath = source.nativeFilePath();
const QByteArray tpath = target.nativeFilePath();
#ifdef QT_HAVE_RENAMEAT2
if (::renameat2(AT_FDCWD, spath.constData(), AT_FDCWD, tpath.constData(), RENAME_NOREPLACE) == 0)
return true;
#else
if (::rename(spath.constData(), tpath.constData()) == 0)
return true;
#endif
*error = errno;
return false;
}