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
20 changes: 12 additions & 8 deletions src/common/io_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,28 +40,30 @@ namespace {
switch (mode) {
case FileAccessMode::Read:
return L"rb";
case FileAccessMode::Write:
return L"wb";
case FileAccessMode::Append:
return L"ab";
case FileAccessMode::Write:
case FileAccessMode::ReadWrite:
return L"r+b";
case FileAccessMode::ReadAppend:
return L"a+b";
case FileAccessMode::Create:
return L"wb";
}
break;
case FileType::TextFile:
switch (mode) {
case FileAccessMode::Read:
return L"r";
case FileAccessMode::Write:
return L"w";
case FileAccessMode::Append:
return L"a";
case FileAccessMode::Write:
case FileAccessMode::ReadWrite:
return L"r+";
case FileAccessMode::ReadAppend:
return L"a+";
case FileAccessMode::Create:
return L"w";
}
break;
}
Expand Down Expand Up @@ -91,28 +93,30 @@ namespace {
switch (mode) {
case FileAccessMode::Read:
return "rb";
case FileAccessMode::Write:
return "wb";
case FileAccessMode::Append:
return "ab";
case FileAccessMode::Write:
case FileAccessMode::ReadWrite:
return "r+b";
case FileAccessMode::ReadAppend:
return "a+b";
case FileAccessMode::Create:
return "wb";
}
break;
case FileType::TextFile:
switch (mode) {
case FileAccessMode::Read:
return "r";
case FileAccessMode::Write:
return "w";
case FileAccessMode::Append:
return "a";
case FileAccessMode::Write:
case FileAccessMode::ReadWrite:
return "r+";
case FileAccessMode::ReadAppend:
return "a+";
case FileAccessMode::Create:
return "w";
}
break;
}
Expand Down
18 changes: 14 additions & 4 deletions src/common/io_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ enum class FileAccessMode {
*/
Read = 1 << 0,
/**
* If the file at path exists, the existing contents of the file are erased.
* The empty file is then opened for writing.
* If the file at path does not exist, it creates and opens a new empty file for writing.
* If the file at path exists, it opens the file for writing.
* If the file at path does not exist, it fails to open the file.
*/
Write = 1 << 1,
/**
Expand All @@ -42,6 +41,12 @@ enum class FileAccessMode {
* reading and appending.
*/
ReadAppend = Read | Append,
/**
* If the file at path exists, the existing contents of the file are erased.
* The empty file is then opened for writing.
* If the file at path does not exist, it creates and opens a new empty file for writing.
*/
Create = 1 << 3,
};
DECLARE_ENUM_FLAG_OPERATORS(FileAccessMode);

Expand Down Expand Up @@ -102,6 +107,11 @@ class IOFile final {
return file != nullptr;
}

bool IsWriteOnly() const {
return file_access_mode == FileAccessMode::Append ||
file_access_mode == FileAccessMode::Write;
}

uintptr_t GetFileMapping();

int Open(const std::filesystem::path& path, FileAccessMode mode,
Expand Down Expand Up @@ -210,7 +220,7 @@ class IOFile final {
}

static size_t WriteBytes(const std::filesystem::path path, const auto& data) {
IOFile out(path, FileAccessMode::Write);
IOFile out(path, FileAccessMode::Create);
return out.Write(data);
}

Expand Down
2 changes: 1 addition & 1 deletion src/common/logging/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class ColorConsoleBackend {
class FileBackend {
public:
explicit FileBackend(const std::filesystem::path& filename)
: file{filename, FS::FileAccessMode::Write, FS::FileType::TextFile} {}
: file{filename, FS::FileAccessMode::Create, FS::FileType::TextFile} {}

~FileBackend() = default;

Expand Down
2 changes: 1 addition & 1 deletion src/core/devtools/widget/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
2 changes: 1 addition & 1 deletion src/core/devtools/widget/frame_dump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,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));
Expand Down
2 changes: 1 addition & 1 deletion src/core/file_format/psf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
47 changes: 34 additions & 13 deletions src/core/libraries/kernel/file_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,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
Expand Down Expand Up @@ -202,22 +202,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);
}
}
}

Expand Down Expand Up @@ -348,6 +356,12 @@ size_t PS4_SYSV_ABI readv(s32 fd, const SceKernelIovec* iov, s32 iovcnt) {
}
return result;
}

if (file->f.IsWriteOnly()) {
*__Error() = POSIX_EBADF;
return -1;
}

size_t total_read = 0;
for (s32 i = 0; i < iovcnt; i++) {
total_read += ReadFile(file->f, iov[i].iov_base, iov[i].iov_len);
Expand Down Expand Up @@ -493,6 +507,12 @@ s64 PS4_SYSV_ABI read(s32 fd, void* buf, size_t nbytes) {
}
return result;
}

if (file->f.IsWriteOnly()) {
*__Error() = POSIX_EBADF;
return -1;
}

return ReadFile(file->f, buf, nbytes);
}

Expand Down Expand Up @@ -784,11 +804,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);
Expand Down Expand Up @@ -831,6 +847,11 @@ s64 PS4_SYSV_ABI posix_preadv(s32 fd, SceKernelIovec* iov, s32 iovcnt, s64 offse
return result;
}

if (file->f.IsWriteOnly()) {
*__Error() = POSIX_EBADF;
return -1;
}

const s64 pos = file->f.Tell();
SCOPE_EXIT {
file->f.Seek(pos);
Expand Down
2 changes: 1 addition & 1 deletion src/core/libraries/save_data/save_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down
4 changes: 2 additions & 2 deletions src/core/libraries/save_data/save_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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();
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/libraries/save_data/savedata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
8 changes: 4 additions & 4 deletions src/core/loader/elf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,27 +502,27 @@ 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));
}
}

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++) {
Expand Down
2 changes: 1 addition & 1 deletion src/core/loader/symbols_resolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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, '#');
Expand Down
2 changes: 1 addition & 1 deletion src/shader_recompiler/frontend/translate/translate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ void Translator::EmitFetch(const GcnInst& inst) {
std::filesystem::create_directories(dump_dir);
}
const auto filename = fmt::format("vs_{:#018x}.fetch.bin", info.pgm_hash);
const auto file = IOFile{dump_dir / filename, FileAccessMode::Write};
const auto file = IOFile{dump_dir / filename, FileAccessMode::Create};
file.WriteRaw<u8>(fetch_data->code, fetch_data->size);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ static void DumpSrtProgram(const Shader::Info& info, const u8* code, size_t code
std::filesystem::create_directories(dump_dir);
}
const auto filename = fmt::format("{}_{:#018x}.srtprogram.txt", info.stage, info.pgm_hash);
const auto file = IOFile{dump_dir / filename, FileAccessMode::Write, FileType::TextFile};
const auto file = IOFile{dump_dir / filename, FileAccessMode::Create, FileType::TextFile};

u64 address = reinterpret_cast<u64>(code);
u64 code_end = address + codesize;
Expand Down
4 changes: 2 additions & 2 deletions src/shader_recompiler/ir/program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void DumpProgram(const Program& program, const Info& info, const std::string& ty
}
const auto ir_filename =
fmt::format("{}_{:#018x}.{}irprogram.txt", info.stage, info.pgm_hash, type);
const auto ir_file = IOFile{dump_dir / ir_filename, FileAccessMode::Write, FileType::TextFile};
const auto ir_file = IOFile{dump_dir / ir_filename, FileAccessMode::Create, FileType::TextFile};

size_t index{0};
std::map<const IR::Inst*, size_t> inst_to_index;
Expand All @@ -46,7 +46,7 @@ void DumpProgram(const Program& program, const Info& info, const std::string& ty

const auto asl_filename = fmt::format("{}_{:#018x}.{}asl.txt", info.stage, info.pgm_hash, type);
const auto asl_file =
IOFile{dump_dir / asl_filename, FileAccessMode::Write, FileType::TextFile};
IOFile{dump_dir / asl_filename, FileAccessMode::Create, FileType::TextFile};

for (const auto& node : program.syntax_list) {
std::string s = IR::DumpASLNode(node, block_to_index, inst_to_index) + '\n';
Expand Down
2 changes: 1 addition & 1 deletion src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ void PipelineCache::DumpShader(std::span<const u32> code, u64 hash, Shader::Stag
std::filesystem::create_directories(dump_dir);
}
const auto filename = fmt::format("{}.{}", GetShaderName(stage, hash, perm_idx), ext);
const auto file = IOFile{dump_dir / filename, FileAccessMode::Write};
const auto file = IOFile{dump_dir / filename, FileAccessMode::Create};
file.WriteSpan(code);
}

Expand Down