| 95 | } |
| 96 | |
| 97 | bool SaveFile::commit() |
| 98 | { |
| 99 | QTC_ASSERT(!m_finalized && m_tempFile, return false;); |
| 100 | m_finalized = true; |
| 101 | |
| 102 | if (!flush()) { |
| 103 | close(); |
| 104 | m_tempFile->remove(); |
| 105 | return false; |
| 106 | } |
| 107 | #ifdef Q_OS_WIN |
| 108 | FlushFileBuffers(reinterpret_cast<HANDLE>(_get_osfhandle(handle()))); |
| 109 | #elif _POSIX_SYNCHRONIZED_IO > 0 |
| 110 | fdatasync(handle()); |
| 111 | #else |
| 112 | fsync(handle()); |
| 113 | #endif |
| 114 | close(); |
| 115 | m_tempFile->close(); |
| 116 | if (error() != NoError) { |
| 117 | m_tempFile->remove(); |
| 118 | return false; |
| 119 | } |
| 120 | |
| 121 | QString finalFileName |
| 122 | = FileUtils::resolveSymlinks(FileName::fromString(m_finalFileName)).toString(); |
| 123 | |
| 124 | #ifdef Q_OS_WIN |
| 125 | // Release the file lock |
| 126 | m_tempFile.reset(); |
| 127 | bool result = ReplaceFile(finalFileName.toStdWString().data(), |
| 128 | fileName().toStdWString().data(), |
| 129 | nullptr, REPLACEFILE_IGNORE_MERGE_ERRORS, nullptr, nullptr); |
| 130 | if (!result) { |
| 131 | DWORD replaceErrorCode = GetLastError(); |
| 132 | QString errorStr; |
| 133 | if (!QFile::exists(finalFileName)) { |
| 134 | // Replace failed because finalFileName does not exist, try rename. |
| 135 | if (!(result = rename(finalFileName))) |
| 136 | errorStr = errorString(); |
| 137 | } else { |
| 138 | if (replaceErrorCode == ERROR_UNABLE_TO_REMOVE_REPLACED) { |
| 139 | // If we do not get the rights to remove the original final file we still might try |
| 140 | // to replace the file contents |
| 141 | result = MoveFileEx(fileName().toStdWString().data(), |
| 142 | finalFileName.toStdWString().data(), |
| 143 | MOVEFILE_COPY_ALLOWED |
| 144 | | MOVEFILE_REPLACE_EXISTING |
| 145 | | MOVEFILE_WRITE_THROUGH); |
| 146 | if (!result) |
| 147 | replaceErrorCode = GetLastError(); |
| 148 | } |
| 149 | if (!result) { |
| 150 | wchar_t messageBuffer[256]; |
| 151 | FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 152 | nullptr, replaceErrorCode, |
| 153 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
| 154 | messageBuffer, sizeof(messageBuffer), nullptr); |
no test coverage detected