mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-25 20:25:38 -06:00
Cleanse
This commit is contained in:
parent
748d81b647
commit
98ec0d073e
@ -1,15 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "common/singleton.h"
|
||||
#include "core/file_sys/directories/base_directory.h"
|
||||
#include "core/file_sys/fs.h"
|
||||
|
||||
namespace Core::Directories {
|
||||
|
||||
BaseDirectory::BaseDirectory() = default;
|
||||
|
||||
BaseDirectory::~BaseDirectory() = default;
|
||||
|
||||
} // namespace Core::Directories
|
||||
@ -1,52 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include "common/types.h"
|
||||
#include "common/va_ctx.h"
|
||||
#include "core/libraries/kernel/file_system.h"
|
||||
#include "core/libraries/kernel/orbis_error.h"
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
struct OrbisKernelStat;
|
||||
struct OrbisKernelIovec;
|
||||
struct OrbisKernelDirent;
|
||||
} // namespace Libraries::Kernel
|
||||
|
||||
namespace Core::Directories {
|
||||
|
||||
class BaseDirectory {
|
||||
public:
|
||||
explicit BaseDirectory();
|
||||
|
||||
virtual ~BaseDirectory() = 0;
|
||||
|
||||
virtual s64 read(void* buf, u64 nbytes) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 lseek(s64 offset, s32 whence) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s32 fstat(Libraries::Kernel::OrbisKernelStat* stat) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 getdents(void* buf, u64 nbytes, s64* basep) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Core::Directories
|
||||
@ -1,140 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/singleton.h"
|
||||
#include "core/file_sys/directories/normal_directory.h"
|
||||
#include "core/file_sys/fs.h"
|
||||
|
||||
namespace Core::Directories {
|
||||
|
||||
std::shared_ptr<BaseDirectory> NormalDirectory::Create(std::string_view guest_directory) {
|
||||
return std::static_pointer_cast<BaseDirectory>(
|
||||
std::make_shared<NormalDirectory>(guest_directory));
|
||||
}
|
||||
|
||||
NormalDirectory::NormalDirectory(std::string_view guest_directory) {
|
||||
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
|
||||
|
||||
static s32 fileno = 0;
|
||||
mnt->IterateDirectory(guest_directory, [this](const auto& ent_path, const auto ent_is_file) {
|
||||
auto& dirent = dirents.emplace_back();
|
||||
dirent.d_fileno = ++fileno;
|
||||
dirent.d_type = (ent_is_file ? 8 : 4);
|
||||
strncpy(dirent.d_name, ent_path.filename().string().data(), MAX_LENGTH + 1);
|
||||
dirent.d_namlen = ent_path.filename().string().size();
|
||||
|
||||
// Calculate the appropriate length for this dirent.
|
||||
// Account for the null terminator in d_name too.
|
||||
dirent.d_reclen = Common::AlignUp(sizeof(dirent.d_fileno) + sizeof(dirent.d_type) +
|
||||
sizeof(dirent.d_namlen) + sizeof(dirent.d_reclen) +
|
||||
(dirent.d_namlen + 1),
|
||||
4);
|
||||
|
||||
directory_size += dirent.d_reclen;
|
||||
});
|
||||
|
||||
// The last entry of a normal directory should have d_reclen covering the remaining data.
|
||||
// Since the dirents of a folder are constant by this point, we can modify the last dirent
|
||||
// before creating the emulated file buffer.
|
||||
const u64 filler_count = Common::AlignUp(directory_size, DIRECTORY_ALIGNMENT) - directory_size;
|
||||
dirents[dirents.size() - 1].d_reclen += filler_count;
|
||||
|
||||
// Reading from standard directories seems to be based around file pointer logic.
|
||||
// Keep an internal buffer representing the raw contents of this file descriptor,
|
||||
// then emulate the various read functions with that.
|
||||
directory_size = Common::AlignUp(directory_size, DIRECTORY_ALIGNMENT);
|
||||
data_buffer.reserve(directory_size);
|
||||
memset(data_buffer.data(), 0, directory_size);
|
||||
|
||||
u8* current_dirent = data_buffer.data();
|
||||
for (const NormalDirectoryDirent& dirent : dirents) {
|
||||
NormalDirectoryDirent* dirent_to_write =
|
||||
reinterpret_cast<NormalDirectoryDirent*>(current_dirent);
|
||||
dirent_to_write->d_fileno = dirent.d_fileno;
|
||||
|
||||
// Using size d_namlen + 1 to account for null terminator.
|
||||
strncpy(dirent_to_write->d_name, dirent.d_name, dirent.d_namlen + 1);
|
||||
dirent_to_write->d_namlen = dirent.d_namlen;
|
||||
dirent_to_write->d_reclen = dirent.d_reclen;
|
||||
dirent_to_write->d_type = dirent.d_type;
|
||||
|
||||
current_dirent += dirent.d_reclen;
|
||||
}
|
||||
}
|
||||
|
||||
s64 NormalDirectory::read(void* buf, u64 nbytes) {
|
||||
// Nothing left to read.
|
||||
if (file_offset >= directory_size) {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
const s64 remaining_data = directory_size - file_offset;
|
||||
const s64 bytes = nbytes > remaining_data ? remaining_data : nbytes;
|
||||
|
||||
std::memcpy(buf, data_buffer.data() + file_offset, bytes);
|
||||
|
||||
file_offset += bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
s64 NormalDirectory::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
s64 bytes_read = 0;
|
||||
for (s32 i = 0; i < iovcnt; i++) {
|
||||
const s64 result = read(iov[i].iov_base, iov[i].iov_len);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
bytes_read += result;
|
||||
}
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
s64 NormalDirectory::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt,
|
||||
s64 offset) {
|
||||
const u64 old_file_pointer = file_offset;
|
||||
file_offset = offset;
|
||||
const s64 bytes_read = readv(iov, iovcnt);
|
||||
file_offset = old_file_pointer;
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
s64 NormalDirectory::lseek(s64 offset, s32 whence) {
|
||||
switch (whence) {
|
||||
case 0: {
|
||||
file_offset = offset;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
file_offset += offset;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
file_offset = directory_size + offset;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
UNREACHABLE_MSG("lseek with unknown whence {}", whence);
|
||||
}
|
||||
}
|
||||
return file_offset;
|
||||
}
|
||||
|
||||
s32 NormalDirectory::fstat(Libraries::Kernel::OrbisKernelStat* stat) {
|
||||
stat->st_mode = 0000777u | 0040000u;
|
||||
stat->st_size = directory_size;
|
||||
stat->st_blksize = 0x8000;
|
||||
stat->st_blocks = 8;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s64 NormalDirectory::getdents(void* buf, u64 nbytes, s64* basep) {
|
||||
if (basep != nullptr) {
|
||||
*basep = file_offset;
|
||||
}
|
||||
// read behaves identically to getdents for normal directories.
|
||||
return read(buf, nbytes);
|
||||
}
|
||||
} // namespace Core::Directories
|
||||
@ -1,45 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include "common/types.h"
|
||||
#include "core/file_sys/directories/base_directory.h"
|
||||
#include "core/libraries/kernel/orbis_error.h"
|
||||
|
||||
namespace Core::Directories {
|
||||
|
||||
class NormalDirectory final : public BaseDirectory {
|
||||
public:
|
||||
static std::shared_ptr<BaseDirectory> Create(std::string_view guest_path);
|
||||
explicit NormalDirectory(std::string_view guest_path);
|
||||
~NormalDirectory() override = default;
|
||||
|
||||
virtual s64 read(void* buf, u64 count) override;
|
||||
virtual s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
virtual s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt,
|
||||
s64 offset) override;
|
||||
virtual s64 lseek(s64 offset, s32 whence) override;
|
||||
virtual s32 fstat(Libraries::Kernel::OrbisKernelStat* stat) override;
|
||||
virtual s64 getdents(void* buf, u64 count, s64* basep) override;
|
||||
|
||||
private:
|
||||
static constexpr s32 MAX_LENGTH = 255;
|
||||
static constexpr s64 DIRECTORY_ALIGNMENT = 0x200;
|
||||
struct NormalDirectoryDirent {
|
||||
u32 d_fileno;
|
||||
u16 d_reclen;
|
||||
u8 d_type;
|
||||
u8 d_namlen;
|
||||
char d_name[MAX_LENGTH + 1];
|
||||
};
|
||||
|
||||
u64 directory_size = 0;
|
||||
s64 file_offset = 0;
|
||||
std::vector<u8> data_buffer;
|
||||
std::vector<NormalDirectoryDirent> dirents;
|
||||
};
|
||||
} // namespace Core::Directories
|
||||
@ -1,220 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/singleton.h"
|
||||
#include "core/file_sys/directories/pfs_directory.h"
|
||||
#include "core/file_sys/fs.h"
|
||||
|
||||
namespace Core::Directories {
|
||||
|
||||
std::shared_ptr<BaseDirectory> PfsDirectory::Create(std::string_view guest_directory) {
|
||||
return std::static_pointer_cast<BaseDirectory>(std::make_shared<PfsDirectory>(guest_directory));
|
||||
}
|
||||
|
||||
PfsDirectory::PfsDirectory(std::string_view guest_directory) {
|
||||
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
|
||||
|
||||
static s32 fileno = 0;
|
||||
mnt->IterateDirectory(guest_directory, [this](const auto& ent_path, const auto ent_is_file) {
|
||||
auto& dirent = dirents.emplace_back();
|
||||
dirent.d_fileno = ++fileno;
|
||||
dirent.d_type = (ent_is_file ? 8 : 4);
|
||||
strncpy(dirent.d_name, ent_path.filename().string().data(), MAX_LENGTH + 1);
|
||||
dirent.d_namlen = ent_path.filename().string().size();
|
||||
|
||||
// Calculate the appropriate length for this dirent.
|
||||
// Account for the null terminator in d_name too.
|
||||
dirent.d_reclen = Common::AlignUp(sizeof(dirent.d_fileno) + sizeof(dirent.d_type) +
|
||||
sizeof(dirent.d_namlen) + sizeof(dirent.d_reclen) +
|
||||
(dirent.d_namlen + 1),
|
||||
8);
|
||||
|
||||
// To handle some obscure dirents_index behavior,
|
||||
// keep track of the "actual" length of this directory.
|
||||
directory_content_size += dirent.d_reclen;
|
||||
});
|
||||
|
||||
directory_size = Common::AlignUp(directory_content_size, DIRECTORY_ALIGNMENT);
|
||||
}
|
||||
|
||||
s64 PfsDirectory::read(void* buf, u64 nbytes) {
|
||||
if (dirents_index >= dirents.size()) {
|
||||
if (dirents_index < directory_content_size) {
|
||||
// We need to find the appropriate dirents_index to start from.
|
||||
s64 data_to_skip = dirents_index;
|
||||
u64 corrected_index = 0;
|
||||
while (data_to_skip > 0) {
|
||||
const auto dirent = dirents[corrected_index++];
|
||||
data_to_skip -= dirent.d_reclen;
|
||||
}
|
||||
dirents_index = corrected_index;
|
||||
} else {
|
||||
// Nothing left to read.
|
||||
return ORBIS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
s64 bytes_remaining = nbytes > directory_size ? directory_size : nbytes;
|
||||
// read on PfsDirectories will always return the maximum possible value.
|
||||
const u64 bytes_written = bytes_remaining;
|
||||
memset(buf, 0, bytes_remaining);
|
||||
|
||||
char* current_dirent = static_cast<char*>(buf);
|
||||
PfsDirectoryDirent dirent = dirents[dirents_index];
|
||||
while (bytes_remaining > dirent.d_reclen) {
|
||||
PfsDirectoryDirent* dirent_to_write = reinterpret_cast<PfsDirectoryDirent*>(current_dirent);
|
||||
dirent_to_write->d_fileno = dirent.d_fileno;
|
||||
|
||||
// Using size d_namlen + 1 to account for null terminator.
|
||||
strncpy(dirent_to_write->d_name, dirent.d_name, dirent.d_namlen + 1);
|
||||
dirent_to_write->d_namlen = dirent.d_namlen;
|
||||
dirent_to_write->d_reclen = dirent.d_reclen;
|
||||
dirent_to_write->d_type = dirent.d_type;
|
||||
|
||||
current_dirent += dirent.d_reclen;
|
||||
bytes_remaining -= dirent.d_reclen;
|
||||
|
||||
if (dirents_index == dirents.size() - 1) {
|
||||
// Currently at the last dirent, so break out of the loop.
|
||||
dirents_index++;
|
||||
break;
|
||||
}
|
||||
dirent = dirents[++dirents_index];
|
||||
}
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
s64 PfsDirectory::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
s64 bytes_read = 0;
|
||||
for (s32 i = 0; i < iovcnt; i++) {
|
||||
const s64 result = read(iov[i].iov_base, iov[i].iov_len);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
bytes_read += result;
|
||||
}
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
s64 PfsDirectory::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||
const u64 old_dirent_index = dirents_index;
|
||||
dirents_index = 0;
|
||||
s64 data_to_skip = offset;
|
||||
// If offset is part-way through one dirent, that dirent is skipped.
|
||||
while (data_to_skip > 0) {
|
||||
const auto dirent = dirents[dirents_index++];
|
||||
data_to_skip -= dirent.d_reclen;
|
||||
if (dirents_index == dirents.size()) {
|
||||
// We've reached the end of the dirents, nothing more can be skipped.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const s64 bytes_read = readv(iov, iovcnt);
|
||||
dirents_index = old_dirent_index;
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
s64 PfsDirectory::lseek(s64 offset, s32 whence) {
|
||||
switch (whence) {
|
||||
// Seek start
|
||||
case 0: {
|
||||
dirents_index = 0;
|
||||
}
|
||||
case 1: {
|
||||
// There aren't any dirents left to pass through.
|
||||
if (dirents_index >= dirents.size()) {
|
||||
dirents_index = dirents_index + offset;
|
||||
break;
|
||||
}
|
||||
s64 data_to_skip = offset;
|
||||
while (data_to_skip > 0) {
|
||||
const auto dirent = dirents[dirents_index++];
|
||||
data_to_skip -= dirent.d_reclen;
|
||||
if (dirents_index == dirents.size()) {
|
||||
// We've passed through all file dirents.
|
||||
// Set dirents_index to directory_size + remaining_offset instead.
|
||||
dirents_index = directory_content_size + data_to_skip;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// Seems like real hardware gives up on tracking dirents_index if you go this route.
|
||||
dirents_index = directory_size + offset;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
UNREACHABLE_MSG("lseek with unknown whence {}", whence);
|
||||
}
|
||||
}
|
||||
|
||||
return dirents_index;
|
||||
}
|
||||
|
||||
s32 PfsDirectory::fstat(Libraries::Kernel::OrbisKernelStat* stat) {
|
||||
stat->st_mode = 0000777u | 0040000u;
|
||||
stat->st_size = directory_size;
|
||||
stat->st_blksize = 0x10000;
|
||||
stat->st_blocks = 0x80;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s64 PfsDirectory::getdents(void* buf, u64 nbytes, s64* basep) {
|
||||
// basep is set at the start of the function.
|
||||
if (basep != nullptr) {
|
||||
*basep = dirents_index;
|
||||
}
|
||||
|
||||
if (dirents_index >= dirents.size()) {
|
||||
if (dirents_index < directory_content_size) {
|
||||
// We need to find the appropriate dirents_index to start from.
|
||||
s64 data_to_skip = dirents_index;
|
||||
u64 corrected_index = 0;
|
||||
while (data_to_skip > 0) {
|
||||
const auto dirent = dirents[corrected_index++];
|
||||
data_to_skip -= dirent.d_reclen;
|
||||
}
|
||||
dirents_index = corrected_index;
|
||||
} else {
|
||||
// Nothing left to read.
|
||||
return ORBIS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
s64 bytes_remaining = nbytes > directory_size ? directory_size : nbytes;
|
||||
memset(buf, 0, bytes_remaining);
|
||||
|
||||
u64 bytes_written = 0;
|
||||
char* current_dirent = static_cast<char*>(buf);
|
||||
// getdents has to convert pfs dirents to normal dirents
|
||||
PfsDirectoryDirent dirent = dirents[dirents_index];
|
||||
while (bytes_remaining > dirent.d_reclen) {
|
||||
NormalDirectoryDirent* dirent_to_write =
|
||||
reinterpret_cast<NormalDirectoryDirent*>(current_dirent);
|
||||
dirent_to_write->d_fileno = dirent.d_fileno;
|
||||
strncpy(dirent_to_write->d_name, dirent.d_name, dirent.d_namlen + 1);
|
||||
dirent_to_write->d_namlen = dirent.d_namlen;
|
||||
dirent_to_write->d_reclen = dirent.d_reclen;
|
||||
dirent_to_write->d_type = dirent.d_type;
|
||||
|
||||
current_dirent += dirent.d_reclen;
|
||||
bytes_remaining -= dirent.d_reclen;
|
||||
bytes_written += dirent.d_reclen;
|
||||
|
||||
if (dirents_index == dirents.size() - 1) {
|
||||
// Currently at the last dirent, so set dirents_index appropriately and break.
|
||||
dirents_index = directory_size;
|
||||
break;
|
||||
}
|
||||
dirent = dirents[++dirents_index];
|
||||
}
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
} // namespace Core::Directories
|
||||
@ -1,53 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include "common/types.h"
|
||||
#include "core/file_sys/directories/base_directory.h"
|
||||
#include "core/libraries/kernel/orbis_error.h"
|
||||
|
||||
namespace Core::Directories {
|
||||
|
||||
class PfsDirectory final : public BaseDirectory {
|
||||
public:
|
||||
static std::shared_ptr<BaseDirectory> Create(std::string_view guest_path);
|
||||
explicit PfsDirectory(std::string_view guest_path);
|
||||
~PfsDirectory() override = default;
|
||||
|
||||
virtual s64 read(void* buf, u64 nbytes) override;
|
||||
virtual s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
virtual s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt,
|
||||
s64 offset) override;
|
||||
virtual s64 lseek(s64 offset, s32 whence) override;
|
||||
virtual s32 fstat(Libraries::Kernel::OrbisKernelStat* stat) override;
|
||||
virtual s64 getdents(void* buf, u64 nbytes, s64* basep) override;
|
||||
|
||||
private:
|
||||
static constexpr s32 MAX_LENGTH = 255;
|
||||
static constexpr s32 DIRECTORY_ALIGNMENT = 0x10000;
|
||||
struct PfsDirectoryDirent {
|
||||
u32 d_fileno;
|
||||
u32 d_type;
|
||||
u32 d_namlen;
|
||||
u32 d_reclen;
|
||||
char d_name[MAX_LENGTH + 1];
|
||||
};
|
||||
|
||||
struct NormalDirectoryDirent {
|
||||
u32 d_fileno;
|
||||
u16 d_reclen;
|
||||
u8 d_type;
|
||||
u8 d_namlen;
|
||||
char d_name[MAX_LENGTH + 1];
|
||||
};
|
||||
|
||||
u64 directory_size = 0;
|
||||
u64 directory_content_size = 0;
|
||||
s64 dirents_index = 0;
|
||||
std::vector<PfsDirectoryDirent> dirents;
|
||||
};
|
||||
} // namespace Core::Directories
|
||||
@ -10,7 +10,6 @@
|
||||
#include <tsl/robin_map.h>
|
||||
#include "common/io_file.h"
|
||||
#include "common/logging/formatter.h"
|
||||
#include "core/file_sys/directories/base_directory.h"
|
||||
|
||||
namespace Libraries::Net {
|
||||
struct Socket;
|
||||
|
||||
@ -18,8 +18,6 @@
|
||||
#include "core/file_sys/devices/random_device.h"
|
||||
#include "core/file_sys/devices/rng_device.h"
|
||||
#include "core/file_sys/devices/srandom_device.h"
|
||||
#include "core/file_sys/directories/normal_directory.h"
|
||||
#include "core/file_sys/directories/pfs_directory.h"
|
||||
#include "core/file_sys/fs.h"
|
||||
|
||||
#include "core/libraries/kernel/file_system.h"
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/config.h"
|
||||
#include "common/debug.h"
|
||||
#include "core/file_sys/fs.h"
|
||||
#include "core/file_sys/quasifs/quasifs.h"
|
||||
#include "core/libraries/kernel/memory.h"
|
||||
#include "core/libraries/kernel/orbis_error.h"
|
||||
#include "core/libraries/kernel/process.h"
|
||||
@ -555,14 +555,19 @@ s32 MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, u64 size, Memory
|
||||
}
|
||||
|
||||
// Get the file to map
|
||||
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||
auto file = h->GetFile(fd);
|
||||
if (file == nullptr) {
|
||||
auto* qfs = Common::Singleton<QuasiFS::QFS>::Instance();
|
||||
auto file = qfs->GetHandle(fd);
|
||||
|
||||
if (nullptr == file) {
|
||||
LOG_WARNING(Kernel_Vmm, "Invalid file for mmap, fd {}", fd);
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
if (file->type != Core::FileSys::FileType::Regular) {
|
||||
if (nullptr == file->node) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
if (!file->node->is_file()) {
|
||||
LOG_WARNING(Kernel_Vmm, "Unsupported file type for mmap, fd {}", fd);
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
@ -572,10 +577,14 @@ s32 MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, u64 size, Memory
|
||||
prot |= MemoryProt::CpuRead;
|
||||
}
|
||||
|
||||
const auto handle = file->f.GetFileMapping();
|
||||
const auto handle = file->host_fd;
|
||||
|
||||
if (False(file->f.GetAccessMode() & Common::FS::FileAccessMode::Write) ||
|
||||
False(file->f.GetAccessMode() & Common::FS::FileAccessMode::Append)) {
|
||||
if (handle < 0) {
|
||||
LOG_CRITICAL(Kernel_Vmm, "Descriptor does not have host-bound file associated for mmap");
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
if (0 == (file->write | file->append)) {
|
||||
// If the file does not have write access, ensure prot does not contain write permissions.
|
||||
// On real hardware, these mappings succeed, but the memory cannot be written to.
|
||||
prot &= ~MemoryProt::CpuWrite;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user