forked from qt-creator/qt-creator
Utils: Add env to disable special win32 code
Change-Id: I450152a4d049461b98416fa61a9a1e7082625ecc Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
@@ -129,86 +129,90 @@ bool SaveFile::commit()
|
|||||||
|
|
||||||
FilePath finalFileName = m_finalFilePath.resolveSymlinks();
|
FilePath finalFileName = m_finalFilePath.resolveSymlinks();
|
||||||
|
|
||||||
if constexpr (HostOsInfo::isWindowsHost() && !m_finalFilePath.needsDevice()) {
|
if constexpr (HostOsInfo::isWindowsHost()) {
|
||||||
// Release the file lock
|
static const bool disableWinSpecialCode = !qEnvironmentVariableIsEmpty(
|
||||||
m_tempFile.reset();
|
"QTC_DISABLE_SPECIAL_WIN_SAVEFILE");
|
||||||
bool result = ReplaceFile(
|
if (!m_finalFilePath.needsDevice() && !disableWinSpecialCode) {
|
||||||
finalFileName.nativePath().toStdWString().data(),
|
// Release the file lock
|
||||||
fileName().toStdWString().data(),
|
m_tempFile.reset();
|
||||||
nullptr,
|
bool result = ReplaceFile(
|
||||||
REPLACEFILE_IGNORE_MERGE_ERRORS,
|
finalFileName.nativePath().toStdWString().data(),
|
||||||
nullptr,
|
fileName().toStdWString().data(),
|
||||||
nullptr);
|
nullptr,
|
||||||
if (!result) {
|
REPLACEFILE_IGNORE_MERGE_ERRORS,
|
||||||
DWORD replaceErrorCode = GetLastError();
|
nullptr,
|
||||||
QString errorStr;
|
nullptr);
|
||||||
if (!finalFileName.exists()) {
|
if (!result) {
|
||||||
// Replace failed because finalFileName does not exist, try rename.
|
DWORD replaceErrorCode = GetLastError();
|
||||||
if (!(result = rename(finalFileName.toFSPathString())))
|
QString errorStr;
|
||||||
errorStr = errorString();
|
if (!finalFileName.exists()) {
|
||||||
} else {
|
// Replace failed because finalFileName does not exist, try rename.
|
||||||
if (replaceErrorCode == ERROR_UNABLE_TO_REMOVE_REPLACED) {
|
if (!(result = rename(finalFileName.toFSPathString())))
|
||||||
// If we do not get the rights to remove the original final file we still might try
|
errorStr = errorString();
|
||||||
// to replace the file contents
|
} else {
|
||||||
result = MoveFileEx(
|
if (replaceErrorCode == ERROR_UNABLE_TO_REMOVE_REPLACED) {
|
||||||
fileName().toStdWString().data(),
|
// If we do not get the rights to remove the original final file we still might try
|
||||||
finalFileName.nativePath().toStdWString().data(),
|
// to replace the file contents
|
||||||
MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);
|
result = MoveFileEx(
|
||||||
if (!result)
|
fileName().toStdWString().data(),
|
||||||
replaceErrorCode = GetLastError();
|
finalFileName.nativePath().toStdWString().data(),
|
||||||
|
MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING
|
||||||
|
| MOVEFILE_WRITE_THROUGH);
|
||||||
|
if (!result)
|
||||||
|
replaceErrorCode = GetLastError();
|
||||||
|
}
|
||||||
|
if (!result) {
|
||||||
|
wchar_t messageBuffer[256];
|
||||||
|
FormatMessageW(
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
nullptr,
|
||||||
|
replaceErrorCode,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
messageBuffer,
|
||||||
|
sizeof(messageBuffer),
|
||||||
|
nullptr);
|
||||||
|
errorStr = QString::fromWCharArray(messageBuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!result) {
|
if (!result) {
|
||||||
wchar_t messageBuffer[256];
|
remove();
|
||||||
FormatMessageW(
|
setErrorString(errorStr);
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
nullptr,
|
|
||||||
replaceErrorCode,
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
||||||
messageBuffer,
|
|
||||||
sizeof(messageBuffer),
|
|
||||||
nullptr);
|
|
||||||
errorStr = QString::fromWCharArray(messageBuffer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!result) {
|
|
||||||
remove();
|
return result;
|
||||||
setErrorString(errorStr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
const QString backupName = finalFileName.toFSPathString() + '~';
|
|
||||||
|
|
||||||
// Back up current file.
|
|
||||||
// If it's opened by another application, the lock follows the move.
|
|
||||||
if (finalFileName.exists()) {
|
|
||||||
// Kill old backup. Might be useful if creator crashed before removing backup.
|
|
||||||
QFile::remove(backupName);
|
|
||||||
QFile finalFile(finalFileName.toFSPathString());
|
|
||||||
if (!finalFile.rename(backupName)) {
|
|
||||||
m_tempFile->filePath().removeFile();
|
|
||||||
setErrorString(finalFile.errorString());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
expected_str<void> renameResult = m_tempFile->filePath().renameFile(finalFileName);
|
|
||||||
if (!renameResult) {
|
|
||||||
// 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
|
|
||||||
// return false while keeping the error string from last rename call.
|
|
||||||
m_tempFile->filePath().removeFile();
|
|
||||||
setErrorString(renameResult.error());
|
|
||||||
QFile::rename(
|
|
||||||
backupName, finalFileName.toFSPathString()); // rollback to backup if possible ...
|
|
||||||
return false; // ... or keep the backup copy at least
|
|
||||||
}
|
|
||||||
|
|
||||||
QFile::remove(backupName);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString backupName = finalFileName.toFSPathString() + '~';
|
||||||
|
|
||||||
|
// Back up current file.
|
||||||
|
// If it's opened by another application, the lock follows the move.
|
||||||
|
if (finalFileName.exists()) {
|
||||||
|
// Kill old backup. Might be useful if creator crashed before removing backup.
|
||||||
|
QFile::remove(backupName);
|
||||||
|
QFile finalFile(finalFileName.toFSPathString());
|
||||||
|
if (!finalFile.rename(backupName)) {
|
||||||
|
m_tempFile->filePath().removeFile();
|
||||||
|
setErrorString(finalFile.errorString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expected_str<void> renameResult = m_tempFile->filePath().renameFile(finalFileName);
|
||||||
|
if (!renameResult) {
|
||||||
|
// 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
|
||||||
|
// return false while keeping the error string from last rename call.
|
||||||
|
m_tempFile->filePath().removeFile();
|
||||||
|
setErrorString(renameResult.error());
|
||||||
|
QFile::rename(backupName, finalFileName.toFSPathString()); // rollback to backup if possible ...
|
||||||
|
return false; // ... or keep the backup copy at least
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile::remove(backupName);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveFile::initializeUmask()
|
void SaveFile::initializeUmask()
|
||||||
|
Reference in New Issue
Block a user