mirror of
				https://github.com/RetroDECK/Duckstation.git
				synced 2025-04-10 19:15:14 +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
	
	 Connor McLaughlin
						Connor McLaughlin