From 6c36013e2a4f87a12ad5b04968925e513a546a48 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 13 Mar 2015 18:06:27 +0300 Subject: [PATCH] sys_fs_open rewritten --- rpcs3/Emu/FS/VFS.cpp | 4 +- rpcs3/Emu/FS/VFS.h | 2 +- rpcs3/Emu/FS/vfsFile.cpp | 4 +- rpcs3/Emu/FS/vfsFile.h | 2 +- rpcs3/Emu/FS/vfsFileBase.h | 2 +- rpcs3/Emu/FS/vfsLocalFile.cpp | 8 +- rpcs3/Emu/FS/vfsLocalFile.h | 2 +- rpcs3/Emu/Memory/atomic.h | 8 +- rpcs3/Emu/Memory/vm_var.h | 20 +++ rpcs3/Emu/SysCalls/Modules/cellFs.cpp | 20 +-- rpcs3/Emu/SysCalls/lv2/sys_fs.cpp | 170 +++++++++++++++----------- rpcs3/Emu/SysCalls/lv2/sys_fs.h | 22 ++-- 12 files changed, 158 insertions(+), 106 deletions(-) diff --git a/rpcs3/Emu/FS/VFS.cpp b/rpcs3/Emu/FS/VFS.cpp index 11feecb3ef..6af15b1f47 100644 --- a/rpcs3/Emu/FS/VFS.cpp +++ b/rpcs3/Emu/FS/VFS.cpp @@ -161,7 +161,7 @@ vfsDirBase* VFS::OpenDir(const std::string& ps3_path) const return nullptr; } -bool VFS::CreateFile(const std::string& ps3_path) const +bool VFS::CreateFile(const std::string& ps3_path, bool overwrite) const { std::string path; if (vfsDevice* dev = GetDevice(ps3_path, path)) @@ -170,7 +170,7 @@ bool VFS::CreateFile(const std::string& ps3_path) const if (res) { - return res->Create(path); + return res->Create(path, overwrite); } } diff --git a/rpcs3/Emu/FS/VFS.h b/rpcs3/Emu/FS/VFS.h index 9d202d4cb9..d62ba7c411 100644 --- a/rpcs3/Emu/FS/VFS.h +++ b/rpcs3/Emu/FS/VFS.h @@ -78,7 +78,7 @@ struct VFS vfsFileBase* OpenFile(const std::string& ps3_path, vfsOpenMode mode) const; vfsDirBase* OpenDir(const std::string& ps3_path) const; - bool CreateFile(const std::string& ps3_path) const; + bool CreateFile(const std::string& ps3_path, bool overwrite = false) const; bool CreateDir(const std::string& ps3_path) const; bool RemoveFile(const std::string& ps3_path) const; bool RemoveDir(const std::string& ps3_path) const; diff --git a/rpcs3/Emu/FS/vfsFile.cpp b/rpcs3/Emu/FS/vfsFile.cpp index 8d0bfb1ebb..6f990c31e2 100644 --- a/rpcs3/Emu/FS/vfsFile.cpp +++ b/rpcs3/Emu/FS/vfsFile.cpp @@ -26,9 +26,9 @@ bool vfsFile::Open(const std::string& path, vfsOpenMode mode) return m_stream && m_stream->IsOpened(); } -bool vfsFile::Create(const std::string& path) +bool vfsFile::Create(const std::string& path, bool overwrite) { - return m_stream->Create(path); + return m_stream->Create(path, overwrite); } bool vfsFile::Exists(const std::string& path) diff --git a/rpcs3/Emu/FS/vfsFile.h b/rpcs3/Emu/FS/vfsFile.h index 4ab9ddc87d..a5ed8cf138 100644 --- a/rpcs3/Emu/FS/vfsFile.h +++ b/rpcs3/Emu/FS/vfsFile.h @@ -11,7 +11,7 @@ public: vfsFile(const std::string& path, vfsOpenMode mode = vfsRead); virtual bool Open(const std::string& path, vfsOpenMode mode = vfsRead) override; - virtual bool Create(const std::string& path) override; + virtual bool Create(const std::string& path, bool overwrite = false) override; virtual bool Exists(const std::string& path) override; virtual bool Rename(const std::string& from, const std::string& to) override; virtual bool Remove(const std::string& path) override; diff --git a/rpcs3/Emu/FS/vfsFileBase.h b/rpcs3/Emu/FS/vfsFileBase.h index ff7a56e349..700f397a2a 100644 --- a/rpcs3/Emu/FS/vfsFileBase.h +++ b/rpcs3/Emu/FS/vfsFileBase.h @@ -27,7 +27,7 @@ public: virtual bool Open(const std::string& path, vfsOpenMode mode); virtual bool Close() override; - virtual bool Create(const std::string& path) { return false; } + virtual bool Create(const std::string& path, bool overwrite = false) { return false; } virtual bool Exists(const std::string& path) { return false; } virtual bool Rename(const std::string& from, const std::string& to) { return false; } virtual bool Remove(const std::string& path) { return false; } diff --git a/rpcs3/Emu/FS/vfsLocalFile.cpp b/rpcs3/Emu/FS/vfsLocalFile.cpp index 0e716c40af..f33639bd1d 100644 --- a/rpcs3/Emu/FS/vfsLocalFile.cpp +++ b/rpcs3/Emu/FS/vfsLocalFile.cpp @@ -51,9 +51,9 @@ bool vfsLocalFile::Open(const std::string& path, vfsOpenMode mode) // } } -bool vfsLocalFile::Create(const std::string& path) +bool vfsLocalFile::Create(const std::string& path, bool overwrite) { - LOG_WARNING(HLE, "vfsLocalFile::Create('%s')", path.c_str()); + LOG_WARNING(HLE, "vfsLocalFile::Create('%s', overwrite=%d)", path.c_str(), overwrite); for(uint p=1; p < path.length() && path[p] != '\0' ; p++) { for(; p < path.length() && path[p] != '\0'; p++) @@ -75,8 +75,8 @@ bool vfsLocalFile::Create(const std::string& path) if(m != '/' && m != '\\' && !rExists(path)) // ??? { rFile f; - if (!f.Create(path)) { - LOG_NOTICE(HLE, "vfsLocalFile::Create: couldn't create file"); + if (!f.Create(path, overwrite)) { + if (overwrite) LOG_NOTICE(HLE, "vfsLocalFile::Create: couldn't create file"); return false; } else diff --git a/rpcs3/Emu/FS/vfsLocalFile.h b/rpcs3/Emu/FS/vfsLocalFile.h index 7395eb519a..efef6328d5 100644 --- a/rpcs3/Emu/FS/vfsLocalFile.h +++ b/rpcs3/Emu/FS/vfsLocalFile.h @@ -11,7 +11,7 @@ public: vfsLocalFile(vfsDevice* device); virtual bool Open(const std::string& path, vfsOpenMode mode = vfsRead) override; - virtual bool Create(const std::string& path) override; + virtual bool Create(const std::string& path, bool overwrite = false) override; virtual bool Close() override; virtual bool Exists(const std::string& path) override; diff --git a/rpcs3/Emu/Memory/atomic.h b/rpcs3/Emu/Memory/atomic.h index 54eb1c7427..f53214792e 100644 --- a/rpcs3/Emu/Memory/atomic.h +++ b/rpcs3/Emu/Memory/atomic.h @@ -199,10 +199,10 @@ public: }; // Helper definitions -template using if_arithmetic_t = typename std::enable_if::value && std::is_arithmetic::value, T>::type; -template using if_arithmetic_be_t = typename std::enable_if::value && std::is_arithmetic::value, be_t>::type; -template using if_arithmetic_atomic_t = typename std::enable_if::value && std::is_arithmetic::value, _atomic_base>::type; -template using if_arithmetic_atomic_be_t = typename std::enable_if::value && std::is_arithmetic::value, _atomic_base>>::type; +template using if_arithmetic_t = const typename std::enable_if::value && std::is_arithmetic::value, T>::type; +template using if_arithmetic_be_t = const typename std::enable_if::value && std::is_arithmetic::value, be_t>::type; +template using if_arithmetic_atomic_t = typename std::enable_if::value && std::is_arithmetic::value, _atomic_base&>::type; +template using if_arithmetic_atomic_be_t = typename std::enable_if::value && std::is_arithmetic::value, _atomic_base>&>::type; template inline static if_arithmetic_t operator ++(_atomic_base& left) { diff --git a/rpcs3/Emu/Memory/vm_var.h b/rpcs3/Emu/Memory/vm_var.h index 1a3d104c3d..b42f89096c 100644 --- a/rpcs3/Emu/Memory/vm_var.h +++ b/rpcs3/Emu/Memory/vm_var.h @@ -117,6 +117,16 @@ namespace vm { return _ptr_base::make(m_addr); } + + template operator _ptr_base() const + { + return _ptr_base::make(m_data.addr); + } + + template operator _ptr_base() const + { + return _ptr_base::make(m_data.addr); + } operator T&() { @@ -614,6 +624,16 @@ namespace vm return _ptr_base::make(m_data.addr); } + template operator _ptr_base() const + { + return _ptr_base::make(m_data.addr); + } + + template operator _ptr_base() const + { + return _ptr_base::make(m_data.addr); + } + operator T&() { return *m_data.ptr; diff --git a/rpcs3/Emu/SysCalls/Modules/cellFs.cpp b/rpcs3/Emu/SysCalls/Modules/cellFs.cpp index d3ca1644ad..3b18e0965a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellFs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellFs.cpp @@ -537,13 +537,20 @@ int sdata_unpack(const std::string& packed_file, const std::string& unpacked_fil return CELL_OK; } -s32 cellFsSdataOpen(vm::ptr path, s32 flags, vm::ptr fd, vm::ptr arg, u64 size) +s32 cellFsSdataOpen(PPUThread& CPU, vm::ptr path, s32 flags, vm::ptr fd, vm::ptr arg, u64 size) { - cellFs.Warning("cellFsSdataOpen(path=*0x%x, flags=0x%x, fd=*0x%x, arg=*0x%x, size=0x%llx) -> sys_fs_open()", path, flags, fd, arg, size); + cellFs.Log("cellFsSdataOpen(path=*0x%x, flags=0x%x, fd=*0x%x, arg=*0x%x, size=0x%llx)", path, flags, fd, arg, size); - /*if (flags != CELL_O_RDONLY) - return CELL_EINVAL; + if (flags != CELL_FS_O_RDONLY) + { + return CELL_EINVAL; + } + return cellFsOpen(path, CELL_FS_O_RDONLY, fd, vm::stackvar>(CPU), 8); + + // Don't implement sdata decryption in this function, it should be done in sys_fs_open() syscall or somewhere else + + /* std::string suffix = path.substr(path.length() - 5, 5); if (suffix != ".sdat" && suffix != ".SDAT") return CELL_ENOTSDATA; @@ -556,9 +563,8 @@ s32 cellFsSdataOpen(vm::ptr path, s32 flags, vm::ptr fd, vm::pt fd = Emu.GetIdManager().GetNewID(Emu.GetVFS().OpenFile(unpacked_path, vfsRead), TYPE_FS_FILE); - return CELL_OK;*/ - - return sys_fs_open(path, flags, fd, 0, arg, size); + return CELL_OK; + */ } s32 cellFsSdataOpenByFd(u32 mself_fd, s32 flags, vm::ptr sdata_fd, u64 offset, vm::ptr arg, u64 size) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp b/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp index 99c0c58914..7a93f23687 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp @@ -22,83 +22,87 @@ SysCallBase sys_fs("sys_fs"); s32 sys_fs_open(vm::ptr path, s32 flags, vm::ptr fd, u32 mode, vm::ptr arg, u64 size) { - sys_fs.Warning("sys_fs_open(path=*0x%x, flags=0x%x, fd=*0x%x, arg=*0x%x, size=0x%llx)", path, flags, fd, arg, size); + sys_fs.Warning("sys_fs_open(path=*0x%x, flags=%d, fd=*0x%x, arg=*0x%x, size=0x%llx)", path, flags, fd, arg, size); sys_fs.Warning("*** path = '%s'", path.get_ptr()); - const std::string _path = path.get_ptr(); + std::shared_ptr file; - s32 _oflags = flags; - if (flags & CELL_FS_O_CREAT) + if (mode) { - _oflags &= ~CELL_FS_O_CREAT; - Emu.GetVFS().CreateFile(_path); + sys_fs.Error("sys_fs_open(): unknown mode (0x%x)", mode); + return CELL_FS_EINVAL; } - vfsOpenMode o_mode; + // TODO: other checks for path - switch (flags & CELL_FS_O_ACCMODE) + if (Emu.GetVFS().ExistsDir(path.get_ptr())) + { + sys_fs.Error("sys_fs_open(): '%s' is a directory", path.get_ptr()); + return CELL_FS_EISDIR; + } + + switch (flags) { case CELL_FS_O_RDONLY: - _oflags &= ~CELL_FS_O_RDONLY; - o_mode = vfsRead; + { + file.reset(Emu.GetVFS().OpenFile(path.get_ptr(), vfsRead)); break; + } + //case CELL_FS_O_WRONLY: + //case CELL_FS_O_WRONLY | CELL_FS_O_CREAT: - case CELL_FS_O_WRONLY: - _oflags &= ~CELL_FS_O_WRONLY; + case CELL_FS_O_WRONLY | CELL_FS_O_CREAT | CELL_FS_O_EXCL: + { + file.reset(Emu.GetVFS().OpenFile(path.get_ptr(), vfsWriteExcl)); - if (flags & CELL_FS_O_APPEND) + if ((!file || !file->IsOpened()) && Emu.GetVFS().ExistsFile(path.get_ptr())) { - _oflags &= ~CELL_FS_O_APPEND; - o_mode = vfsWriteAppend; - } - else if (flags & CELL_FS_O_EXCL) - { - _oflags &= ~CELL_FS_O_EXCL; - o_mode = vfsWriteExcl; - } - else //if (flags & CELL_FS_O_TRUNC) - { - _oflags &= ~CELL_FS_O_TRUNC; - o_mode = vfsWrite; + return CELL_FS_EEXIST; } + break; + } + case CELL_FS_O_WRONLY | CELL_FS_O_CREAT | CELL_FS_O_TRUNC: + { + Emu.GetVFS().CreateFile(path.get_ptr()); + file.reset(Emu.GetVFS().OpenFile(path.get_ptr(), vfsWrite)); + break; + } + case CELL_FS_O_WRONLY | CELL_FS_O_CREAT | CELL_FS_O_APPEND: + { + Emu.GetVFS().CreateFile(path.get_ptr()); + file.reset(Emu.GetVFS().OpenFile(path.get_ptr(), vfsWriteAppend)); + break; + } case CELL_FS_O_RDWR: - _oflags &= ~CELL_FS_O_RDWR; - if (flags & CELL_FS_O_TRUNC) - { - _oflags &= ~CELL_FS_O_TRUNC; - //truncate file before opening it as read/write - auto filePtr = Emu.GetVFS().OpenFile(_path, vfsWrite); - delete filePtr; - } - o_mode = vfsReadWrite; + { + file.reset(Emu.GetVFS().OpenFile(path.get_ptr(), vfsReadWrite)); break; } - - if (_oflags != 0) + case CELL_FS_O_RDWR | CELL_FS_O_CREAT: { - sys_fs.Error("sys_fs_open(): '%s' has unknown flags! flags: 0x%08x", path.get_ptr(), flags); - return CELL_EINVAL; + Emu.GetVFS().CreateFile(path.get_ptr()); + file.reset(Emu.GetVFS().OpenFile(path.get_ptr(), vfsReadWrite)); + break; + } + //case CELL_FS_O_RDWR | CELL_FS_O_CREAT | CELL_FS_O_EXCL: + //case CELL_FS_O_RDWR | CELL_FS_O_CREAT | CELL_FS_O_TRUNC: + + default: + { + sys_fs.Error("sys_fs_open(): invalid or unimplemented flags (%d)", flags); + return CELL_FS_EINVAL; + } } - if (!Emu.GetVFS().ExistsFile(_path)) + if (!file || !file->IsOpened()) { - sys_fs.Error("sys_fs_open(): '%s' not found! flags: 0x%08x", path.get_ptr(), flags); - return CELL_ENOENT; + sys_fs.Error("sys_fs_open(): failed to open '%s' (flags=%d, mode=0x%x)", path.get_ptr(), flags, mode); + return CELL_FS_ENOENT; } - std::shared_ptr stream(Emu.GetVFS().OpenFile(_path, o_mode)); - - if (!stream || !stream->IsOpened()) - { - sys_fs.Error("sys_fs_open(): '%s' not found! flags: 0x%08x", path.get_ptr(), flags); - return CELL_ENOENT; - } - - u32 id = Emu.GetIdManager().GetNewID(stream, TYPE_FS_FILE); - *fd = id; - sys_fs.Notice("sys_fs_open(): '%s' opened, id -> 0x%x", path.get_ptr(), id); + *fd = Emu.GetIdManager().GetNewID(file, TYPE_FS_FILE); return CELL_OK; } @@ -108,14 +112,13 @@ s32 sys_fs_read(u32 fd, vm::ptr buf, u64 nbytes, vm::ptr nread) sys_fs.Log("sys_fs_read(fd=0x%x, buf=0x%x, nbytes=0x%llx, nread=0x%x)", fd, buf, nbytes, nread); std::shared_ptr file; + if (!Emu.GetIdManager().GetIDData(fd, file)) - return CELL_ESRCH; + { + return CELL_FS_EBADF; // TODO: return if not opened for reading + } - // TODO: checks - - const u64 res = nbytes ? file->Read(buf.get_ptr(), nbytes) : 0; - - if (nread) *nread = res; + *nread = file->Read(buf.get_ptr(), nbytes); return CELL_OK; } @@ -125,23 +128,34 @@ s32 sys_fs_write(u32 fd, vm::ptr buf, u64 nbytes, vm::ptr nwrit sys_fs.Log("sys_fs_write(fd=0x%x, buf=*0x%x, nbytes=0x%llx, nwrite=*0x%x)", fd, buf, nbytes, nwrite); std::shared_ptr file; - if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; - // TODO: checks + if (!Emu.GetIdManager().GetIDData(fd, file)) + { + return CELL_FS_EBADF; // TODO: return if not opened for writing + } - const u64 res = nbytes ? file->Write(buf.get_ptr(), nbytes) : 0; - - if (nwrite) *nwrite = res; + *nwrite = file->Write(buf.get_ptr(), nbytes); return CELL_OK; } s32 sys_fs_close(u32 fd) { - sys_fs.Warning("sys_fs_close(fd=0x%x)", fd); + sys_fs.Log("sys_fs_close(fd=0x%x)", fd); - if (!Emu.GetIdManager().RemoveID(fd)) - return CELL_ESRCH; + std::shared_ptr file; + + if (!Emu.GetIdManager().GetIDData(fd, file)) + { + return CELL_FS_EBADF; + } + + if (false) + { + return CELL_FS_EBUSY; // TODO: return if locked + } + + Emu.GetIdManager().RemoveID(fd); return CELL_OK; } @@ -151,13 +165,15 @@ s32 sys_fs_opendir(vm::ptr path, vm::ptr fd) sys_fs.Warning("sys_fs_opendir(path=*0x%x, fd=*0x%x)", path, fd); sys_fs.Warning("*** path = '%s'", path.get_ptr()); - std::shared_ptr dir(Emu.GetVFS().OpenDir(path.get_ptr())); - if (!dir || !dir->IsOpened()) + std::shared_ptr directory(Emu.GetVFS().OpenDir(path.get_ptr())); + + if (!directory || !directory->IsOpened()) { - return CELL_ENOENT; + return CELL_FS_ENOENT; } - *fd = Emu.GetIdManager().GetNewID(dir, TYPE_FS_DIR); + *fd = Emu.GetIdManager().GetNewID(directory, TYPE_FS_DIR); + return CELL_OK; } @@ -166,10 +182,14 @@ s32 sys_fs_readdir(u32 fd, vm::ptr dir, vm::ptr nread) sys_fs.Warning("sys_fs_readdir(fd=0x%x, dir=*0x%x, nread=*0x%x)", fd, dir, nread); std::shared_ptr directory; + if (!Emu.GetIdManager().GetIDData(fd, directory)) + { return CELL_ESRCH; + } const DirEntryInfo* info = directory->Read(); + if (info) { dir->d_type = (info->flags & DirEntry_TypeFile) ? CELL_FS_TYPE_REGULAR : CELL_FS_TYPE_DIRECTORY; @@ -187,10 +207,16 @@ s32 sys_fs_readdir(u32 fd, vm::ptr dir, vm::ptr nread) s32 sys_fs_closedir(u32 fd) { - sys_fs.Warning("sys_fs_closedir(fd=0x%x)", fd); + sys_fs.Log("sys_fs_closedir(fd=0x%x)", fd); - if (!Emu.GetIdManager().RemoveID(fd)) + std::shared_ptr directory; + + if (!Emu.GetIdManager().GetIDData(fd, directory)) + { return CELL_ESRCH; + } + + Emu.GetIdManager().RemoveID(fd); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_fs.h b/rpcs3/Emu/SysCalls/lv2/sys_fs.h index f54eeeb047..546544613e 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_fs.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_fs.h @@ -61,15 +61,15 @@ enum : s32 // Open Flags enum : s32 { - CELL_FS_O_RDONLY = 000000, - CELL_FS_O_WRONLY = 000001, - CELL_FS_O_RDWR = 000002, + CELL_FS_O_RDONLY = 000000, + CELL_FS_O_WRONLY = 000001, + CELL_FS_O_RDWR = 000002, CELL_FS_O_ACCMODE = 000003, - CELL_FS_O_CREAT = 000100, - CELL_FS_O_EXCL = 000200, - CELL_FS_O_TRUNC = 001000, - CELL_FS_O_APPEND = 002000, - CELL_FS_O_MSELF = 010000, + CELL_FS_O_CREAT = 000100, + CELL_FS_O_EXCL = 000200, + CELL_FS_O_TRUNC = 001000, + CELL_FS_O_APPEND = 002000, + CELL_FS_O_MSELF = 010000, }; // Seek Mode @@ -111,10 +111,10 @@ enum CellFsMode : s32 // CellFsDirent.d_type enum : u8 { - CELL_FS_TYPE_UNKNOWN = 0, + CELL_FS_TYPE_UNKNOWN = 0, CELL_FS_TYPE_DIRECTORY = 1, - CELL_FS_TYPE_REGULAR = 2, - CELL_FS_TYPE_SYMLINK = 3, + CELL_FS_TYPE_REGULAR = 2, + CELL_FS_TYPE_SYMLINK = 3, }; struct CellFsDirent