QFSFileEngine: update d->fileEntry after a successful rename

Otherwise member methods such as size() could return incorrect info.

Add setFileEntry(QFileSystemEntry &&); to reuse a QFileSystemEntry if we
have already constructed one.

As a result of this, a QTemporaryFileEngine::setFileName() call has
become redundant and can be removed; the code it executed is already
taken care of:
- QFSFileEngine::close(): already called by QTFEngine::rename() a couple
  of lines above
- QFSFileEngine::setFileName(): QTFEngine::rename() calls
  QFSFileEngine::rename() which in turn updates the `fileEntry`

This commit is covered by tst_QTemporaryFile::rename(), i.e. if
QFSFileEngine::rename() didn't update the fileEntry, that test would
fail.

Change-Id: I312f35cf7fdf9b1a8cd0bce5e98ba7a48cf9426e
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Ahmad Samir 2024-04-17 02:08:48 +02:00
parent d691872b86
commit df6b74f461
4 changed files with 27 additions and 8 deletions

View File

@ -990,6 +990,17 @@ bool QFSFileEngine::remove()
return ret;
}
/*
An alternative to setFileName() when you have already constructed
a QFileSystemEntry.
*/
void QFSFileEngine::setFileEntry(QFileSystemEntry &&entry)
{
Q_D(QFSFileEngine);
d->init();
d->fileEntry = std::move(entry);
}
bool QFSFileEngine::rename_helper(const QString &newName, RenameMode mode)
{
Q_D(QFSFileEngine);
@ -997,10 +1008,14 @@ bool QFSFileEngine::rename_helper(const QString &newName, RenameMode mode)
auto func = mode == Rename ? QFileSystemEngine::renameFile
: QFileSystemEngine::renameOverwriteFile;
QSystemError error;
const bool ret = func(d->fileEntry, QFileSystemEntry(newName), error);
if (!ret)
auto newEntry = QFileSystemEntry(newName);
const bool ret = func(d->fileEntry, newEntry, error);
if (!ret) {
setError(QFile::RenameError, error.toString());
return ret;
return false;
}
setFileEntry(std::move(newEntry));
return true;
}
/*!

View File

@ -83,6 +83,7 @@ public:
bool setFileTime(const QDateTime &newDate, QFile::FileTime time) override;
QDateTime fileTime(QFile::FileTime time) const override;
void setFileName(const QString &file) override;
void setFileEntry(QFileSystemEntry &&entry);
int handle() const override;
#ifndef QT_NO_FILESYSTEMITERATOR
@ -160,7 +161,7 @@ public:
bool isSequentialFdFh() const;
#endif
#ifdef Q_OS_WIN
bool nativeRenameOverwrite(const QString &newName);
bool nativeRenameOverwrite(const QFileSystemEntry &newEntry);
#endif
uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);

View File

@ -396,11 +396,10 @@ bool QFSFileEnginePrivate::nativeIsSequential() const
|| (fileType == FILE_TYPE_PIPE);
}
bool QFSFileEnginePrivate::nativeRenameOverwrite(const QString &newName)
bool QFSFileEnginePrivate::nativeRenameOverwrite(const QFileSystemEntry &newEntry)
{
if (fileHandle == INVALID_HANDLE_VALUE)
return false;
QFileSystemEntry newEntry(newName, QFileSystemEntry::FromInternalPath());
const QString newFilePath = newEntry.nativeFilePath();
const size_t nameByteLength = newFilePath.length() * sizeof(wchar_t);
if (nameByteLength + sizeof(wchar_t) > std::numeric_limits<DWORD>::max())

View File

@ -393,8 +393,13 @@ bool QTemporaryFileEngine::renameOverwrite(const QString &newName)
}
#ifdef Q_OS_WIN
if (flags & Win32NonShared) {
bool ok = d_func()->nativeRenameOverwrite(newName);
QFileSystemEntry newEntry(newName, QFileSystemEntry::FromInternalPath());
bool ok = d_func()->nativeRenameOverwrite(newEntry);
QFSFileEngine::close();
if (ok) {
// Match what QFSFileEngine::renameOverwrite() does
setFileEntry(std::move(newEntry));
}
return ok;
}
#endif
@ -868,7 +873,6 @@ bool QTemporaryFile::rename(const QString &newName)
if (tef->rename(newName)) {
unsetError();
// engine was able to handle the new name so we just reset it
tef->setFileName(newName);
d->fileName = newName;
return true;
}