Set the state of QTemporaryFileEngine properly prior to reopening

QTemporaryFileEngine does not store the pattern, so it needs to get it
again from QTemporaryFilePrivate prior to reopening the file. It's
possible to lose the pattern when remove() is called on the object.

Task-number: QTBUG-46156
Change-Id: I66a35ce5f88941f29aa6ffff13dfc7f83d4fa3a2
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
Reviewed-by: David Faure <david.faure@kdab.com>
This commit is contained in:
Thiago Macieira 2015-05-19 17:51:15 -07:00
parent ca60311a60
commit 02418d1aaa
4 changed files with 29 additions and 14 deletions

View File

@ -215,7 +215,8 @@ bool QSaveFile::open(OpenMode mode)
d->finalFileName = existingFile.filePath();
}
d->fileEngine = new QTemporaryFileEngine(d->finalFileName, 0666);
d->fileEngine = new QTemporaryFileEngine;
static_cast<QTemporaryFileEngine *>(d->fileEngine)->initialize(d->finalFileName, 0666);
// Same as in QFile: QIODevice provides the buffering, so there's no need to request it from the file engine.
if (!d->fileEngine->open(mode | QIODevice::Unbuffered)) {
QFileDevice::FileError err = d->fileEngine->error();

View File

@ -409,14 +409,24 @@ QTemporaryFilePrivate::~QTemporaryFilePrivate()
QAbstractFileEngine *QTemporaryFilePrivate::engine() const
{
if (!fileEngine) {
if (fileName.isEmpty())
fileEngine = new QTemporaryFileEngine(templateName, 0600);
else
fileEngine = new QTemporaryFileEngine(fileName, 0600, false);
fileEngine = new QTemporaryFileEngine;
resetFileEngine();
}
return fileEngine;
}
void QTemporaryFilePrivate::resetFileEngine() const
{
if (!fileEngine)
return;
QTemporaryFileEngine *tef = static_cast<QTemporaryFileEngine *>(fileEngine);
if (fileName.isEmpty())
tef->initialize(templateName, 0600);
else
tef->initialize(fileName, 0600, false);
}
QString QTemporaryFilePrivate::defaultTemplateName()
{
QString baseName;
@ -769,6 +779,13 @@ bool QTemporaryFile::open(OpenMode flags)
}
}
// reset the engine state so it creates a new, unique file name from the template;
// equivalent to:
// delete d->fileEngine;
// d->fileEngine = 0;
// d->engine();
d->resetFileEngine();
if (QFile::open(flags)) {
d->fileName = d->fileEngine->fileName(QAbstractFileEngine::DefaultName);
return true;

View File

@ -64,6 +64,7 @@ protected:
~QTemporaryFilePrivate();
QAbstractFileEngine *engine() const;
void resetFileEngine() const;
bool autoRemove;
QString templateName;
@ -77,22 +78,17 @@ class QTemporaryFileEngine : public QFSFileEngine
{
Q_DECLARE_PRIVATE(QFSFileEngine)
public:
QTemporaryFileEngine(const QString &file,
quint32 fileMode,
bool fileIsTemplate = true) :
QFSFileEngine(),
fileMode(fileMode),
filePathIsTemplate(fileIsTemplate),
filePathWasTemplate(fileIsTemplate)
void initialize(const QString &file, quint32 mode, bool nameIsTemplate = true)
{
Q_D(QFSFileEngine);
Q_ASSERT(!isReallyOpen());
fileMode = mode;
filePathIsTemplate = filePathWasTemplate = nameIsTemplate;
d->fileEntry = QFileSystemEntry(file);
if (!filePathIsTemplate)
QFSFileEngine::setFileName(file);
}
~QTemporaryFileEngine();
bool isReallyOpen();

View File

@ -353,6 +353,7 @@ void tst_QTemporaryFile::removeAndReOpen()
QVERIFY(!QFile::exists(fileName));
QVERIFY(file.open());
QCOMPARE(QFileInfo(file.fileName()).path(), QFileInfo(fileName).path());
fileName = file.fileName();
QVERIFY(QFile::exists(fileName));
}