mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-21 16:12:47 -05:00
81 lines
2.6 KiB
C++
81 lines
2.6 KiB
C++
#include "prx/libc/include/General.hpp"
|
|
#include "prx/libc/include/Shutdown.hpp"
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <exception>
|
|
#include <filesystem>
|
|
#include <thread>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
extern "C" char* APS5_VABI getcwd_nid_postfix(char*, std::size_t);
|
|
|
|
namespace {
|
|
|
|
int events[2];
|
|
char expectedRoot[4096];
|
|
|
|
void CheckPathsDuringExit() {
|
|
bool passed = false;
|
|
try {
|
|
std::thread worker([&] {
|
|
try {
|
|
const std::filesystem::path root(expectedRoot);
|
|
char cwd[32] = {};
|
|
passed = getcwd_nid_postfix(cwd, sizeof(cwd)) == cwd &&
|
|
std::strcmp(cwd, "/") == 0 &&
|
|
ResolvePath_nid_no_patch(".").lexically_relative(root) == "." &&
|
|
ResolvePath_nid_no_patch("/").lexically_relative(root) == "." &&
|
|
ResolvePath_nid_no_patch("/lifetime_alias") == root;
|
|
RemovePathAlias_nid_no_patch("/lifetime_alias");
|
|
AddPathAlias_nid_no_patch("/lifetime_alias", expectedRoot);
|
|
passed = passed && ResolvePath_nid_no_patch("/lifetime_alias") == root;
|
|
} catch (const std::exception& error) {
|
|
std::fprintf(stderr, "path services during exit: %s\n", error.what());
|
|
passed = false;
|
|
} catch (...) { passed = false; }
|
|
});
|
|
worker.join();
|
|
} catch (...) { passed = false; }
|
|
const char result = passed ? 'P' : 'F';
|
|
static_cast<void>(!write(events[1], &result, 1));
|
|
}
|
|
|
|
bool PathsSurviveExit() {
|
|
if (pipe(events) != 0) return false;
|
|
const pid_t child = fork();
|
|
if (child < 0) {
|
|
close(events[0]);
|
|
close(events[1]);
|
|
return false;
|
|
}
|
|
if (child == 0) {
|
|
close(events[0]);
|
|
const auto root = std::filesystem::canonical(std::filesystem::current_path()).string();
|
|
if (root.size() >= sizeof(expectedRoot)) std::_Exit(2);
|
|
std::memcpy(expectedRoot, root.c_str(), root.size() + 1);
|
|
if (std::atexit(CheckPathsDuringExit) != 0) std::_Exit(2);
|
|
ResolvePath_nid_no_patch("/");
|
|
AddPathAlias_nid_no_patch("/lifetime_alias", expectedRoot);
|
|
LibcExit_nid_no_patch(0);
|
|
}
|
|
close(events[1]);
|
|
char result = 0;
|
|
const ssize_t count = read(events[0], &result, 1);
|
|
close(events[0]);
|
|
int status = 0;
|
|
return waitpid(child, &status, 0) == child && WIFEXITED(status) &&
|
|
WEXITSTATUS(status) == 0 && count == 1 && result == 'P';
|
|
}
|
|
|
|
}
|
|
|
|
int main() {
|
|
if (!PathsSurviveExit()) {
|
|
std::fputs("guest path services must remain available during process exit\n", stderr);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|