From 6abf4f0c667f6beae061dbaebfe141bb8906369b Mon Sep 17 00:00:00 2001 From: Silent Date: Sun, 7 Mar 2021 13:30:22 +0100 Subject: [PATCH] Further improve partition path functions * Close a possible edge case of "\\Partition" being present in the path * Close a possible edge case of an invalid path being shorter than the string "\\Partition" * Allow for partition formatting to work fine when EmuDisk has been relocated --- src/core/kernel/support/EmuFile.cpp | 35 +++++++++++++++++++++++------ src/core/kernel/support/EmuFile.h | 2 +- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/core/kernel/support/EmuFile.cpp b/src/core/kernel/support/EmuFile.cpp index 9cde84ef6..26faf4d37 100644 --- a/src/core/kernel/support/EmuFile.cpp +++ b/src/core/kernel/support/EmuFile.cpp @@ -153,34 +153,55 @@ static std::wstring CxbxGetFinalPathNameByHandle(HANDLE hFile) return path; } +static bool CxbxIsPathInsideEmuDisk(const std::filesystem::path& path) +{ + std::error_code rootError, finalError; + + const std::filesystem::path rootPath = std::filesystem::canonical(CxbxBasePath, rootError); + const std::filesystem::path finalPath = std::filesystem::canonical(path, finalError); + if (rootError || finalError) { + return false; + } + auto match = std::mismatch(rootPath.begin(), rootPath.end(), finalPath.begin(), finalPath.end()); + return match.first == rootPath.end(); +} + int CxbxGetPartitionNumberFromHandle(HANDLE hFile) { // Get which partition number is being accessed, by parsing the filename and extracting the last portion const std::wstring path = CxbxGetFinalPathNameByHandle(hFile); - const std::wstring_view partitionString = L"\\Partition"; - const std::wstring partitionNumberString = path.substr(path.find(partitionString) + partitionString.length(), 1); + const std::wstring_view partitionString = L"\\EmuDisk\\Partition"; + const size_t pos = path.rfind(partitionString); + if (pos == std::string::npos) { + return 0; + } + const std::wstring partitionNumberString = path.substr(pos + partitionString.length(), 1); // wcstol returns 0 on non-numeric characters, so we don't need to error check here return wcstol(partitionNumberString.c_str(), nullptr, 0); } -std::wstring CxbxGetPartitionDataPathFromHandle(HANDLE hFile) +std::filesystem::path CxbxGetPartitionDataPathFromHandle(HANDLE hFile) { // Get which partition number is being accessed, by parsing the filename and extracting the last portion const std::wstring path = CxbxGetFinalPathNameByHandle(hFile); - const std::wstring_view partitionString = L"\\Partition"; - const std::wstring partitionPath = path.substr(0, path.find(partitionString) + partitionString.length() + 1); + std::wstring partitionPath; + const std::wstring_view partitionString = L"\\EmuDisk\\Partition"; + const size_t pos = path.rfind(partitionString); + if (pos != std::string::npos) { + partitionPath = path.substr(0, path.find(partitionString) + partitionString.length() + 1); + } return partitionPath; } void CxbxFormatPartitionByHandle(HANDLE hFile) { - const std::wstring partitionPath = CxbxGetPartitionDataPathFromHandle(hFile); + const std::filesystem::path partitionPath = CxbxGetPartitionDataPathFromHandle(hFile); // Sanity check, make sure we are actually deleting something within the Cxbx-Reloaded folder - if (partitionPath.find(L"\\Cxbx-Reloaded\\") == std::string::npos) { + if (!CxbxIsPathInsideEmuDisk(partitionPath)) { EmuLog(LOG_LEVEL::WARNING, "Attempting to format a path that is not within a Cxbx-Reloaded data folder... Ignoring!\n"); return; } diff --git a/src/core/kernel/support/EmuFile.h b/src/core/kernel/support/EmuFile.h index 3fc898abf..c82b0f6b8 100644 --- a/src/core/kernel/support/EmuFile.h +++ b/src/core/kernel/support/EmuFile.h @@ -307,7 +307,7 @@ typedef struct _FATX_SUPERBLOCK XboxPartitionTable CxbxGetPartitionTable(); FATX_SUPERBLOCK CxbxGetFatXSuperBlock(int partitionNumber); int CxbxGetPartitionNumberFromHandle(HANDLE hFile); -std::wstring CxbxGetPartitionDataPathFromHandle(HANDLE hFile); +std::filesystem::path CxbxGetPartitionDataPathFromHandle(HANDLE hFile); void CxbxFormatPartitionByHandle(HANDLE hFile); // Ensures that an original IoStatusBlock gets passed to the completion callback