diff options
author | Mitch Curtis <mitch.curtis@digia.com> | 2013-03-19 16:45:25 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-03-23 14:42:45 +0100 |
commit | a3304489e870555f5d01d02c0252103db2288898 (patch) | |
tree | ebf8314f9fa8812e227b078d7e6b943860cf2448 | |
parent | 0450d8119028905823a393a5598eb350b8b5d377 (diff) |
Ensure QTemporaryFile can create files when an identical dir exists.
When QTemporaryFile attempts to create a new file in
createFileFromTemplate, it fails if the filename exists and is a
directory. Windows returns error code 5 (ERROR_ACCESS_DENIED) in this
case - rather than ERROR_FILE_EXISTS - which is not handled.
This patch handles ERROR_ACCESS_DENIED in addition to the already
handled ERROR_FILE_EXISTS, meaning that QTemporaryFile will continue
to look for unique names when a directory with the same name exists.
Task-number: QTBUG-30058
Change-Id: I42339887d7f5483e3dc6a03a9da15111c350da8f
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: David Faure <david.faure@kdab.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
-rw-r--r-- | src/corelib/io/qtemporaryfile.cpp | 9 | ||||
-rw-r--r-- | tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp | 35 |
2 files changed, 43 insertions, 1 deletions
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index d3a6e3c238..c2f421843c 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -160,7 +160,14 @@ static bool createFileFromTemplate(NativeFileHandle &file, return true; DWORD err = GetLastError(); - if (err != ERROR_FILE_EXISTS) { + if (err == ERROR_ACCESS_DENIED) { + DWORD attributes = GetFileAttributes((const wchar_t *)path.constData()); + if (attributes == INVALID_FILE_ATTRIBUTES) { + // Potential write error (read-only parent directory, etc.). + error = QSystemError(err, QSystemError::NativeError); + return false; + } // else file already exists as a directory. + } else if (err != ERROR_FILE_EXISTS) { error = QSystemError(err, QSystemError::NativeError); return false; } diff --git a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp index 28cf7a904a..6eb6f83d2a 100644 --- a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp +++ b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp @@ -92,6 +92,7 @@ private slots: void createNativeFile(); void QTBUG_4796_data(); void QTBUG_4796(); + void guaranteeUnique(); }; void tst_QTemporaryFile::initTestCase() @@ -782,5 +783,39 @@ void tst_QTemporaryFile::QTBUG_4796() cleaner.reset(); } +void tst_QTemporaryFile::guaranteeUnique() +{ + QDir dir(QDir::tempPath()); + QString takenFileName; + + // First pass. See which filename QTemporaryFile will try first. + { + // Fix the random seed. + qsrand(1135); + QTemporaryFile tmpFile("testFile1.XXXXXX"); + tmpFile.open(); + takenFileName = tmpFile.fileName(); + QVERIFY(QFile::exists(takenFileName)); + } + + QVERIFY(!QFile::exists(takenFileName)); + + // Create a directory with same name. + QVERIFY(dir.mkdir(takenFileName)); + + // Second pass, now we have blocked its first attempt with a directory. + { + // Fix the random seed. + qsrand(1135); + QTemporaryFile tmpFile("testFile1.XXXXXX"); + QVERIFY(tmpFile.open()); + QString uniqueFileName = tmpFile.fileName(); + QVERIFY(QFileInfo(uniqueFileName).isFile()); + QVERIFY(uniqueFileName != takenFileName); + } + + QVERIFY(dir.rmdir(takenFileName)); +} + QTEST_MAIN(tst_QTemporaryFile) #include "tst_qtemporaryfile.moc" |