QFile::rename: avoid two stat(2)/CreateFile in a row
QFileSystemEngine::id() will stat(2)/CreateFile in order to get the ID of the file anyway, so we don't need to use QFile::exists() to check if the destination exists. Instead, rely on id() returning a null value to indicate error. On Windows, it's possible that the calls to either GetFileInformationByHandle or GetFileInformationByHandleEx might fail, but we ignore those. Change-Id: I1eba2b016de74620bfc8fffd14ccaebcbed64419 Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@qt.io>
This commit is contained in:
parent
353fb118c3
commit
fd95ef765a
@ -567,9 +567,11 @@ QFile::rename(const QString &newName)
|
|||||||
}
|
}
|
||||||
// If the file exists and it is a case-changing rename ("foo" -> "Foo"),
|
// If the file exists and it is a case-changing rename ("foo" -> "Foo"),
|
||||||
// compare Ids to make sure it really is a different file.
|
// compare Ids to make sure it really is a different file.
|
||||||
if (QFile::exists(newName)) {
|
// Note: this does not take file engines into account.
|
||||||
if (d->fileName.compare(newName, Qt::CaseInsensitive)
|
QByteArray targetId = QFileSystemEngine::id(QFileSystemEntry(newName));
|
||||||
|| QFileSystemEngine::id(QFileSystemEntry(d->fileName)) != QFileSystemEngine::id(QFileSystemEntry(newName))) {
|
if (!targetId.isNull()) {
|
||||||
|
QByteArray fileId = QFileSystemEngine::id(QFileSystemEntry(d->fileName));
|
||||||
|
if (fileId != targetId || d->fileName.compare(newName, Qt::CaseInsensitive)) {
|
||||||
// ### Race condition. If a file is moved in after this, it /will/ be
|
// ### Race condition. If a file is moved in after this, it /will/ be
|
||||||
// overwritten. On Unix, the proper solution is to use hardlinks:
|
// overwritten. On Unix, the proper solution is to use hardlinks:
|
||||||
// return ::link(old, new) && ::remove(old);
|
// return ::link(old, new) && ::remove(old);
|
||||||
|
@ -338,7 +338,8 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
|
|||||||
{
|
{
|
||||||
QT_STATBUF statResult;
|
QT_STATBUF statResult;
|
||||||
if (QT_STAT(entry.nativeFilePath().constData(), &statResult)) {
|
if (QT_STAT(entry.nativeFilePath().constData(), &statResult)) {
|
||||||
qErrnoWarning("stat() failed for '%s'", entry.nativeFilePath().constData());
|
if (errno != ENOENT)
|
||||||
|
qErrnoWarning("stat() failed for '%s'", entry.nativeFilePath().constData());
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
}
|
}
|
||||||
QByteArray result = QByteArray::number(quint64(statResult.st_dev), 16);
|
QByteArray result = QByteArray::number(quint64(statResult.st_dev), 16);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user