mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-01-30 03:25:39 +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
|
class AtomicUpdatedFileByteStream : public FileByteStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AtomicUpdatedFileByteStream(FILE* pFile, const char* originalFileName, const char* temporaryFileName)
|
AtomicUpdatedFileByteStream(FILE* pFile, std::string originalFileName, std::string temporaryFileName)
|
||||||
: FileByteStream(pFile), m_committed(false), m_discarded(false), m_originalFileName(originalFileName),
|
: FileByteStream(pFile), m_committed(false), m_discarded(false), m_originalFileName(std::move(originalFileName)),
|
||||||
m_temporaryFileName(temporaryFileName)
|
m_temporaryFileName(std::move(temporaryFileName))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +272,7 @@ public:
|
||||||
{
|
{
|
||||||
if (m_discarded)
|
if (m_discarded)
|
||||||
{
|
{
|
||||||
#if _WIN32
|
#if defined(_WIN32) && !defined(_UWP)
|
||||||
// delete the temporary file
|
// delete the temporary file
|
||||||
if (!DeleteFileW(StringUtil::UTF8StringToWideString(m_temporaryFileName).c_str()))
|
if (!DeleteFileW(StringUtil::UTF8StringToWideString(m_temporaryFileName).c_str()))
|
||||||
{
|
{
|
||||||
|
@ -280,6 +280,14 @@ public:
|
||||||
"AtomicUpdatedFileByteStream::~AtomicUpdatedFileByteStream(): Failed to delete temporary file '%s'",
|
"AtomicUpdatedFileByteStream::~AtomicUpdatedFileByteStream(): Failed to delete temporary file '%s'",
|
||||||
m_temporaryFileName.c_str());
|
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
|
#else
|
||||||
// delete the temporary file
|
// delete the temporary file
|
||||||
if (remove(m_temporaryFileName.c_str()) < 0)
|
if (remove(m_temporaryFileName.c_str()) < 0)
|
||||||
|
@ -315,7 +323,7 @@ public:
|
||||||
|
|
||||||
fflush(m_pFile);
|
fflush(m_pFile);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32) && !defined(_UWP)
|
||||||
// move the atomic file name to the original file name
|
// move the atomic file name to the original file name
|
||||||
if (!MoveFileExW(StringUtil::UTF8StringToWideString(m_temporaryFileName).c_str(),
|
if (!MoveFileExW(StringUtil::UTF8StringToWideString(m_temporaryFileName).c_str(),
|
||||||
StringUtil::UTF8StringToWideString(m_originalFileName).c_str(), MOVEFILE_REPLACE_EXISTING))
|
StringUtil::UTF8StringToWideString(m_originalFileName).c_str(), MOVEFILE_REPLACE_EXISTING))
|
||||||
|
@ -328,6 +336,17 @@ public:
|
||||||
{
|
{
|
||||||
m_committed = true;
|
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
|
#else
|
||||||
// move the atomic file name to the original file name
|
// move the atomic file name to the original file name
|
||||||
if (rename(m_temporaryFileName.c_str(), m_originalFileName.c_str()) < 0)
|
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));
|
DebugAssert(openMode & (BYTESTREAM_OPEN_CREATE | BYTESTREAM_OPEN_WRITE));
|
||||||
|
|
||||||
|
#ifndef _UWP
|
||||||
// generate the temporary file name
|
// generate the temporary file name
|
||||||
u32 fileNameLength = static_cast<u32>(std::strlen(fileName));
|
u32 fileNameLength = static_cast<u32>(std::strlen(fileName));
|
||||||
char* temporaryFileName = (char*)alloca(fileNameLength + 8);
|
char* temporaryFileName = (char*)alloca(fileNameLength + 8);
|
||||||
|
@ -1008,6 +1028,22 @@ std::unique_ptr<ByteStream> ByteStream_OpenFileStream(const char* fileName, u32
|
||||||
// fill in random characters
|
// fill in random characters
|
||||||
_mktemp_s(temporaryFileName, fileNameLength + 8);
|
_mktemp_s(temporaryFileName, fileNameLength + 8);
|
||||||
const std::wstring wideTemporaryFileName(StringUtil::UTF8StringToWideString(temporaryFileName));
|
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
|
// massive hack here
|
||||||
DWORD desiredAccess = GENERIC_WRITE;
|
DWORD desiredAccess = GENERIC_WRITE;
|
||||||
|
|
|
@ -1794,7 +1794,17 @@ bool FileSystem::RenamePath(const char* OldPath, const char* NewPath)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#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());
|
Log_ErrorPrintf("MoveFileFromAppW('%s', '%s') failed: %08X", OldPath, NewPath, GetLastError());
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in a new issue