From 0393c7f52c58741807ea0a4a298c35623b05eee9 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 23 Mar 2017 21:32:59 +0300 Subject: [PATCH] fs:: handle negative seek --- Utilities/File.cpp | 31 +++++++++++++++++++++++++------ Utilities/File.h | 17 +++++++++++++---- rpcs3/Crypto/unedat.h | 17 +++++++++++++---- rpcs3/Emu/Cell/lv2/sys_fs.cpp | 31 ++++++++++++++++++++++++++----- 4 files changed, 77 insertions(+), 19 deletions(-) diff --git a/Utilities/File.cpp b/Utilities/File.cpp index 9bfcf76c58..f84459f2f9 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -797,7 +797,11 @@ fs::file::file(const std::string& path, bs_t mode) whence == seek_end ? FILE_END : (fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0); - verify("file::seek" HERE), SetFilePointerEx(m_handle, pos, &pos, mode); + if (!SetFilePointerEx(m_handle, pos, &pos, mode)) + { + g_tls_error = to_error(GetLastError()); + return -1; + } return pos.QuadPart; } @@ -899,7 +903,12 @@ fs::file::file(const std::string& path, bs_t mode) (fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0); const auto result = ::lseek(m_fd, offset, mode); - verify("file::seek" HERE), result != -1; + + if (result == -1) + { + g_tls_error = to_error(errno); + return -1; + } return result; } @@ -966,11 +975,20 @@ fs::file::file(const void* ptr, std::size_t size) u64 seek(s64 offset, fs::seek_mode whence) override { - return - whence == fs::seek_set ? m_pos = offset : - whence == fs::seek_cur ? m_pos = offset + m_pos : - whence == fs::seek_end ? m_pos = offset + m_size : + const s64 new_pos = + whence == fs::seek_set ? offset : + whence == fs::seek_cur ? offset + m_pos : + whence == fs::seek_end ? offset + size() : (fmt::raw_error("fs::file::memory_stream::seek(): invalid whence"), 0); + + if (new_pos < 0) + { + fs::g_tls_error = fs::error::inval; + return -1; + } + + m_pos = new_pos; + return m_pos; } u64 size() override @@ -1313,6 +1331,7 @@ void fmt_class_string::format(std::string& out, u64 arg) case fs::error::inval: return "Invalid arguments"; case fs::error::noent: return "Not found"; case fs::error::exist: return "Already exists"; + case fs::error::acces: return "Access violation"; } return unknown; diff --git a/Utilities/File.h b/Utilities/File.h index a92aabf861..0498a9ab74 100644 --- a/Utilities/File.h +++ b/Utilities/File.h @@ -547,11 +547,20 @@ namespace fs u64 seek(s64 offset, seek_mode whence) override { - return - whence == fs::seek_set ? pos = offset : - whence == fs::seek_cur ? pos = offset + pos : - whence == fs::seek_end ? pos = offset + size() : + const s64 new_pos = + whence == fs::seek_set ? offset : + whence == fs::seek_cur ? offset + pos : + whence == fs::seek_end ? offset + size() : (fmt::raw_error("fs::container_stream<>::seek(): invalid whence"), 0); + + if (new_pos < 0) + { + fs::g_tls_error = fs::error::inval; + return -1; + } + + pos = new_pos; + return pos; } u64 size() override diff --git a/rpcs3/Crypto/unedat.h b/rpcs3/Crypto/unedat.h index 01b2b4b379..a5356c1e4f 100644 --- a/rpcs3/Crypto/unedat.h +++ b/rpcs3/Crypto/unedat.h @@ -109,11 +109,20 @@ public: u64 seek(s64 offset, fs::seek_mode whence) override { - return - whence == fs::seek_set ? pos = offset : - whence == fs::seek_cur ? pos = offset + pos : - whence == fs::seek_end ? pos = offset + size() : + const s64 new_pos = + whence == fs::seek_set ? offset : + whence == fs::seek_cur ? offset + pos : + whence == fs::seek_end ? offset + size() : (fmt::raw_error("EDATADecrypter::seek(): invalid whence"), 0); + + if (new_pos < 0) + { + fs::g_tls_error = fs::error::inval; + return -1; + } + + pos = new_pos; + return pos; } u64 size() override { return file_size; } }; diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index 9c7290436e..0ebb9322f9 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -124,11 +124,20 @@ struct lv2_file::file_view : fs::file_base u64 seek(s64 offset, fs::seek_mode whence) override { - return - whence == fs::seek_set ? m_pos = offset : - whence == fs::seek_cur ? m_pos = offset + m_pos : - whence == fs::seek_end ? m_pos = offset + size() : + const s64 new_pos = + whence == fs::seek_set ? offset : + whence == fs::seek_cur ? offset + m_pos : + whence == fs::seek_end ? offset + size() : (fmt::raw_error("lv2_file::file_view::seek(): invalid whence"), 0); + + if (new_pos < 0) + { + fs::g_tls_error = fs::error::inval; + return -1; + } + + m_pos = new_pos; + return m_pos; } u64 size() override @@ -694,8 +703,20 @@ error_code sys_fs_lseek(u32 fd, s64 offset, s32 whence, vm::ptr pos) std::lock_guard lock(file->mp->mutex); - *pos = file->file.seek(offset, static_cast(whence)); + const u64 result = file->file.seek(offset, static_cast(whence)); + if (result == -1) + { + switch (auto error = fs::g_tls_error) + { + case fs::error::inval: return CELL_EINVAL; + default: sys_fs.error("sys_fs_lseek(): unknown error %s", error); + } + + return CELL_EIO; // ??? + } + + *pos = result; return CELL_OK; }