mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-09-26 12:16:45 -05:00
Merge pull request #14833 from JosJuice/state-nand-tas
IOS/FS: Fix loading savestate while TASing
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user