mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-12 14:48:52 +00:00
Core: Simulate write-only file access with read-write access (#3360)
* Swap write access mode for read write Opening with access mode w will erase the opened file. We do not want this. * Create mode Opening with write access was previously the only way to create a file through open, so add a separate FileAccessMode that uses the write access mode to create files. * Update file_system.cpp Remove a hack added to posix_rename to bypass the file clearing behaviors of FileAccessMode::Write * Check access mode in read functions Write-only files cause the EBADF return on the various read functions. Now that we're opening files differently, properly handling this is necessary. * Separate appends into proper modes Fixes a potential regression from one of my prior PRs, and ensures the Write | Append flag combo also behaves properly in read-related functions. * Move IsWriteOnly check after device/socket reads file->f is only valid for files, so checking this before checking for sockets/devices will cause access violations. * Fix issues Now that Write is identical to ReadWrite, internal uses of Write need to be swapped to my new Create mode * Fix remaining uses of FileAccessMode write to create files Missed these before. * Fix rebase * Add stubbed get_authinfo (#3722) * mostly stubbed get_authinfo * Return value observed on console if get_authinfo was called for the current thread, esrch otherwise --------- Co-authored-by: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Co-authored-by: georgemoralis <giorgosmrls@gmail.com>
This commit is contained in:
@@ -152,7 +152,7 @@ inline std::string RunDisassembler(const std::string& disassembler_cli, const T&
|
||||
}
|
||||
} else {
|
||||
cli.replace(pos, src_arg.size(), "\"" + bin_path.string() + "\"");
|
||||
Common::FS::IOFile file(bin_path, Common::FS::FileAccessMode::Write);
|
||||
Common::FS::IOFile file(bin_path, Common::FS::FileAccessMode::Create);
|
||||
file.Write(shader_code);
|
||||
file.Close();
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ void FrameDumpViewer::Draw() {
|
||||
const auto fname = fmt::format("{:%F %H-%M-%S} {}_{}_{}.bin", now_time,
|
||||
magic_enum::enum_name(selected_queue_type),
|
||||
selected_submit_num, selected_queue_num2);
|
||||
Common::FS::IOFile file(fname, Common::FS::FileAccessMode::Write);
|
||||
Common::FS::IOFile file(fname, Common::FS::FileAccessMode::Create);
|
||||
const auto& data = frame_dump->queues[selected_cmd].data;
|
||||
if (file.IsOpen()) {
|
||||
DebugState.ShowDebugMessage(fmt::format("Dumping cmd as {}", fname));
|
||||
|
||||
@@ -99,7 +99,7 @@ bool PSF::Open(const std::vector<u8>& psf_buffer) {
|
||||
}
|
||||
|
||||
bool PSF::Encode(const std::filesystem::path& filepath) const {
|
||||
Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Write);
|
||||
Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Create);
|
||||
if (!file.IsOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) {
|
||||
return -1;
|
||||
}
|
||||
// Create a file if it doesn't exist
|
||||
Common::FS::IOFile out(file->m_host_name, Common::FS::FileAccessMode::Write);
|
||||
Common::FS::IOFile out(file->m_host_name, Common::FS::FileAccessMode::Create);
|
||||
}
|
||||
} else if (!exists) {
|
||||
// If we're not creating a file, and it doesn't exist, return ENOENT
|
||||
@@ -205,22 +205,30 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) {
|
||||
}
|
||||
|
||||
if (read) {
|
||||
// Read only
|
||||
// Open exclusively for reading
|
||||
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Read);
|
||||
} else if (read_only) {
|
||||
// Can't open files with write/read-write access in a read only directory
|
||||
h->DeleteHandle(handle);
|
||||
*__Error() = POSIX_EROFS;
|
||||
return -1;
|
||||
} else if (append) {
|
||||
// Append can be specified with rdwr or write, but we treat it as a separate mode.
|
||||
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Append);
|
||||
} else if (write) {
|
||||
// Write only
|
||||
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Write);
|
||||
if (append) {
|
||||
// Open exclusively for appending
|
||||
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Append);
|
||||
} else {
|
||||
// Open exclusively for writing
|
||||
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Write);
|
||||
}
|
||||
} else if (rdwr) {
|
||||
// Read and write
|
||||
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::ReadWrite);
|
||||
if (append) {
|
||||
// Open for reading and appending
|
||||
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::ReadAppend);
|
||||
} else {
|
||||
// Open for reading and writing
|
||||
e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::ReadWrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,6 +362,12 @@ s64 PS4_SYSV_ABI readv(s32 fd, const OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (file->f.IsWriteOnly()) {
|
||||
*__Error() = POSIX_EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
s64 total_read = 0;
|
||||
for (s32 i = 0; i < iovcnt; i++) {
|
||||
total_read += ReadFile(file->f, iov[i].iov_base, iov[i].iov_len);
|
||||
@@ -509,6 +523,12 @@ s64 PS4_SYSV_ABI read(s32 fd, void* buf, u64 nbytes) {
|
||||
// Socket functions handle errnos internally.
|
||||
return file->socket->ReceivePacket(buf, nbytes, 0, nullptr, 0);
|
||||
}
|
||||
|
||||
if (file->f.IsWriteOnly()) {
|
||||
*__Error() = POSIX_EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ReadFile(file->f, buf, nbytes);
|
||||
}
|
||||
|
||||
@@ -801,11 +821,7 @@ s32 PS4_SYSV_ABI posix_rename(const char* from, const char* to) {
|
||||
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||
auto file = h->GetFile(src_path);
|
||||
if (file) {
|
||||
// We need to force ReadWrite if the file had Write access before
|
||||
// Otherwise f.Open will clear the file contents.
|
||||
auto access_mode = file->f.GetAccessMode() == Common::FS::FileAccessMode::Write
|
||||
? Common::FS::FileAccessMode::ReadWrite
|
||||
: file->f.GetAccessMode();
|
||||
auto access_mode = file->f.GetAccessMode();
|
||||
file->f.Close();
|
||||
std::filesystem::remove(src_path);
|
||||
file->f.Open(dst_path, access_mode);
|
||||
@@ -855,6 +871,11 @@ s64 PS4_SYSV_ABI posix_preadv(s32 fd, OrbisKernelIovec* iov, s32 iovcnt, s64 off
|
||||
return result;
|
||||
}
|
||||
|
||||
if (file->f.IsWriteOnly()) {
|
||||
*__Error() = POSIX_EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const s64 pos = file->f.Tell();
|
||||
SCOPE_EXIT {
|
||||
file->f.Seek(pos);
|
||||
|
||||
@@ -180,7 +180,7 @@ void SaveInstance::SetupAndMount(bool read_only, bool copy_icon, bool ignore_cor
|
||||
}
|
||||
|
||||
if (!ignore_corrupt && !read_only) {
|
||||
Common::FS::IOFile f(corrupt_file_path, Common::FS::FileAccessMode::Write);
|
||||
Common::FS::IOFile f(corrupt_file_path, Common::FS::FileAccessMode::Create);
|
||||
f.Close();
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ void PersistMemory(u32 slot_id, bool lock) {
|
||||
while (n++ < 10) {
|
||||
try {
|
||||
IOFile f;
|
||||
int r = f.Open(memoryPath, Common::FS::FileAccessMode::Write);
|
||||
int r = f.Open(memoryPath, Common::FS::FileAccessMode::Create);
|
||||
if (f.IsOpen()) {
|
||||
f.WriteRaw<u8>(data.memory_cache.data(), data.memory_cache.size());
|
||||
f.Close();
|
||||
@@ -148,7 +148,7 @@ void SetIcon(u32 slot_id, void* buf, size_t buf_size) {
|
||||
fs::copy_file(src_icon, icon_path);
|
||||
}
|
||||
} else {
|
||||
IOFile file(icon_path, Common::FS::FileAccessMode::Write);
|
||||
IOFile file(icon_path, Common::FS::FileAccessMode::Create);
|
||||
file.WriteRaw<u8>(buf, buf_size);
|
||||
file.Close();
|
||||
}
|
||||
|
||||
@@ -1389,7 +1389,7 @@ Error PS4_SYSV_ABI sceSaveDataSaveIcon(const OrbisSaveDataMountPoint* mountPoint
|
||||
}
|
||||
|
||||
try {
|
||||
const Common::FS::IOFile file(path, Common::FS::FileAccessMode::Write);
|
||||
const Common::FS::IOFile file(path, Common::FS::FileAccessMode::Create);
|
||||
file.WriteRaw<u8>(icon->buf, std::min(icon->bufSize, icon->dataSize));
|
||||
} catch (const fs::filesystem_error& e) {
|
||||
LOG_ERROR(Lib_SaveData, "Failed to load icon: {}", e.what());
|
||||
|
||||
@@ -502,19 +502,19 @@ bool Elf::IsSharedLib() {
|
||||
}
|
||||
|
||||
void Elf::ElfHeaderDebugDump(const std::filesystem::path& file_name) {
|
||||
Common::FS::IOFile f{file_name, Common::FS::FileAccessMode::Write,
|
||||
Common::FS::IOFile f{file_name, Common::FS::FileAccessMode::Create,
|
||||
Common::FS::FileType::TextFile};
|
||||
f.WriteString(ElfHeaderStr());
|
||||
}
|
||||
|
||||
void Elf::SelfHeaderDebugDump(const std::filesystem::path& file_name) {
|
||||
Common::FS::IOFile f{file_name, Common::FS::FileAccessMode::Write,
|
||||
Common::FS::IOFile f{file_name, Common::FS::FileAccessMode::Create,
|
||||
Common::FS::FileType::TextFile};
|
||||
f.WriteString(SElfHeaderStr());
|
||||
}
|
||||
|
||||
void Elf::SelfSegHeaderDebugDump(const std::filesystem::path& file_name) {
|
||||
Common::FS::IOFile f{file_name, Common::FS::FileAccessMode::Write,
|
||||
Common::FS::IOFile f{file_name, Common::FS::FileAccessMode::Create,
|
||||
Common::FS::FileType::TextFile};
|
||||
for (u16 i = 0; i < m_self.segment_count; i++) {
|
||||
f.WriteString(SELFSegHeader(i));
|
||||
@@ -522,7 +522,7 @@ void Elf::SelfSegHeaderDebugDump(const std::filesystem::path& file_name) {
|
||||
}
|
||||
|
||||
void Elf::PHeaderDebugDump(const std::filesystem::path& file_name) {
|
||||
Common::FS::IOFile f{file_name, Common::FS::FileAccessMode::Write,
|
||||
Common::FS::IOFile f{file_name, Common::FS::FileAccessMode::Create,
|
||||
Common::FS::FileType::TextFile};
|
||||
if (m_elf_header.e_phentsize > 0) {
|
||||
for (u16 i = 0; i < m_elf_header.e_phnum; i++) {
|
||||
|
||||
@@ -32,7 +32,7 @@ const SymbolRecord* SymbolsResolver::FindSymbol(const SymbolResolver& s) const {
|
||||
}
|
||||
|
||||
void SymbolsResolver::DebugDump(const std::filesystem::path& file_name) {
|
||||
Common::FS::IOFile f{file_name, Common::FS::FileAccessMode::Write,
|
||||
Common::FS::IOFile f{file_name, Common::FS::FileAccessMode::Create,
|
||||
Common::FS::FileType::TextFile};
|
||||
for (const auto& symbol : m_symbols) {
|
||||
const auto ids = Common::SplitString(symbol.name, '#');
|
||||
|
||||
Reference in New Issue
Block a user