Merge pull request #5133 from SandstromPL/fix/savedata-search-other-title
fix(savedata): return no saves for a search with another title's ID
This commit is contained in:
commit
a21d73733c
|
|
@ -18,6 +18,7 @@
|
|||
#include <string>
|
||||
#include "SceTypes.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
#include "prx/libkernel/AppMetadata/include/AppMetadata.hpp"
|
||||
#include "SaveData.hpp"
|
||||
#include "prx/libSceSaveData/SaveDataFile.hpp"
|
||||
|
||||
|
|
@ -278,6 +279,9 @@ static int dirNameSearch(const SaveDataDirNameSearchCond* cond, SaveDataDirNameS
|
|||
if ((key > SAVE_DATA_SORT_KEY_MTIME && key != SAVE_DATA_SORT_KEY_FREE_BLOCKS) || cond->order > SAVE_DATA_SORT_ORDER_DESCENT) {
|
||||
return SAVE_DATA_ERROR_PARAMETER;
|
||||
}
|
||||
if (cond->title_id != nullptr && std::strncmp(cond->title_id->data, GetAppTitleId_nid_postfix().value, sizeof(cond->title_id->data)) != 0) {
|
||||
return SAVE_DATA_OK;
|
||||
}
|
||||
const char* pattern = (cond->dir_name != nullptr) ? cond->dir_name->data : nullptr;
|
||||
const std::string root = save_root();
|
||||
if (!std::filesystem::is_directory(root)) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "SceTypes.hpp"
|
||||
#include "prx/libc/include/general/VabiMacros.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
|
@ -123,6 +124,42 @@ static void TrailingWildcards() {
|
|||
Require(SearchPattern("TRAIL_%") == Names{"TRAIL1"}, "_ must still match exactly one character");
|
||||
}
|
||||
|
||||
static std::uint32_t SearchTitle(const char* titleId, bool second) {
|
||||
SceSaveDataTitleId title{};
|
||||
std::snprintf(title.data, sizeof(title.data), "%s", titleId != nullptr ? titleId : "");
|
||||
SceSaveDataDirName pattern{};
|
||||
std::snprintf(pattern.data, sizeof(pattern.data), "OTHER_%%");
|
||||
SaveDataDirNameSearchCond cond{};
|
||||
cond.user_id = 1;
|
||||
cond.title_id = titleId != nullptr ? &title : nullptr;
|
||||
cond.dir_name = &pattern;
|
||||
std::array<SceSaveDataDirName, 1> names{};
|
||||
names[0].data[0] = '!';
|
||||
SaveDataDirNameSearchResult result{};
|
||||
result.dir_names = names.data();
|
||||
result.dir_names_num = 1;
|
||||
result.hit_num = 7;
|
||||
result.set_num = 7;
|
||||
Require((second ? sceSaveDataDirNameSearch2(&cond, &result) : sceSaveDataDirNameSearch(&cond, &result)) == 0, "title search failed");
|
||||
Require(result.set_num == std::min<std::uint32_t>(result.hit_num, 1), "title search must set the names it found");
|
||||
Require(result.set_num == 1 ? std::string(names[0].data) == "OTHER_A" : names[0].data[0] == '!', "title search returned the wrong name");
|
||||
return result.hit_num;
|
||||
}
|
||||
|
||||
static void OtherTitle() {
|
||||
std::filesystem::create_directories("app0/sce_sys");
|
||||
std::FILE* param = std::fopen("app0/sce_sys/param.json", "wb");
|
||||
Require(param != nullptr, "param.json was not created");
|
||||
std::fputs("{\"titleId\":\"PPSA00000\",\"localizedParameters\":{\"en-US\":{\"titleName\":\"Example\"}}}", param);
|
||||
std::fclose(param);
|
||||
std::filesystem::create_directories(std::filesystem::path("_sd") / "OTHER_A");
|
||||
for (const bool second : {false, true}) {
|
||||
Require(SearchTitle(nullptr, second) == 1, "a search without a title id must find the running title's save");
|
||||
Require(SearchTitle("PPSA00000", second) == 1, "a search for the running title must find its save");
|
||||
Require(SearchTitle("PPSA17221", second) == 0, "a search for another title must find none of the running title's saves");
|
||||
}
|
||||
}
|
||||
|
||||
static void SearchAndMount() {
|
||||
const std::array names{std::string(31, 'A'), std::string(31, 'B')};
|
||||
for (const auto& name : names) std::filesystem::create_directories(std::filesystem::path("_sd") / name);
|
||||
|
|
@ -181,6 +218,7 @@ int main() {
|
|||
try {
|
||||
SearchAndMount();
|
||||
SortByKey();
|
||||
OtherTitle();
|
||||
TrailingWildcards();
|
||||
} catch (const std::exception& error) {
|
||||
std::fprintf(stderr, "%s\n", error.what());
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
### Functional
|
||||
|
||||
- [sceSaveDataDirNameSearch, sceSaveDataDirNameSearch2](../../../core/libs/prx/libSceSaveData.native/Export.cpp) (libSceSaveData.native) - only the running title's saves are kept, so a search with another title's `title_id` reports zero hits, as [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/ec334904604ba41f5d4753f4a2498ec82540e5d6/src/core/libraries/save_data/savedata.cpp#L791-L802) and [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/569ec04d1a77127c601eed522ad5bba187173f9d/src/libs/libSaveData.cpp#L592-L596) do when that title has no save directory; what a console returns for another title's saves is not verified. The running title's ID is the `titleId` in its `param.json`
|
||||
- [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