Utils: take control over QTemporaryFile file lock

When we derive from QTemporaryFile we can't unlock file
to be used by outer functions.
With this change lock is managed by m_tempFile variable and
can be released by reseting m_tempFile.

Change-Id: I41339410471c69d1e73df49f04bc2d5c2036a064
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Ivan Donchevskii
2017-12-15 09:20:48 +01:00
parent 0dafe5cb8c
commit 010fb41700
2 changed files with 23 additions and 13 deletions

View File

@@ -50,7 +50,7 @@ SaveFile::~SaveFile()
bool SaveFile::open(OpenMode flags) bool SaveFile::open(OpenMode flags)
{ {
QTC_ASSERT(!m_finalFileName.isEmpty() && fileName().isEmpty(), return false); QTC_ASSERT(!m_finalFileName.isEmpty(), return false);
QFile ofi(m_finalFileName); QFile ofi(m_finalFileName);
// Check whether the existing file is writable // Check whether the existing file is writable
@@ -59,9 +59,12 @@ bool SaveFile::open(OpenMode flags)
return false; return false;
} }
setAutoRemove(false); m_tempFile = std::make_unique<QTemporaryFile>(m_finalFileName);
setFileTemplate(m_finalFileName); m_tempFile->setAutoRemove(false);
if (!QTemporaryFile::open(flags)) m_tempFile->open();
setFileName(m_tempFile->fileName());
if (!QFile::open(flags))
return false; return false;
m_finalized = false; // needs clean up in the end m_finalized = false; // needs clean up in the end
@@ -84,17 +87,20 @@ bool SaveFile::open(OpenMode flags)
void SaveFile::rollback() void SaveFile::rollback()
{ {
remove(); close();
if (m_tempFile)
m_tempFile->remove();
m_finalized = true; m_finalized = true;
} }
bool SaveFile::commit() bool SaveFile::commit()
{ {
QTC_ASSERT(!m_finalized, return false); QTC_ASSERT(!m_finalized && m_tempFile, return false;);
m_finalized = true; m_finalized = true;
if (!flush()) { if (!flush()) {
remove(); close();
m_tempFile->remove();
return false; return false;
} }
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@@ -105,8 +111,9 @@ bool SaveFile::commit()
fsync(handle()); fsync(handle());
#endif #endif
close(); close();
m_tempFile->close();
if (error() != NoError) { if (error() != NoError) {
remove(); m_tempFile->remove();
return false; return false;
} }
@@ -121,19 +128,19 @@ bool SaveFile::commit()
QFile::remove(backupName); QFile::remove(backupName);
QFile finalFile(finalFileName); QFile finalFile(finalFileName);
if (!finalFile.rename(backupName)) { if (!finalFile.rename(backupName)) {
remove(); m_tempFile->remove();
setErrorString(finalFile.errorString()); setErrorString(finalFile.errorString());
return false; return false;
} }
} }
bool result = true; bool result = true;
if (!rename(finalFileName)) { if (!m_tempFile->rename(finalFileName)) {
// The case when someone else was able to create finalFileName after we've renamed it. // The case when someone else was able to create finalFileName after we've renamed it.
// Higher level call may try to save this file again but here we do nothing and // Higher level call may try to save this file again but here we do nothing and
// return false while keeping the error string from last rename call. // return false while keeping the error string from last rename call.
const QString &renameError = errorString(); const QString &renameError = m_tempFile->errorString();
remove(); m_tempFile->remove();
setErrorString(renameError); setErrorString(renameError);
result = false; result = false;
} }

View File

@@ -29,9 +29,11 @@
#include <QTemporaryFile> #include <QTemporaryFile>
#include <memory>
namespace Utils { namespace Utils {
class QTCREATOR_UTILS_EXPORT SaveFile : public QTemporaryFile class QTCREATOR_UTILS_EXPORT SaveFile : public QFile
{ {
Q_OBJECT Q_OBJECT
@@ -48,6 +50,7 @@ public:
private: private:
const QString m_finalFileName; const QString m_finalFileName;
std::unique_ptr<QTemporaryFile> m_tempFile;
bool m_finalized; bool m_finalized;
static QFile::Permissions m_umask; static QFile::Permissions m_umask;
}; };