mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-22 08:33:12 -05:00
guest_directory_close expected ENOTDIR from getdents on a descriptor number reused by a regular file, and guest_directory_buffer expected ENOTDIR for descriptor -1. kern_getdirentries returns EINVAL for a vnode that is not a directory and getvnode returns EBADF for a descriptor that is not open, which is what sceKernelGetdirentries now reports on Windows. Written with AI assistance (Claude). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
67 lines
2.2 KiB
C++
67 lines
2.2 KiB
C++
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include "prx/libkernel/File/include/FileFlags.hpp"
|
|
|
|
#include <array>
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <string>
|
|
|
|
extern "C" {
|
|
int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t);
|
|
int APS5_VABI sceKernelGetdents(int, char*, int);
|
|
int APS5_VABI close_nid_postfix(int);
|
|
int APS5_VABI _close_nid_postfix(int);
|
|
}
|
|
|
|
static void Check(bool value, int line) {
|
|
if (!value) {
|
|
std::fprintf(stderr, "Directory close check failed at line %d\n", line);
|
|
std::abort();
|
|
}
|
|
}
|
|
#define Require(value) Check((value), __LINE__)
|
|
|
|
static constexpr int ErrorEinval = static_cast<int>(0x80020016u);
|
|
|
|
static void VerifyCloseReuse(const std::filesystem::path& root, const char* scenario,
|
|
bool useUnderscoreClose) {
|
|
const auto directoryPath = root / scenario;
|
|
Require(std::filesystem::create_directory(directoryPath));
|
|
const auto filePath = directoryPath / "entry.txt";
|
|
{
|
|
std::ofstream file(filePath, std::ios::binary);
|
|
Require(file.is_open());
|
|
file << "entry";
|
|
Require(static_cast<bool>(file));
|
|
}
|
|
|
|
const int directory = sceKernelOpen(directoryPath.string().c_str(),
|
|
SCE_KERNEL_O_RDONLY | SCE_KERNEL_O_DIRECTORY, 0);
|
|
Require(directory >= 0);
|
|
Require((useUnderscoreClose ? _close_nid_postfix(directory) : close_nid_postfix(directory)) == 0);
|
|
|
|
const int file = sceKernelOpen(filePath.string().c_str(), SCE_KERNEL_O_RDONLY, 0);
|
|
Require(file >= 0);
|
|
Require(file == directory);
|
|
|
|
std::array<char, 256> entries{};
|
|
Require(sceKernelGetdents(file, entries.data(), static_cast<int>(entries.size())) == ErrorEinval);
|
|
Require((useUnderscoreClose ? _close_nid_postfix(file) : close_nid_postfix(file)) == 0);
|
|
}
|
|
|
|
int main() {
|
|
const auto root = std::filesystem::temp_directory_path() /
|
|
("anyps5-directory-close-" +
|
|
std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()));
|
|
Require(std::filesystem::create_directory(root));
|
|
|
|
VerifyCloseReuse(root, "close", false);
|
|
VerifyCloseReuse(root, "underscore-close", true);
|
|
|
|
std::filesystem::remove_all(root);
|
|
}
|