mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-01-18 06:25:37 +00:00
ByteStream: Fix atomic updates on external storage with UWP
This commit is contained in:
parent
e8c16056b6
commit
3be6270b2d
|
@ -262,9 +262,9 @@ protected:
|
|||
class AtomicUpdatedFileByteStream : public FileByteStream
|
||||
{
|
||||
public:
|
||||
AtomicUpdatedFileByteStream(FILE* pFile, const char* originalFileName, const char* temporaryFileName)
|
||||
: FileByteStream(pFile), m_committed(false), m_discarded(false), m_originalFileName(originalFileName),
|
||||
m_temporaryFileName(temporaryFileName)
|
||||
AtomicUpdatedFileByteStream(FILE* pFile, std::string originalFileName, std::string temporaryFileName)
|
||||
: FileByteStream(pFile), m_committed(false), m_discarded(false), m_originalFileName(std::move(originalFileName)),
|
||||
m_temporaryFileName(std::move(temporaryFileName))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -272,7 +272,7 @@ public:
|
|||
{
|
||||
if (m_discarded)
|
||||
{
|
||||
#if _WIN32
|
||||
#if defined(_WIN32) && !defined(_UWP)
|
||||
// delete the temporary file
|
||||
if (!DeleteFileW(StringUtil::UTF8StringToWideString(m_temporaryFileName).c_str()))
|
||||
{
|
||||
|
@ -280,6 +280,14 @@ public:
|
|||
"AtomicUpdatedFileByteStream::~AtomicUpdatedFileByteStream(): Failed to delete temporary file '%s'",
|
||||
m_temporaryFileName.c_str());
|
||||
}
|
||||
#elif defined(_UWP)
|
||||
// delete the temporary file
|
||||
if (!DeleteFileFromAppW(StringUtil::UTF8StringToWideString(m_temporaryFileName).c_str()))
|
||||
{
|
||||
Log_WarningPrintf(
|
||||
"AtomicUpdatedFileByteStream::~AtomicUpdatedFileByteStream(): Failed to delete temporary file '%s'",
|
||||
m_temporaryFileName.c_str());
|
||||
}
|
||||
#else
|
||||
// delete the temporary file
|
||||
if (remove(m_temporaryFileName.c_str()) < 0)
|
||||
|
@ -315,7 +323,7 @@ public:
|
|||
|
||||
fflush(m_pFile);
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(_UWP)
|
||||
// move the atomic file name to the original file name
|
||||
if (!MoveFileExW(StringUtil::UTF8StringToWideString(m_temporaryFileName).c_str(),
|
||||
StringUtil::UTF8StringToWideString(m_originalFileName).c_str(), MOVEFILE_REPLACE_EXISTING))
|
||||
|
@ -328,6 +336,17 @@ public:
|
|||
{
|
||||
m_committed = true;
|
||||
}
|
||||
#elif defined(_UWP)
|
||||
if (!FileSystem::RenamePath(m_temporaryFileName.c_str(), m_originalFileName.c_str()))
|
||||
{
|
||||
Log_WarningPrintf("AtomicUpdatedFileByteStream::Commit(): Failed to rename temporary file '%s' to '%s'",
|
||||
m_temporaryFileName.c_str(), m_originalFileName.c_str());
|
||||
m_discarded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_committed = true;
|
||||
}
|
||||
#else
|
||||
// move the atomic file name to the original file name
|
||||
if (rename(m_temporaryFileName.c_str(), m_originalFileName.c_str()) < 0)
|
||||
|
@ -1000,6 +1019,7 @@ std::unique_ptr<ByteStream> ByteStream_OpenFileStream(const char* fileName, u32
|
|||
{
|
||||
DebugAssert(openMode & (BYTESTREAM_OPEN_CREATE | BYTESTREAM_OPEN_WRITE));
|
||||
|
||||
#ifndef _UWP
|
||||
// generate the temporary file name
|
||||
u32 fileNameLength = static_cast<u32>(std::strlen(fileName));
|
||||
char* temporaryFileName = (char*)alloca(fileNameLength + 8);
|
||||
|
@ -1008,6 +1028,22 @@ std::unique_ptr<ByteStream> ByteStream_OpenFileStream(const char* fileName, u32
|
|||
// fill in random characters
|
||||
_mktemp_s(temporaryFileName, fileNameLength + 8);
|
||||
const std::wstring wideTemporaryFileName(StringUtil::UTF8StringToWideString(temporaryFileName));
|
||||
#else
|
||||
// On UWP, preserve the extension, as it affects permissions.
|
||||
std::string temporaryFileName;
|
||||
const char* extension = std::strrchr(fileName, '.');
|
||||
if (extension)
|
||||
temporaryFileName.append(fileName, extension - fileName);
|
||||
else
|
||||
temporaryFileName.append(fileName);
|
||||
|
||||
temporaryFileName.append("_XXXXXX");
|
||||
_mktemp_s(temporaryFileName.data(), temporaryFileName.size() + 1);
|
||||
if (extension)
|
||||
temporaryFileName.append(extension);
|
||||
|
||||
const std::wstring wideTemporaryFileName(StringUtil::UTF8StringToWideString(temporaryFileName));
|
||||
#endif
|
||||
|
||||
// massive hack here
|
||||
DWORD desiredAccess = GENERIC_WRITE;
|
||||
|
|
|
@ -1794,7 +1794,17 @@ bool FileSystem::RenamePath(const char* OldPath, const char* NewPath)
|
|||
return false;
|
||||
}
|
||||
#else
|
||||
if (!ReplaceFileFromAppW(old_wpath.c_str(), new_wpath.c_str(), nullptr, 0, nullptr, nullptr))
|
||||
// try moving if it doesn't exist, since ReplaceFile fails on non-existing destinations
|
||||
if (WrapGetFileAttributes(new_wpath.c_str()) != INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
if (!DeleteFileFromAppW(new_wpath.c_str()))
|
||||
{
|
||||
Log_ErrorPrintf("DeleteFileFromAppW('%s') failed: %08X", new_wpath.c_str(), GetLastError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!MoveFileFromAppW(old_wpath.c_str(), new_wpath.c_str()))
|
||||
{
|
||||
Log_ErrorPrintf("MoveFileFromAppW('%s', '%s') failed: %08X", OldPath, NewPath, GetLastError());
|
||||
return false;
|
||||
|
|
Loading…
Reference in a new issue