From aa009e3dcc7ab47b27ec7e56a2b19fb835b04ee1 Mon Sep 17 00:00:00 2001 From: Janne Anttila Date: Wed, 20 Mar 2013 10:16:24 +0200 Subject: Fix QFSFileEngine::renameOverwrite for Windows Embedded Compact 7. Windows Embedded Compact 7 does not have MoveFileEx, simulate it with the available file I/O functions [1]. For more details please check the comments in source code. [1] http://msdn.microsoft.com/en-us/library/ee490588.aspx Change-Id: Ib0fb0ba84e2d070dee2f633af1b81bec132f4c17 Reviewed-by: Oswald Buddenhagen Reviewed-by: Andreas Holzammer Reviewed-by: Johannes Oikarinen --- src/corelib/io/qfsfileengine_win.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 41526d1eac..fca1a446ce 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -520,9 +520,35 @@ bool QFSFileEngine::rename(const QString &newName) bool QFSFileEngine::renameOverwrite(const QString &newName) { Q_D(QFSFileEngine); +#if defined(Q_OS_WINCE) + // Windows Embedded Compact 7 does not have MoveFileEx, simulate it with the following sequence: + // 1. DeleteAndRenameFile (Should work on RAM FS when both files exist) + // 2. DeleteFile/MoveFile (Should work on all file systems) + // + // DeleteFile/MoveFile fallback implementation violates atomicity, but it is more acceptable than + // alternative CopyFile/DeleteFile sequence for the following reasons: + // + // 1. DeleteFile/MoveFile is way faster than CopyFile/DeleteFile and thus more atomic. + // 2. Given the intended use case of this function in QSaveFile, DeleteFile/MoveFile sequence will + // delete the old content, but leave a file "filename.ext.XXXXXX" in the same directory if MoveFile fails. + // With CopyFile/DeleteFile sequence, it can happen that new data is partially copied to target file + // (because CopyFile is not atomic either), thus leaving *some* content to target file. + // This makes the need for application level recovery harder to detect than in DeleteFile/MoveFile + // sequence where target file simply does not exist. + // + bool ret = ::DeleteAndRenameFile((wchar_t*)QFileSystemEntry(newName).nativeFilePath().utf16(), + (wchar_t*)d->fileEntry.nativeFilePath().utf16()) != 0; + if (!ret) { + ret = ::DeleteFile((wchar_t*)d->fileEntry.nativeFilePath().utf16()) != 0; + if (ret) + ret = ::MoveFile((wchar_t*)d->fileEntry.nativeFilePath().utf16(), + (wchar_t*)QFileSystemEntry(newName).nativeFilePath().utf16()) != 0; + } +#else bool ret = ::MoveFileEx((wchar_t*)d->fileEntry.nativeFilePath().utf16(), (wchar_t*)QFileSystemEntry(newName).nativeFilePath().utf16(), MOVEFILE_REPLACE_EXISTING) != 0; +#endif if (!ret) setError(QFile::RenameError, QSystemError(::GetLastError(), QSystemError::NativeError).toString()); return ret; -- cgit v1.2.3