mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-28 00:35:47 +00:00
126 lines
5.2 KiB
C++
126 lines
5.2 KiB
C++
#include "prx/libkernel/include/Api.hpp"
|
|
#include "prx/libc/include/Api.hpp"
|
|
#include "SceTypes.hpp"
|
|
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <thread>
|
|
|
|
static constexpr int GUEST_ENOENT = 2;
|
|
static constexpr int GUEST_EEXIST = 17;
|
|
static constexpr int GUEST_EINVAL = 22;
|
|
static constexpr int GUEST_EAGAIN = 35;
|
|
static constexpr int GUEST_ENAMETOOLONG = 63;
|
|
static constexpr int O_CREAT_FLAG = 0x200;
|
|
static constexpr int O_EXCL_FLAG = 0x800;
|
|
|
|
static void Require(bool condition, int line) {
|
|
if (!condition) {
|
|
std::fprintf(stderr, "line %d failed, errno=%d\n", line, *__error_nid_postfix());
|
|
std::abort();
|
|
}
|
|
}
|
|
#define REQUIRE(condition) Require(condition, __LINE__)
|
|
|
|
template <typename Call>
|
|
static bool Throws(Call call) {
|
|
try {
|
|
call();
|
|
} catch (const std::exception&) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool OpenFails(const char* name, int flags, int error) {
|
|
*__error_nid_postfix() = 0;
|
|
return sem_open_nid_postfix(name, flags, 0600, 1) == nullptr && *__error_nid_postfix() == error;
|
|
}
|
|
|
|
static bool UnlinkFails(const char* name, int error) {
|
|
*__error_nid_postfix() = 0;
|
|
return sem_unlink_nid_postfix(name) == -1 && *__error_nid_postfix() == error;
|
|
}
|
|
|
|
static int Value(void* sem) {
|
|
int value = -1;
|
|
REQUIRE(sem_getvalue_nid_postfix(sem, &value) == 0);
|
|
return value;
|
|
}
|
|
|
|
static void CheckNames() {
|
|
REQUIRE(OpenFails("relative", O_CREAT_FLAG, GUEST_EINVAL));
|
|
REQUIRE(OpenFails("/anyps5-named-flags", 0x1, GUEST_EINVAL));
|
|
REQUIRE(OpenFails("/anyps5-named-flags", O_CREAT_FLAG | 0x2, GUEST_EINVAL));
|
|
REQUIRE(OpenFails("/anyps5-named-missing", 0, GUEST_ENOENT));
|
|
REQUIRE(OpenFails("/anyps5-named-missing", O_EXCL_FLAG, GUEST_ENOENT));
|
|
const std::string longPath = "/" + std::string(1015, 'p');
|
|
REQUIRE(OpenFails(longPath.c_str(), O_CREAT_FLAG, GUEST_ENAMETOOLONG));
|
|
REQUIRE(UnlinkFails(longPath.c_str(), GUEST_ENAMETOOLONG));
|
|
const std::string longFile = "/" + std::string(252, 'f');
|
|
REQUIRE(OpenFails(longFile.c_str(), O_CREAT_FLAG, GUEST_ENAMETOOLONG));
|
|
REQUIRE(OpenFails(longFile.c_str(), 0x1, GUEST_EINVAL));
|
|
REQUIRE(UnlinkFails(longFile.c_str(), GUEST_ENAMETOOLONG));
|
|
const std::string longestFile = "/" + std::string(251, 'f');
|
|
void* longest = sem_open_nid_postfix(longestFile.c_str(), O_CREAT_FLAG, 0600, 0);
|
|
REQUIRE(longest != nullptr && sem_close_nid_postfix(longest) == 0 && sem_unlink_nid_postfix(longestFile.c_str()) == 0);
|
|
REQUIRE(UnlinkFails("relative", GUEST_ENOENT));
|
|
REQUIRE(UnlinkFails("/anyps5-named-missing", GUEST_ENOENT));
|
|
REQUIRE(Throws([] { sem_open_nid_postfix(nullptr, 0); }));
|
|
REQUIRE(Throws([] { sem_unlink_nid_postfix(nullptr); }));
|
|
}
|
|
|
|
static void CheckLifetime() {
|
|
const char* name = "/anyps5-named-lifetime";
|
|
void* sem = sem_open_nid_postfix(name, O_CREAT_FLAG | O_EXCL_FLAG, 0600, 2);
|
|
REQUIRE(sem != nullptr && Value(sem) == 2);
|
|
REQUIRE(sem_open_nid_postfix(name, 0) == sem);
|
|
REQUIRE(sem_open_nid_postfix(name, O_CREAT_FLAG, 0600, 9) == sem && Value(sem) == 2);
|
|
REQUIRE(OpenFails(name, O_CREAT_FLAG | O_EXCL_FLAG, GUEST_EEXIST));
|
|
REQUIRE(sem_trywait_nid_postfix(sem) == 0 && sem_trywait_nid_postfix(sem) == 0);
|
|
*__error_nid_postfix() = 0;
|
|
REQUIRE(sem_trywait_nid_postfix(sem) == -1 && *__error_nid_postfix() == GUEST_EAGAIN);
|
|
std::thread poster([name] {
|
|
void* other = sem_open_nid_postfix(name, 0);
|
|
REQUIRE(other != nullptr && sem_post_nid_postfix(other) == 0 && sem_close_nid_postfix(other) == 0);
|
|
});
|
|
REQUIRE(sem_wait_nid_postfix(sem) == 0);
|
|
poster.join();
|
|
REQUIRE(sem_post_nid_postfix(sem) == 0 && sem_post_nid_postfix(sem) == 0 && Value(sem) == 2);
|
|
*__error_nid_postfix() = 0;
|
|
REQUIRE(sem_destroy_nid_postfix(sem) == -1 && *__error_nid_postfix() == GUEST_EINVAL && Value(sem) == 2);
|
|
for (int open = 0; open < 3; ++open) REQUIRE(sem_close_nid_postfix(sem) == 0);
|
|
*__error_nid_postfix() = 0;
|
|
REQUIRE(sem_close_nid_postfix(sem) == -1 && *__error_nid_postfix() == GUEST_EINVAL);
|
|
|
|
void* reopened = sem_open_nid_postfix(name, 0);
|
|
REQUIRE(reopened != nullptr && Value(reopened) == 2);
|
|
REQUIRE(sem_unlink_nid_postfix(name) == 0);
|
|
REQUIRE(UnlinkFails(name, GUEST_ENOENT));
|
|
REQUIRE(OpenFails(name, 0, GUEST_ENOENT));
|
|
REQUIRE(sem_post_nid_postfix(reopened) == 0 && Value(reopened) == 3);
|
|
void* recreated = sem_open_nid_postfix(name, O_CREAT_FLAG | O_EXCL_FLAG, 0600, 5);
|
|
REQUIRE(recreated != nullptr && recreated != reopened && Value(recreated) == 5 && Value(reopened) == 3);
|
|
REQUIRE(sem_close_nid_postfix(reopened) == 0);
|
|
REQUIRE(sem_close_nid_postfix(recreated) == 0 && sem_unlink_nid_postfix(name) == 0);
|
|
}
|
|
|
|
static void CheckUnnamed() {
|
|
std::uintptr_t storage[2] = {};
|
|
REQUIRE(sem_init_nid_postfix(storage, 0, 1) == 0);
|
|
*__error_nid_postfix() = 0;
|
|
REQUIRE(sem_close_nid_postfix(storage) == -1 && *__error_nid_postfix() == GUEST_EINVAL);
|
|
REQUIRE(Value(storage) == 1 && sem_destroy_nid_postfix(storage) == 0);
|
|
REQUIRE(Throws([] { sem_close_nid_postfix(nullptr); }));
|
|
}
|
|
|
|
int main() {
|
|
CheckNames();
|
|
CheckLifetime();
|
|
CheckUnnamed();
|
|
return 0;
|
|
}
|