forked from qt-creator/qt-creator
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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user