From a4db58f5f29674f5f82b20b2dbe8e87d7a00f8de Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 1 Nov 2015 13:33:28 +0300 Subject: [PATCH] Added fs::file_ptr, fom::rewrite, cleanup --- Utilities/File.cpp | 46 +++++++++++-- Utilities/File.h | 71 ++++++++++++++++++--- Utilities/Log.cpp | 4 +- rpcs3/Crypto/unedat.cpp | 2 +- rpcs3/Crypto/unpkg.cpp | 2 +- rpcs3/Crypto/unpkg.h | 2 +- rpcs3/Crypto/unself.cpp | 6 +- rpcs3/Emu/Audio/AudioDumper.cpp | 2 +- rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp | 6 +- rpcs3/Emu/HDD/HDD.cpp | 2 +- rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h | 6 +- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 2 +- rpcs3/Emu/RSX/GL/GLProgramBuffer.h | 4 +- rpcs3/Emu/SysCalls/Modules/cellFs.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 2 +- rpcs3/Gui/AutoPauseManager.cpp | 2 +- rpcs3/Gui/MainFrame.cpp | 19 ++---- rpcs3/Loader/TROPUSR.cpp | 2 +- rpcs3/Loader/TRP.cpp | 2 +- 19 files changed, 130 insertions(+), 54 deletions(-) diff --git a/Utilities/File.cpp b/Utilities/File.cpp index 8ef949a65e..e5f47b6b4d 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -96,6 +96,7 @@ bool truncate_file(const std::string& file, u64 length) } #else +#include #include #include #include @@ -306,14 +307,16 @@ bool fs::rename(const std::string& from, const std::string& to) int OSCopyFile(const char* source, const char* destination, bool overwrite) { - /* This function was taken from http://stackoverflow.com/questions/2180079/how-can-i-copy-a-file-on-unix-using-c */ + /* Source: http://stackoverflow.com/questions/2180079/how-can-i-copy-a-file-on-unix-using-c */ - int input, output; - if ((input = open(source, O_RDONLY)) == -1) + const int input = open(source, O_RDONLY); + if (input == -1) { return -1; } - if ((output = open(destination, O_WRONLY | O_CREAT | (overwrite ? O_TRUNC : O_EXCL), 0666)) == -1) + + const int output = open(destination, O_WRONLY | O_CREAT | (overwrite ? O_TRUNC : O_EXCL), 0666); + if (output == -1) { close(input); return -1; @@ -322,13 +325,12 @@ int OSCopyFile(const char* source, const char* destination, bool overwrite) //Here we use kernel-space copying for performance reasons #if defined(__APPLE__) || defined(__FreeBSD__) //fcopyfile works on FreeBSD and OS X 10.5+ - int result = fcopyfile(input, output, 0, COPYFILE_ALL); + const int result = fcopyfile(input, output, 0, COPYFILE_ALL); #else //sendfile will work with non-socket output (i.e. regular file) on Linux 2.6.33+ off_t bytesCopied = 0; struct stat fileinfo = { 0 }; - fstat(input, &fileinfo); - int result = sendfile(output, input, &bytesCopied, fileinfo.st_size) == -1 ? -1 : 0; + const int result = fstat(input, &fileinfo) == -1 || sendfile(output, input, &bytesCopied, fileinfo.st_size) == -1 ? -1 : 0; #endif close(input); @@ -662,6 +664,36 @@ fs::dir::~dir() } } +void fs::file_ptr::reset(const file& f) +{ + reset(); + + if (f) + { +#ifdef _WIN32 + const HANDLE handle = ::CreateFileMapping((HANDLE)f.m_fd, NULL, PAGE_READONLY, 0, 0, NULL); + m_ptr = (char*)::MapViewOfFile(handle, FILE_MAP_READ, 0, 0, 0); + m_size = f.size(); + ::CloseHandle(handle); +#else + m_ptr = (char*)::mmap(nullptr, m_size = f.size(), PROT_READ, MAP_SHARED, f.m_fd, 0); + if (m_ptr == (void*)-1) m_ptr = nullptr; +#endif + } +} + +void fs::file_ptr::reset() +{ + if (m_ptr) + { +#ifdef _WIN32 + ::UnmapViewOfFile(m_ptr); +#else + ::munmap(m_ptr, m_size); +#endif + } +} + bool fs::dir::open(const std::string& dirname) { this->close(); diff --git a/Utilities/File.h b/Utilities/File.h index d9c614ffac..1678f2833a 100644 --- a/Utilities/File.h +++ b/Utilities/File.h @@ -11,12 +11,14 @@ namespace fom // file open mode { enum : u32 { - read = 1 << 0, - write = 1 << 1, - append = 1 << 2, - create = 1 << 3, - trunc = 1 << 4, - excl = 1 << 5, + read = 1 << 0, // enable reading + write = 1 << 1, // enable writing + append = 1 << 2, // enable appending (always write to the end of file) + create = 1 << 3, // create file if it doesn't exist + trunc = 1 << 4, // clear opened file if it's not empty + excl = 1 << 5, // failure if the file already exists (used with `create`) + + rewrite = write | create | trunc, // write + create + trunc }; }; @@ -81,6 +83,8 @@ namespace fs handle_type m_fd = null; + friend class file_ptr; + public: file() = default; @@ -133,14 +137,63 @@ namespace fs // Write the data to the file and return the amount of data actually written u64 write(const void* buffer, u64 count) const; - // Write std::string - u64 write(const std::string& string) const { return write(string.data(), string.size()); } - // Move file pointer u64 seek(s64 offset, fsm seek_mode = fsm::begin) const; // Get file size u64 size() const; + + // Write std::string + const file& operator <<(const std::string& str) const + { + CHECK_ASSERTION(write(str.data(), str.size()) == str.size()); + return *this; + } + }; + + class file_ptr final + { + char* m_ptr = nullptr; + u64 m_size; + + public: + file_ptr() = default; + + file_ptr(file_ptr&& right) + : m_ptr(right.m_ptr) + , m_size(right.m_size) + { + right.m_ptr = 0; + } + + file_ptr& operator =(file_ptr&& right) + { + std::swap(m_ptr, right.m_ptr); + std::swap(m_size, right.m_size); + return *this; + } + + file_ptr(const file& f) + { + reset(f); + } + + ~file_ptr() + { + reset(); + } + + // Open file mapping + void reset(const file& f); + + // Close file mapping + void reset(); + + // Get pointer + operator char*() const + { + return m_ptr; + } }; class dir final diff --git a/Utilities/Log.cpp b/Utilities/Log.cpp index 0286ca0a58..4b981756a2 100644 --- a/Utilities/Log.cpp +++ b/Utilities/Log.cpp @@ -94,7 +94,7 @@ struct FileListener : LogListener bool mPrependChannelName; FileListener(const std::string& name = _PRGNAME_, bool prependChannel = true) - : mFile(rPlatform::getConfigDir() + name + ".log", fom::write | fom::create | fom::trunc) + : mFile(rPlatform::getConfigDir() + name + ".log", fom::rewrite) , mPrependChannelName(prependChannel) { if (!mFile) @@ -120,7 +120,7 @@ struct FileListener : LogListener } } - mFile.write(text.c_str(), text.size()); + mFile << text; } }; diff --git a/rpcs3/Crypto/unedat.cpp b/rpcs3/Crypto/unedat.cpp index 011e9a701f..e6269544f3 100644 --- a/rpcs3/Crypto/unedat.cpp +++ b/rpcs3/Crypto/unedat.cpp @@ -821,7 +821,7 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi { // Prepare the files. fs::file input(input_file_name); - fs::file output(output_file_name, fom::write | fom::create | fom::trunc); + fs::file output(output_file_name, fom::rewrite); fs::file rap(rap_file_name); // Set keys (RIF and DEVKLIC). diff --git a/rpcs3/Crypto/unpkg.cpp b/rpcs3/Crypto/unpkg.cpp index 03168d734c..6e9f42c948 100644 --- a/rpcs3/Crypto/unpkg.cpp +++ b/rpcs3/Crypto/unpkg.cpp @@ -59,7 +59,7 @@ static bool CheckHeader(const fs::file& pkg_f, PKGHeader& header) } // PKG Decryption -bool UnpackPKG(const fs::file& pkg_f, const std::string& dir, volatile f64& progress) +bool pkg_install(const fs::file& pkg_f, const std::string& dir, volatile f64& progress) { const std::size_t BUF_SIZE = 8192 * 1024; // 8 MB diff --git a/rpcs3/Crypto/unpkg.h b/rpcs3/Crypto/unpkg.h index 8bdfe04b06..fe39e9aed0 100644 --- a/rpcs3/Crypto/unpkg.h +++ b/rpcs3/Crypto/unpkg.h @@ -57,4 +57,4 @@ struct PKGEntry be_t pad; // Padding (zeros) }; -bool UnpackPKG(const class fs::file& pkg_f, const std::string& dir, volatile f64& progress); +bool pkg_install(const class fs::file& pkg_f, const std::string& dir, volatile f64& progress); diff --git a/rpcs3/Crypto/unself.cpp b/rpcs3/Crypto/unself.cpp index c307a9de6b..9b3ca90edf 100644 --- a/rpcs3/Crypto/unself.cpp +++ b/rpcs3/Crypto/unself.cpp @@ -1085,8 +1085,8 @@ bool SELFDecrypter::DecryptData() bool SELFDecrypter::MakeElf(const std::string& elf, bool isElf32) { // Create a new ELF file. - fs::file e(elf, fom::write | fom::create | fom::trunc); - if (!e) + fs::file e(elf, fom::rewrite); + if(!e) { LOG_ERROR(LOADER, "Could not create ELF file! (%s)", elf.c_str()); return false; @@ -1309,7 +1309,7 @@ bool CheckDebugSelf(const std::string& self, const std::string& elf) CHECK_ASSERTION(s.seek(elf_offset) != -1); // Write the real ELF file back. - fs::file e(elf, fom::write | fom::create | fom::trunc); + fs::file e(elf, fom::rewrite); if (!e) { LOG_ERROR(LOADER, "Could not create ELF file! (%s)", elf.c_str()); diff --git a/rpcs3/Emu/Audio/AudioDumper.cpp b/rpcs3/Emu/Audio/AudioDumper.cpp index 53e6ea7165..fc215bcbf6 100644 --- a/rpcs3/Emu/Audio/AudioDumper.cpp +++ b/rpcs3/Emu/Audio/AudioDumper.cpp @@ -12,7 +12,7 @@ AudioDumper::~AudioDumper() bool AudioDumper::Init(u8 ch) { - if ((m_init = m_output.open("audio.wav", fom::write | fom::create | fom::trunc))) + if ((m_init = m_output.open("audio.wav", fom::rewrite))) { m_header = WAVHeader(ch); WriteHeader(); diff --git a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp index 74ed9b1de7..b2a83a7f72 100644 --- a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp @@ -33,9 +33,7 @@ spu_recompiler::spu_recompiler() LOG_SUCCESS(SPU, "SPU Recompiler (ASMJIT) created..."); - const std::string str = fmt::format("SPU JIT initialization...\n\nTitle: %s\nTitle ID: %s\n\n", Emu.GetTitle().c_str(), Emu.GetTitleID().c_str()); - - fs::file("SPUJIT.log", fom::write | fom::create | fom::trunc).write(str.c_str(), str.size()); + fs::file("SPUJIT.log", fom::rewrite) << fmt::format("SPU JIT initialization...\n\nTitle: %s\nTitle ID: %s\n\n", Emu.GetTitle().c_str(), Emu.GetTitleID().c_str()); } void spu_recompiler::compile(spu_function_t& f) @@ -220,7 +218,7 @@ void spu_recompiler::compile(spu_function_t& f) log += "\n\n\n"; // Append log file - fs::file("SPUJIT.log", fom::write | fom::append | fom::create).write(log.c_str(), log.size()); + fs::file("SPUJIT.log", fom::write | fom::append) << log; } spu_recompiler::XmmLink spu_recompiler::XmmAlloc() // get empty xmm register diff --git a/rpcs3/Emu/HDD/HDD.cpp b/rpcs3/Emu/HDD/HDD.cpp index 769f2ebf43..9675fde84a 100644 --- a/rpcs3/Emu/HDD/HDD.cpp +++ b/rpcs3/Emu/HDD/HDD.cpp @@ -21,7 +21,7 @@ void vfsHDDManager::CreateEntry(vfsHDD_Entry& entry) void vfsHDDManager::CreateHDD(const std::string& path, u64 size, u64 block_size) { - fs::file f(path, fom::write | fom::create | fom::trunc); + fs::file f(path, fom::rewrite); static const u64 cur_dir_block = 1; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h index 26d4267fdb..f0766bfc4c 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.h @@ -164,8 +164,7 @@ struct D3D12Traits } // TODO: This shouldn't use current dir - std::string filename = "./FragmentProgram" + std::to_string(ID) + ".hlsl"; - fs::file(filename, fom::write | fom::create | fom::trunc).write(shader.c_str(), shader.size()); + fs::file("./FragmentProgram" + std::to_string(ID) + ".hlsl", fom::rewrite) << shader; fragmentProgramData.id = (u32)ID; } @@ -177,8 +176,7 @@ struct D3D12Traits vertexProgramData.Compile(shaderCode, Shader::SHADER_TYPE::SHADER_TYPE_VERTEX); vertexProgramData.vertex_shader_inputs = VS.input_slots; // TODO: This shouldn't use current dir - std::string filename = "./VertexProgram" + std::to_string(ID) + ".hlsl"; - fs::file(filename, fom::write | fom::create | fom::trunc).write(shaderCode.c_str(), shaderCode.size()); + fs::file("./VertexProgram" + std::to_string(ID) + ".hlsl", fom::rewrite) << shaderCode; vertexProgramData.id = (u32)ID; } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 5cd1ce6809..5e7c2deee3 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -469,7 +469,7 @@ void GLTexture::save(rsx::texture& tex, const std::string& name) return; } - fs::file(name + ".raw", fom::write | fom::create | fom::trunc).write(alldata, texPixelCount * 4); + fs::file(name + ".raw", fom::rewrite).write(alldata, texPixelCount * 4); u8* data = new u8[texPixelCount * 3]; u8* alpha = new u8[texPixelCount]; diff --git a/rpcs3/Emu/RSX/GL/GLProgramBuffer.h b/rpcs3/Emu/RSX/GL/GLProgramBuffer.h index a82547aeb7..28652bf975 100644 --- a/rpcs3/Emu/RSX/GL/GLProgramBuffer.h +++ b/rpcs3/Emu/RSX/GL/GLProgramBuffer.h @@ -19,7 +19,7 @@ struct GLTraits //checkForGlError("m_fragment_prog.Compile"); // TODO: This shouldn't use current dir - fs::file("./FragmentProgram.txt", fom::write | fom::create | fom::trunc).write(fragmentProgramData.shader.c_str(), fragmentProgramData.shader.size()); + fs::file("./FragmentProgram.txt", fom::rewrite) << fragmentProgramData.shader; } static @@ -30,7 +30,7 @@ struct GLTraits //checkForGlError("m_vertex_prog.Compile"); // TODO: This shouldn't use current dir - fs::file("./VertexProgram.txt", fom::write | fom::create | fom::trunc).write(vertexProgramData.shader.c_str(), vertexProgramData.shader.size()); + fs::file("./VertexProgram.txt", fom::rewrite) << vertexProgramData.shader; } static diff --git a/rpcs3/Emu/SysCalls/Modules/cellFs.cpp b/rpcs3/Emu/SysCalls/Modules/cellFs.cpp index 232771d4b6..e50abb4ba4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellFs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellFs.cpp @@ -753,7 +753,7 @@ bool sdata_check(u32 version, u32 flags, u64 filesizeInput, u64 filesizeTmp) s32 sdata_unpack(const std::string& packed_file, const std::string& unpacked_file) { std::shared_ptr packed_stream(Emu.GetVFS().OpenFile(packed_file, fom::read)); - std::shared_ptr unpacked_stream(Emu.GetVFS().OpenFile(unpacked_file, fom::write | fom::create | fom::trunc)); + std::shared_ptr unpacked_stream(Emu.GetVFS().OpenFile(unpacked_file, fom::rewrite)); if (!packed_stream || !packed_stream->IsOpened()) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index 3bf8c7a97e..847826129b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -622,7 +622,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt // Write PARAM.SFO if (psf) { - vfsFile f(sfo_path, fom::write | fom::create | fom::trunc); + vfsFile f(sfo_path, fom::rewrite); psf.Save(f); } diff --git a/rpcs3/Gui/AutoPauseManager.cpp b/rpcs3/Gui/AutoPauseManager.cpp index fd3abd43a1..7fd2fb7202 100644 --- a/rpcs3/Gui/AutoPauseManager.cpp +++ b/rpcs3/Gui/AutoPauseManager.cpp @@ -96,7 +96,7 @@ void AutoPauseManagerDialog::LoadEntries(void) //This would always use a 0xFFFFFFFF as end of the pause.bin void AutoPauseManagerDialog::SaveEntries(void) { - fs::file list("pause.bin", fom::write | fom::create | fom::trunc); + fs::file list("pause.bin", fom::rewrite); //System calls ID and Function calls ID are all u32 iirc. u32 num = 0; CHECK_ASSERTION(list.seek(0) != -1); diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 5d5c96e546..ccce07da48 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -252,25 +252,20 @@ void MainFrame::InstallPkg(wxCommandEvent& WXUNUSED(event)) Emu.GetVFS().GetDevice("/dev_hdd0/game/", local_path); // Open PKG file - fs::file pkg_f{ ctrl.GetPath().ToStdString() }; + fs::file pkg_f(ctrl.GetPath().ToStdString()); - if (!pkg_f) + // Open file mapping (test) + fs::file_ptr pkg_ptr(pkg_f); + + if (!pkg_f || !pkg_ptr) { LOG_ERROR(LOADER, "PKG: Failed to open %s", ctrl.GetPath().ToStdString()); return; } - // Fetch title ID from the header - char title_id[10] = "?????????"; - - CHECK_ASSERTION(pkg_f.seek(55) != -1); - - pkg_f.read(title_id, 9); - pkg_f.seek(0); - // Append title ID to the path local_path += '/'; - local_path += title_id; + local_path += { pkg_ptr + 55, 9 }; if (!fs::create_dir(local_path)) { @@ -294,7 +289,7 @@ void MainFrame::InstallPkg(wxCommandEvent& WXUNUSED(event)) volatile f64 progress = 0.0; // Run PKG unpacking asynchronously - auto result = std::async(WRAP_EXPR(UnpackPKG(pkg_f, local_path + "/", progress))); + auto result = std::async(WRAP_EXPR(pkg_install(pkg_f, local_path + "/", progress))); // Wait for the completion while (result.wait_for(15ms) != std::future_status::ready) diff --git a/rpcs3/Loader/TROPUSR.cpp b/rpcs3/Loader/TROPUSR.cpp index f31e49fcdc..a7ec1714e3 100644 --- a/rpcs3/Loader/TROPUSR.cpp +++ b/rpcs3/Loader/TROPUSR.cpp @@ -124,7 +124,7 @@ bool TROPUSRLoader::Save(const std::string& filepath) Close(); } - m_file = Emu.GetVFS().OpenFile(filepath, fom::write | fom::create | fom::trunc); + m_file = Emu.GetVFS().OpenFile(filepath, fom::rewrite); m_file->Write(&m_header, sizeof(TROPUSRHeader)); for (const TROPUSRTableHeader& tableHeader : m_tableHeaders) diff --git a/rpcs3/Loader/TRP.cpp b/rpcs3/Loader/TRP.cpp index c47327826e..db0b9604f6 100644 --- a/rpcs3/Loader/TRP.cpp +++ b/rpcs3/Loader/TRP.cpp @@ -36,7 +36,7 @@ bool TRPLoader::Install(std::string dest, bool show) char* buffer = new char [(u32)entry.size]; trp_f.Seek(entry.offset); trp_f.Read(buffer, entry.size); - vfsFile(dest + entry.name, fom::write | fom::create | fom::trunc).Write(buffer, entry.size); + vfsFile(dest + entry.name, fom::rewrite).Write(buffer, entry.size); delete[] buffer; }