Merge pull request #4876 from EagleBearerYS/fix/savedata-failed-mount-keeps-result
fix(savedata): leave the mount result untouched when sceSaveDataMount3 fails
This commit is contained in:
commit
8a437941bd
|
|
@ -464,7 +464,6 @@ static int mount3(const SaveDataMount3* mount, SaveDataMountResult* mount_result
|
|||
if (mount == nullptr || mount_result == nullptr || mount->dir_name == nullptr) {
|
||||
throw std::runtime_error("sceSaveDataMount3: null argument");
|
||||
}
|
||||
std::memset(mount_result, 0, sizeof(*mount_result));
|
||||
const bool create = (mount->mount_mode & SAVE_DATA_MOUNT_MODE_CREATE) != 0;
|
||||
const bool create2 = (mount->mount_mode & SAVE_DATA_MOUNT_MODE_CREATE2) != 0;
|
||||
const bool rdonly = (mount->mount_mode & SAVE_DATA_MOUNT_MODE_RDONLY) != 0;
|
||||
|
|
@ -506,6 +505,7 @@ static int mount3(const SaveDataMount3* mount, SaveDataMountResult* mount_result
|
|||
// path resolver maps it to the save directory, whose name may be far longer.
|
||||
const std::string mountPoint = "/savedata" + std::to_string(slot);
|
||||
AddPathAlias_nid_no_patch(mountPoint.c_str(), std::filesystem::absolute(real_path).string().c_str());
|
||||
std::memset(mount_result, 0, sizeof(*mount_result));
|
||||
g_slots[slot].used = true;
|
||||
g_slots[slot].mount_point = mountPoint;
|
||||
g_slots[slot].real_path = real_path;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ namespace {
|
|||
constexpr std::uint32_t MountReadWrite = 2;
|
||||
constexpr std::uint32_t MountCreate = 4;
|
||||
constexpr std::uint32_t MountCreate2 = 32;
|
||||
constexpr int SaveDataErrorBusy = -2137063421;
|
||||
constexpr int SaveDataErrorNotFound = -2137063416;
|
||||
|
||||
int failures = 0;
|
||||
|
||||
|
|
@ -41,6 +43,26 @@ void MountAndCheck(const char* name, std::uint32_t mode, std::uint32_t expectedS
|
|||
Check(sceSaveDataUmount2(0, &result.mount_point) == 0, what + ": unmounts");
|
||||
}
|
||||
|
||||
void CheckFailedMountKeepsResult() {
|
||||
SceSaveDataDirName held{};
|
||||
std::memcpy(held.data, "held", sizeof("held"));
|
||||
SaveDataMount3 mount{};
|
||||
mount.dir_name = &held;
|
||||
mount.mount_mode = MountReadWrite | MountCreate2;
|
||||
SaveDataMountResult result{};
|
||||
Check(sceSaveDataMount3(&mount, &result) == 0, "first mount of a save");
|
||||
const SaveDataMountResult mounted = result;
|
||||
Check(sceSaveDataMount3(&mount, &result) == SaveDataErrorBusy, "second mount of a mounted save is BUSY");
|
||||
Check(std::memcmp(&result, &mounted, sizeof(result)) == 0, "a BUSY mount leaves the result as it was");
|
||||
SceSaveDataDirName absent{};
|
||||
std::memcpy(absent.data, "absent", sizeof("absent"));
|
||||
mount.dir_name = &absent;
|
||||
mount.mount_mode = MountReadWrite;
|
||||
Check(sceSaveDataMount3(&mount, &result) == SaveDataErrorNotFound, "open of a missing save is NOT_FOUND");
|
||||
Check(std::memcmp(&result, &mounted, sizeof(result)) == 0, "a NOT_FOUND mount leaves the result as it was");
|
||||
Check(sceSaveDataUmount2(0, &result.mount_point) == 0, "the kept mount point unmounts the save");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
|
@ -53,6 +75,7 @@ int main() {
|
|||
MountAndCheck("fresh", MountReadWrite | MountCreate2, 0u, "CREATE2 of an existing save");
|
||||
MountAndCheck("made", MountReadWrite | MountCreate, 1u, "CREATE of a missing save");
|
||||
MountAndCheck("made", MountReadWrite, 0u, "open of an existing save");
|
||||
CheckFailedMountKeepsResult();
|
||||
std::filesystem::current_path(previous);
|
||||
std::error_code error;
|
||||
std::filesystem::remove_all(root, error);
|
||||
|
|
|
|||
|
|
@ -13,4 +13,5 @@
|
|||
### Functional
|
||||
|
||||
- [sceSaveDataDirNameSearch2](../../../core/libs/prx/libSceSaveData.native/Export.cpp) (libSceSaveData.native) runs the same search as `sceSaveDataDirNameSearch` with the same condition and result structures, as [SharpEmu](https://github.com/sharpemu/sharpemu/blob/main/src/SharpEmu.Libs/SaveData/SaveDataExports.cs) does, its only source; what distinguishes it on the console is unknown.
|
||||
- [sceSaveDataMount3](../../../core/libs/prx/libSceSaveData.native/Export.cpp) (libSceSaveData.native) - a failed mount (BUSY, EXISTS, NOT_FOUND, MOUNT_FULL) leaves the result as it was, as shadPS4 does; not checked on hardware. Animal Well (PPSA22520) depends on it: it checks for its save with a mount it never unmounts, then saves with a second mount of the same directory, ignores its BUSY and keeps using the first mount point for `sceSaveDataPrepare`, its file and `sceSaveDataUmount2`
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue