diff options
| author | JosJuice <josjuice@gmail.com> | 2026-09-20 22:30:42 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-20 22:30:42 +0200 |
| commit | 8f674f574adfa69f1cbb1d4b98f3149c73b9bf8b (patch) | |
| tree | fb5b26363194ee719e487492adbeb7cfcaaebdc5 /Source | |
| parent | dbff13226c4143e0d48baf2f57284341002dabcf (diff) | |
| parent | 093d3abe95d14ca90cdd7ac9e57c5b76e89084d8 (diff) | |
Merge pull request #14833 from JosJuice/state-nand-tas
IOS/FS: Fix loading savestate while TASing
Diffstat (limited to 'Source')
| -rw-r--r-- | Source/Core/Core/IOS/FS/FileSystemCommon.cpp | 101 |
1 files changed, 82 insertions, 19 deletions
diff --git a/Source/Core/Core/IOS/FS/FileSystemCommon.cpp b/Source/Core/Core/IOS/FS/FileSystemCommon.cpp index 0e13192c5b..225084c177 100644 --- a/Source/Core/Core/IOS/FS/FileSystemCommon.cpp +++ b/Source/Core/Core/IOS/FS/FileSystemCommon.cpp @@ -139,12 +139,45 @@ ResultCode FileSystem::CreateFullPath(Uid uid, Gid gid, const std::string& path, void FileSystem::DoStateRead(PointerWrap& p, const std::string& directory_path) { - const ResultCode delete_result = Delete(0, 0, directory_path); - if (delete_result != ResultCode::Success && delete_result != ResultCode::NotFound) + const auto delete_ = [this](const std::string& directory_path_) { + const ResultCode delete_result = Delete(0, 0, directory_path_); + if (delete_result != ResultCode::Success && delete_result != ResultCode::NotFound) + { + ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call Delete for {}: {}", directory_path_, + delete_result); + return false; + } + return true; + }; + + if (directory_path != "/") { - ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call Delete: {}", delete_result); - p.SetVerifyMode(); - return; + if (!delete_(directory_path)) + { + p.SetVerifyMode(); + return; + } + } + else + { + // Calling Delete for the root would return Invalid. Let's delete all children instead. + auto children = ReadDirectory(0, 0, directory_path); + if (!children) + { + ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call ReadDirectory for {}: {}", directory_path, + children.error()); + p.SetVerifyMode(); + return; + } + + for (const std::string& child_name : children.value()) + { + if (!delete_(directory_path + child_name)) + { + p.SetVerifyMode(); + return; + } + } } Metadata metadata{}; @@ -156,12 +189,29 @@ void FileSystem::DoStateRead(PointerWrap& p, const std::string& directory_path) p.Do(metadata.size); p.Do(metadata.fst_index); - const ResultCode create_directory_result = CreateDirectory( - metadata.uid, metadata.gid, directory_path, metadata.attribute, metadata.modes); - if (create_directory_result != ResultCode::Success) + // Again here, calling CreateDirectory for the root would return Invalid. + // The root always exists, so we can skip creating it. + if (directory_path != "/") { - ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call CreateDirectory: {}", - create_directory_result); + // UID 0 is used to avoid AccessDenied. + const ResultCode create_directory_result = + CreateDirectory(0, 0, directory_path, metadata.attribute, metadata.modes); + if (create_directory_result != ResultCode::Success) + { + ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call CreateDirectory for {}: {}", directory_path, + create_directory_result); + p.SetVerifyMode(); + return; + } + } + + // Change the UID and GID from 0 to the intended values. + const ResultCode set_metadata_result = SetMetadata(0, directory_path, metadata.uid, metadata.gid, + metadata.attribute, metadata.modes); + if (set_metadata_result != ResultCode::Success) + { + ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call SetMetadata for {}: {}", directory_path, + set_metadata_result); p.SetVerifyMode(); return; } @@ -182,22 +232,34 @@ void FileSystem::DoStateRead(PointerWrap& p, const std::string& directory_path) if (child_metadata.is_file) { + // UID 0 is used to avoid AccessDenied. const ResultCode create_file_result = - CreateFile(child_metadata.uid, child_metadata.gid, child_path, child_metadata.attribute, - child_metadata.modes); + CreateFile(0, 0, child_path, child_metadata.attribute, child_metadata.modes); if (create_file_result != ResultCode::Success) { - ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call CreateFile for {}: {}", child_name, + ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call CreateFile for {}: {}", child_path, create_file_result); p_.SetVerifyMode(); return; } + // Change the UID and GID from 0 to the intended values. + const ResultCode set_metadata_result = + SetMetadata(0, child_path, child_metadata.uid, child_metadata.gid, + child_metadata.attribute, child_metadata.modes); + if (set_metadata_result != ResultCode::Success) + { + ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call SetMetadata for {}: {}", child_path, + set_metadata_result); + p_.SetVerifyMode(); + return; + } + std::array<u8, BUFFER_CHUNK_SIZE> buffer; Result<FileHandle> handle = OpenFile(0, 0, child_path, Mode::Write); if (!handle) { - ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call OpenFile for {}: {}", child_name, + ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call OpenFile for {}: {}", child_path, handle.error()); p_.SetVerifyMode(); return; @@ -213,7 +275,7 @@ void FileSystem::DoStateRead(PointerWrap& p, const std::string& directory_path) Result<size_t> write_result = handle->Write(buffer.data(), bytes_to_write); if (!write_result) { - ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call Write for {}: {}", child_name, + ERROR_LOG_FMT(IOS_FS, "DoStateRead failed to call Write for {}: {}", child_path, write_result.error()); p_.SetVerifyMode(); return; @@ -221,7 +283,7 @@ void FileSystem::DoStateRead(PointerWrap& p, const std::string& directory_path) if (*write_result != bytes_to_write) { ERROR_LOG_FMT(IOS_FS, "DoStateRead tried to write {} bytes to {} but wrote {} bytes", - child_name, bytes_to_write, *write_result); + child_path, bytes_to_write, *write_result); p_.SetVerifyMode(); return; } @@ -241,7 +303,8 @@ void FileSystem::DoStateWriteOrMeasure(PointerWrap& p, const std::string& direct const Result<Metadata> metadata = GetMetadata(0, 0, directory_path); if (!metadata) { - ERROR_LOG_FMT(IOS_FS, "DoStateWriteOrMeasure failed to call GetMetadata: {}", metadata.error()); + ERROR_LOG_FMT(IOS_FS, "DoStateWriteOrMeasure failed to call GetMetadata for {}: {}", + directory_path, metadata.error()); p.SetVerifyMode(); return; } @@ -256,8 +319,8 @@ void FileSystem::DoStateWriteOrMeasure(PointerWrap& p, const std::string& direct auto children = ReadDirectory(0, 0, directory_path); if (!children) { - ERROR_LOG_FMT(IOS_FS, "DoStateWriteOrMeasure failed to call ReadDirectory: {}", - children.error()); + ERROR_LOG_FMT(IOS_FS, "DoStateWriteOrMeasure failed to call ReadDirectory for {}: {}", + directory_path, children.error()); p.SetVerifyMode(); return; } |
