Skip to content
Open
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
7 changes: 7 additions & 0 deletions core/libs/prx/libkernel/File/src/Open.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ static int SceIoErrorFromErrno(int error) {
return static_cast<int>(0x80020000u | static_cast<unsigned>(guest));
}

static bool InvalidOpenFlags(int flags) {
constexpr int createExclusiveDirectory = SCE_KERNEL_O_CREAT | SCE_KERNEL_O_EXCL | SCE_KERNEL_O_DIRECTORY;
return (flags & SCE_KERNEL_O_ACCMODE) == SCE_KERNEL_O_ACCMODE || (flags & createExclusiveDirectory) == createExclusiveDirectory;
}

static int OpenNative(const std::filesystem::path& native, int flags, std::uint16_t mode) {
#ifdef _WIN32
if ((flags & (SCE_KERNEL_O_DIRECTORY | SCE_KERNEL_O_CREAT)) == SCE_KERNEL_O_DIRECTORY) {
Expand Down Expand Up @@ -211,6 +216,7 @@ static int OpenNative(const std::filesystem::path& native, int flags, std::uint1
extern "C" {

int APS5_VABI sceKernelOpen(const char* path, int flags, std::uint16_t mode) {
if (InvalidOpenFlags(flags)) return SCE_KERNEL_ERROR_EINVAL;
if (path != nullptr && *path == '\0') return SCE_KERNEL_ERROR_ENOENT;
APS5_LOG_OUT("path=%s flags=0x%X nativeFlags=0x%X mode=0%o", path, flags, MapFlags(flags), mode);
if (path != nullptr && File::IsRandomDevicePath(path)) {
Expand All @@ -227,6 +233,7 @@ int APS5_VABI sceKernelOpen(const char* path, int flags, std::uint16_t mode) {
}

int OpenInDirectory_nid_no_patch(int directory, const char* path, int flags, std::uint16_t mode) {
if (InvalidOpenFlags(flags)) return SCE_KERNEL_ERROR_EINVAL;
int error = 0;
const char* base = GetDirectoryDescriptorPath_nid_no_patch(directory, &error);
if (base == nullptr) return SceErrorFromErrno(error);
Expand Down
9 changes: 9 additions & 0 deletions core/libs/tests/GuestFilesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,15 @@ int main() {
Require(sceKernelOpen(presentName.c_str(), 0x20402, 0) == static_cast<int>(0x80020014u));
Require(std::filesystem::file_size(present) == 5);
Require(sceKernelOpen(missingName.c_str(), 0x20000, 0) == static_cast<int>(0x80020002u));
const auto invalidFlagsName = (root / "invalid-flags.txt").string();
Require(sceKernelOpen(presentName.c_str(), 3, 0) == static_cast<int>(0x80020016u));
Require(sceKernelOpen(missingName.c_str(), 0x203, 0600) == static_cast<int>(0x80020016u));
Require(open_nid_postfix(presentName.c_str(), 3, 0) == -1 && *__error_nid_postfix() == 22);
Require(_open_nid_postfix(presentName.c_str(), 0x403) == -1 && *__error_nid_postfix() == 22);
Require(sceKernelOpen(invalidFlagsName.c_str(), 0x20a02, 0600) == static_cast<int>(0x80020016u));
Require(open_nid_postfix(invalidFlagsName.c_str(), 0x20a00, 0600) == -1 && *__error_nid_postfix() == 22);
Require(!std::filesystem::exists(invalidFlagsName));
Require(std::filesystem::file_size(present) == 5);
Require(open_nid_postfix("", 0, 0) == -1 && *__error_nid_postfix() == 2);
Require(_open_nid_postfix("", 0) == -1 && *__error_nid_postfix() == 2);
Require(sceKernelOpen("", 0, 0) == static_cast<int>(0x80020002u));
Expand Down
2 changes: 2 additions & 0 deletions core/libs/tests/GuestKernelSys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,8 @@ int main() {
Require(sceKernelClose(made) == 0);
Require(openat_nid_postfix(base, "made.bin", SCE_KERNEL_O_WRONLY | SCE_KERNEL_O_CREAT | SCE_KERNEL_O_EXCL, 0644) == -1 && Error() == 17);
Require(openat_nid_postfix(base, "missing.bin", SCE_KERNEL_O_RDONLY) == -1 && Error() == 2);
Require(openat_nid_postfix(base, "file.txt", SCE_KERNEL_O_ACCMODE) == -1 && Error() == 22);
Require(openat_nid_postfix(base, "absent.bin", SCE_KERNEL_O_WRONLY | SCE_KERNEL_O_CREAT | SCE_KERNEL_O_EXCL | SCE_KERNEL_O_DIRECTORY, 0644) == -1 && Error() == 22);
const auto guestFile = "/" + root.filename().string() + "/file.txt";
const int absolute = openat_nid_postfix(-1, guestFile.c_str(), SCE_KERNEL_O_RDONLY);
Require(absolute >= 0 && sceKernelClose(absolute) == 0);
Expand Down
Loading