From 0efff5167d8da31f4233a4bf9999c3970517040a Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 23 Oct 2021 02:03:11 +0200 Subject: [PATCH] IOS/FS: On NAND redirected files, the source and target of a Rename operation may be on different partitions or devices. Implement a fallback for that. --- Source/Core/Core/IOS/FS/HostBackend/FS.cpp | 29 +++++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/Source/Core/Core/IOS/FS/HostBackend/FS.cpp b/Source/Core/Core/IOS/FS/HostBackend/FS.cpp index 8ca81558cd..7bdb785e7f 100644 --- a/Source/Core/Core/IOS/FS/HostBackend/FS.cpp +++ b/Source/Core/Core/IOS/FS/HostBackend/FS.cpp @@ -506,8 +506,10 @@ ResultCode HostFileSystem::Rename(Uid uid, Gid gid, const std::string& old_path, return ResultCode::InUse; } - const std::string host_old_path = BuildFilename(old_path).host_path; - const std::string host_new_path = BuildFilename(new_path).host_path; + const auto host_old_info = BuildFilename(old_path); + const auto host_new_info = BuildFilename(new_path); + const std::string& host_old_path = host_old_info.host_path; + const std::string& host_new_path = host_new_info.host_path; // If there is already something of the same type at the new path, delete it. if (File::Exists(host_new_path)) @@ -524,8 +526,27 @@ ResultCode HostFileSystem::Rename(Uid uid, Gid gid, const std::string& old_path, if (!File::Rename(host_old_path, host_new_path)) { - ERROR_LOG_FMT(IOS_FS, "Rename {} to {} - failed", host_old_path, host_new_path); - return ResultCode::NotFound; + if (host_old_info.is_redirect || host_new_info.is_redirect) + { + // If either path is a redirect, the source and target may be on a different partition or + // device, so a simple rename may not work. Fall back to Copy & Delete and see if that works. + if (!File::Copy(host_old_path, host_new_path)) + { + ERROR_LOG_FMT(IOS_FS, "Copying {} to {} in Rename fallback failed", host_old_path, + host_new_path); + return ResultCode::NotFound; + } + if (!File::Delete(host_old_path)) + { + ERROR_LOG_FMT(IOS_FS, "Deleting {} in Rename fallback failed", host_old_path); + return ResultCode::Invalid; + } + } + else + { + ERROR_LOG_FMT(IOS_FS, "Rename {} to {} - failed", host_old_path, host_new_path); + return ResultCode::NotFound; + } } // Finally, remove the child from the old parent and move it to the new parent.