Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions core/libs/prx/libSceContentDelete/Export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

namespace {
std::atomic<bool> g_initialized{false};

void RequireInitialized(const char* function) {
if (!g_initialized.load()) throw std::logic_error(std::string(function) + ": not initialized");
}
}

extern "C" {
Expand All @@ -19,14 +23,15 @@ int APS5_VABI sceContentDeleteInitialize(const ContentDeleteInitParam* init_para
return 0;
}

int APS5_VABI sceContentDeleteByPath(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
int APS5_VABI sceContentDeleteByPath(const char* contentPath) {
if (contentPath == nullptr) APS5_INVALID_ARG_EX;
RequireInitialized(__func__);
throw std::logic_error(std::string(__func__) + ": " + contentPath + " is not in the host content library, which is empty, and the console's error for it is unknown");
}

int APS5_VABI sceContentDeleteById(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
int APS5_VABI sceContentDeleteById(std::int64_t contentId) {
RequireInitialized(__func__);
throw std::logic_error(std::string(__func__) + ": content id " + std::to_string(contentId) + " is not in the host content library, which is empty, and the console's error for it is unknown");
}

int APS5_VABI sceContentDeleteTerminate(void) {
Expand Down
12 changes: 11 additions & 1 deletion core/libs/prx/libSceContentExport/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,21 @@ if(BUILD_TESTING)

add_test_executable(guest_content_unimplemented_tests ${LIBS_INCLUDE_DIR}/tests/GuestContentUnimplemented.cpp)
target_include_directories(guest_content_unimplemented_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_content_unimplemented_tests PRIVATE libSceContentSearch libSceContentDelete libc)
target_link_libraries(guest_content_unimplemented_tests PRIVATE libSceContentSearch libc)
configure_windows_unwind(guest_content_unimplemented_tests)
add_test(NAME guest_content_unimplemented COMMAND guest_content_unimplemented_tests)
if(WIN32)
set_tests_properties(guest_content_unimplemented PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()

add_test_executable(guest_content_delete_tests ${LIBS_INCLUDE_DIR}/tests/GuestContentDelete.cpp)
target_include_directories(guest_content_delete_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_content_delete_tests PRIVATE libSceContentDelete libc)
configure_windows_unwind(guest_content_delete_tests)
add_test(NAME guest_content_delete COMMAND guest_content_delete_tests)
if(WIN32)
set_tests_properties(guest_content_delete PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
49 changes: 49 additions & 0 deletions core/libs/tests/GuestContentDelete.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "SceTypes.hpp"
#include <cstdint>
#include <cstdlib>
#include <stdexcept>
#include <string>

extern "C" int APS5_VABI sceContentDeleteInitialize(const ContentDeleteInitParam* init_param);
extern "C" int APS5_VABI sceContentDeleteTerminate(void);
extern "C" int APS5_VABI sceContentDeleteById(std::int64_t contentId);
extern "C" int APS5_VABI sceContentDeleteByPath(const char* contentPath);

namespace {

void Require(bool value) { if (!value) std::abort(); }

template <typename TAction>
std::string LogicErrorMessage(TAction action) {
try {
action();
} catch (const std::invalid_argument&) {
return "invalid argument";
} catch (const std::logic_error& error) {
return error.what();
}
return "returned";
}

bool Contains(const std::string& text, const std::string& part) { return text.find(part) != std::string::npos; }

}

int main() {
Require(LogicErrorMessage([] { sceContentDeleteById(1); }) == "sceContentDeleteById: not initialized");
Require(LogicErrorMessage([] { sceContentDeleteByPath("/user/av_contents/photo/a.png"); }) == "sceContentDeleteByPath: not initialized");
Require(LogicErrorMessage([] { sceContentDeleteByPath(nullptr); }) == "invalid argument");

ContentDeleteInitParam param{};
param.heap_size = 0x10000;
Require(sceContentDeleteInitialize(&param) == 0);

Require(LogicErrorMessage([] { sceContentDeleteByPath(nullptr); }) == "invalid argument");
Require(Contains(LogicErrorMessage([] { sceContentDeleteByPath("/user/av_contents/photo/a.png"); }), "sceContentDeleteByPath: /user/av_contents/photo/a.png is not in the host content library"));
Require(Contains(LogicErrorMessage([] { sceContentDeleteById(0x123456789); }), "sceContentDeleteById: content id 4886718345 is not in the host content library"));
Require(Contains(LogicErrorMessage([] { sceContentDeleteById(-1); }), "sceContentDeleteById: content id -1 is not in the host content library"));

Require(sceContentDeleteTerminate() == 0);
Require(LogicErrorMessage([] { sceContentDeleteById(1); }) == "sceContentDeleteById: not initialized");
return 0;
}
2 changes: 0 additions & 2 deletions core/libs/tests/GuestContentUnimplemented.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <string>

extern "C" {
int APS5_VABI sceContentDeleteById();
int APS5_VABI sceContentSearchGetContentLastUpdateId();
int APS5_VABI sceContentSearchOpenMetadataByContentId();
int APS5_VABI sceContentSearchGetTotalContentSize();
Expand All @@ -30,7 +29,6 @@ bool ReportsNotImplemented(const char* name, int (APS5_VABI *function)()) {

int main() {
bool correct = true;
correct &= ReportsNotImplemented("sceContentDeleteById", sceContentDeleteById);
correct &= ReportsNotImplemented("sceContentSearchGetContentLastUpdateId", sceContentSearchGetContentLastUpdateId);
correct &= ReportsNotImplemented("sceContentSearchOpenMetadataByContentId", sceContentSearchOpenMetadataByContentId);
correct &= ReportsNotImplemented("sceContentSearchGetTotalContentSize", sceContentSearchGetTotalContentSize);
Expand Down
4 changes: 2 additions & 2 deletions docs/dev/debt/libSceContentDelete.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# libSceContentDelete technical debt

### Unknown function info
### Functional

- [sceContentDeleteById](../../../core/libs/prx/libSceContentDelete/Export.cpp) (libSceContentDelete) and [sceContentSearchGetContentLastUpdateId, sceContentSearchOpenMetadataByContentId, sceContentSearchGetTotalContentSize, sceContentSearchGetNumOfContent](../../../core/libs/prx/libSceContentSearch/Export.cpp) (libSceContentSearch) - imported by PPSA06465, which fails to load without them; added without an implementation because their signatures are unknown
- [sceContentDeleteById and sceContentDeleteByPath](../../../core/libs/prx/libSceContentDelete/Export.cpp) (libSceContentDelete) delete from a content library that is empty on the host, as nothing is exported to it, so both throw for every content id and path once the arguments and the initialization are checked: no reference gives the console's error for content that is not in the library ([SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/Content/ContentDelete.cs#L25-L42) names only `0x809D5006`, no permission). The signatures, a 64-bit content id and a UTF-8 path, follow [Orbital](https://github.com/AlexAltea/orbital/blob/cc408367da6a6ebbf5ac1ac559fefeadc73b2831/tools/ida/db_types.json#L541-L542) and SharpProspero, which agree. A null path and a call outside `sceContentDeleteInitialize` and `sceContentDeleteTerminate` throw, as the console's errors for them are unknown, and the order of the two checks is unverified.
5 changes: 5 additions & 0 deletions docs/dev/debt/libSceContentSearch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# libSceContentSearch technical debt

### Unknown function info

- [sceContentSearchGetContentLastUpdateId, sceContentSearchOpenMetadataByContentId, sceContentSearchGetTotalContentSize, sceContentSearchGetNumOfContent](../../../core/libs/prx/libSceContentSearch/Export.cpp) (libSceContentSearch) - imported by PPSA06465, which fails to load without them; added without an implementation because their signatures are unknown
Loading