sys_fs_open rewritten

This commit is contained in:
Nekotekina
2015-03-13 18:06:27 +03:00
parent 3e34bd64bf
commit 6c36013e2a
12 changed files with 158 additions and 106 deletions
+2 -2
View File
@@ -161,7 +161,7 @@ vfsDirBase* VFS::OpenDir(const std::string& ps3_path) const
return nullptr; 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; std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path)) if (vfsDevice* dev = GetDevice(ps3_path, path))
@@ -170,7 +170,7 @@ bool VFS::CreateFile(const std::string& ps3_path) const
if (res) if (res)
{ {
return res->Create(path); return res->Create(path, overwrite);
} }
} }
+1 -1
View File
@@ -78,7 +78,7 @@ struct VFS
vfsFileBase* OpenFile(const std::string& ps3_path, vfsOpenMode mode) const; vfsFileBase* OpenFile(const std::string& ps3_path, vfsOpenMode mode) const;
vfsDirBase* OpenDir(const std::string& ps3_path) 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 CreateDir(const std::string& ps3_path) const;
bool RemoveFile(const std::string& ps3_path) const; bool RemoveFile(const std::string& ps3_path) const;
bool RemoveDir(const std::string& ps3_path) const; bool RemoveDir(const std::string& ps3_path) const;
+2 -2
View File
@@ -26,9 +26,9 @@ bool vfsFile::Open(const std::string& path, vfsOpenMode mode)
return m_stream && m_stream->IsOpened(); 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) bool vfsFile::Exists(const std::string& path)
+1 -1
View File
@@ -11,7 +11,7 @@ public:
vfsFile(const std::string& path, vfsOpenMode mode = vfsRead); vfsFile(const std::string& path, vfsOpenMode mode = vfsRead);
virtual bool Open(const std::string& path, vfsOpenMode mode = vfsRead) override; 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 Exists(const std::string& path) override;
virtual bool Rename(const std::string& from, const std::string& to) override; virtual bool Rename(const std::string& from, const std::string& to) override;
virtual bool Remove(const std::string& path) override; virtual bool Remove(const std::string& path) override;
+1 -1
View File
@@ -27,7 +27,7 @@ public:
virtual bool Open(const std::string& path, vfsOpenMode mode); virtual bool Open(const std::string& path, vfsOpenMode mode);
virtual bool Close() override; 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 Exists(const std::string& path) { return false; }
virtual bool Rename(const std::string& from, const std::string& to) { return false; } virtual bool Rename(const std::string& from, const std::string& to) { return false; }
virtual bool Remove(const std::string& path) { return false; } virtual bool Remove(const std::string& path) { return false; }
+4 -4
View File
@@ -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(uint p=1; p < path.length() && path[p] != '\0' ; p++)
{ {
for(; 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)) // ??? if(m != '/' && m != '\\' && !rExists(path)) // ???
{ {
rFile f; rFile f;
if (!f.Create(path)) { if (!f.Create(path, overwrite)) {
LOG_NOTICE(HLE, "vfsLocalFile::Create: couldn't create file"); if (overwrite) LOG_NOTICE(HLE, "vfsLocalFile::Create: couldn't create file");
return false; return false;
} }
else else
+1 -1
View File
@@ -11,7 +11,7 @@ public:
vfsLocalFile(vfsDevice* device); vfsLocalFile(vfsDevice* device);
virtual bool Open(const std::string& path, vfsOpenMode mode = vfsRead) override; 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 Close() override;
virtual bool Exists(const std::string& path) override; virtual bool Exists(const std::string& path) override;
+4 -4
View File
@@ -199,10 +199,10 @@ public:
}; };
// Helper definitions // Helper definitions
template<typename T, typename T2 = T> using if_arithmetic_t = typename std::enable_if<std::is_arithmetic<T>::value && std::is_arithmetic<T2>::value, T>::type; template<typename T, typename T2 = T> using if_arithmetic_t = const typename std::enable_if<std::is_arithmetic<T>::value && std::is_arithmetic<T2>::value, T>::type;
template<typename T, typename T2 = T> using if_arithmetic_be_t = typename std::enable_if<std::is_arithmetic<T>::value && std::is_arithmetic<T2>::value, be_t<T>>::type; template<typename T, typename T2 = T> using if_arithmetic_be_t = const typename std::enable_if<std::is_arithmetic<T>::value && std::is_arithmetic<T2>::value, be_t<T>>::type;
template<typename T, typename T2 = T> using if_arithmetic_atomic_t = typename std::enable_if<std::is_arithmetic<T>::value && std::is_arithmetic<T2>::value, _atomic_base<T>>::type; template<typename T, typename T2 = T> using if_arithmetic_atomic_t = typename std::enable_if<std::is_arithmetic<T>::value && std::is_arithmetic<T2>::value, _atomic_base<T>&>::type;
template<typename T, typename T2 = T> using if_arithmetic_atomic_be_t = typename std::enable_if<std::is_arithmetic<T>::value && std::is_arithmetic<T2>::value, _atomic_base<be_t<T>>>::type; template<typename T, typename T2 = T> using if_arithmetic_atomic_be_t = typename std::enable_if<std::is_arithmetic<T>::value && std::is_arithmetic<T2>::value, _atomic_base<be_t<T>>&>::type;
template<typename T> inline static if_arithmetic_t<T> operator ++(_atomic_base<T>& left) template<typename T> inline static if_arithmetic_t<T> operator ++(_atomic_base<T>& left)
{ {
+20
View File
@@ -118,6 +118,16 @@ namespace vm
return _ptr_base<const T, 1, AT>::make(m_addr); return _ptr_base<const T, 1, AT>::make(m_addr);
} }
template<typename AT> operator _ptr_base<void, 1, AT>() const
{
return _ptr_base<void, 1, AT>::make(m_data.addr);
}
template<typename AT> operator _ptr_base<const void, 1, AT>() const
{
return _ptr_base<const void, 1, AT>::make(m_data.addr);
}
operator T&() operator T&()
{ {
return *m_ptr; return *m_ptr;
@@ -614,6 +624,16 @@ namespace vm
return _ptr_base<const T, 1, AT>::make(m_data.addr); return _ptr_base<const T, 1, AT>::make(m_data.addr);
} }
template<typename AT> operator _ptr_base<void, 1, AT>() const
{
return _ptr_base<void, 1, AT>::make(m_data.addr);
}
template<typename AT> operator _ptr_base<const void, 1, AT>() const
{
return _ptr_base<const void, 1, AT>::make(m_data.addr);
}
operator T&() operator T&()
{ {
return *m_data.ptr; return *m_data.ptr;
+12 -6
View File
@@ -537,13 +537,20 @@ int sdata_unpack(const std::string& packed_file, const std::string& unpacked_fil
return CELL_OK; return CELL_OK;
} }
s32 cellFsSdataOpen(vm::ptr<const char> path, s32 flags, vm::ptr<u32> fd, vm::ptr<const void> arg, u64 size) s32 cellFsSdataOpen(PPUThread& CPU, vm::ptr<const char> path, s32 flags, vm::ptr<u32> fd, vm::ptr<const void> 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) if (flags != CELL_FS_O_RDONLY)
{
return CELL_EINVAL; return CELL_EINVAL;
}
return cellFsOpen(path, CELL_FS_O_RDONLY, fd, vm::stackvar<be_t<u64>>(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); std::string suffix = path.substr(path.length() - 5, 5);
if (suffix != ".sdat" && suffix != ".SDAT") if (suffix != ".sdat" && suffix != ".SDAT")
return CELL_ENOTSDATA; return CELL_ENOTSDATA;
@@ -556,9 +563,8 @@ s32 cellFsSdataOpen(vm::ptr<const char> path, s32 flags, vm::ptr<u32> fd, vm::pt
fd = Emu.GetIdManager().GetNewID(Emu.GetVFS().OpenFile(unpacked_path, vfsRead), TYPE_FS_FILE); fd = Emu.GetIdManager().GetNewID(Emu.GetVFS().OpenFile(unpacked_path, vfsRead), TYPE_FS_FILE);
return CELL_OK;*/ return CELL_OK;
*/
return sys_fs_open(path, flags, fd, 0, arg, size);
} }
s32 cellFsSdataOpenByFd(u32 mself_fd, s32 flags, vm::ptr<u32> sdata_fd, u64 offset, vm::ptr<const void> arg, u64 size) s32 cellFsSdataOpenByFd(u32 mself_fd, s32 flags, vm::ptr<u32> sdata_fd, u64 offset, vm::ptr<const void> arg, u64 size)
+97 -71
View File
@@ -22,83 +22,87 @@ SysCallBase sys_fs("sys_fs");
s32 sys_fs_open(vm::ptr<const char> path, s32 flags, vm::ptr<u32> fd, u32 mode, vm::ptr<const void> arg, u64 size) s32 sys_fs_open(vm::ptr<const char> path, s32 flags, vm::ptr<u32> fd, u32 mode, vm::ptr<const void> 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()); sys_fs.Warning("*** path = '%s'", path.get_ptr());
const std::string _path = path.get_ptr(); std::shared_ptr<vfsStream> file;
s32 _oflags = flags; if (mode)
if (flags & CELL_FS_O_CREAT)
{ {
_oflags &= ~CELL_FS_O_CREAT; sys_fs.Error("sys_fs_open(): unknown mode (0x%x)", mode);
Emu.GetVFS().CreateFile(_path); 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: case CELL_FS_O_RDONLY:
_oflags &= ~CELL_FS_O_RDONLY; {
o_mode = vfsRead; file.reset(Emu.GetVFS().OpenFile(path.get_ptr(), vfsRead));
break; break;
}
//case CELL_FS_O_WRONLY:
//case CELL_FS_O_WRONLY | CELL_FS_O_CREAT:
case CELL_FS_O_WRONLY: case CELL_FS_O_WRONLY | CELL_FS_O_CREAT | CELL_FS_O_EXCL:
_oflags &= ~CELL_FS_O_WRONLY; {
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; return CELL_FS_EEXIST;
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;
} }
break; 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: case CELL_FS_O_RDWR:
_oflags &= ~CELL_FS_O_RDWR;
if (flags & CELL_FS_O_TRUNC)
{ {
_oflags &= ~CELL_FS_O_TRUNC; file.reset(Emu.GetVFS().OpenFile(path.get_ptr(), vfsReadWrite));
//truncate file before opening it as read/write
auto filePtr = Emu.GetVFS().OpenFile(_path, vfsWrite);
delete filePtr;
}
o_mode = vfsReadWrite;
break; break;
} }
case CELL_FS_O_RDWR | CELL_FS_O_CREAT:
if (_oflags != 0)
{ {
sys_fs.Error("sys_fs_open(): '%s' has unknown flags! flags: 0x%08x", path.get_ptr(), flags); Emu.GetVFS().CreateFile(path.get_ptr());
return CELL_EINVAL; 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); sys_fs.Error("sys_fs_open(): failed to open '%s' (flags=%d, mode=0x%x)", path.get_ptr(), flags, mode);
return CELL_ENOENT; return CELL_FS_ENOENT;
} }
std::shared_ptr<vfsStream> stream(Emu.GetVFS().OpenFile(_path, o_mode)); *fd = Emu.GetIdManager().GetNewID(file, TYPE_FS_FILE);
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);
return CELL_OK; return CELL_OK;
} }
@@ -108,14 +112,13 @@ s32 sys_fs_read(u32 fd, vm::ptr<void> buf, u64 nbytes, vm::ptr<u64> nread)
sys_fs.Log("sys_fs_read(fd=0x%x, buf=0x%x, nbytes=0x%llx, nread=0x%x)", fd, buf, nbytes, 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<vfsStream> file; std::shared_ptr<vfsStream> file;
if (!Emu.GetIdManager().GetIDData(fd, file)) if (!Emu.GetIdManager().GetIDData(fd, file))
return CELL_ESRCH; {
return CELL_FS_EBADF; // TODO: return if not opened for reading
}
// TODO: checks *nread = file->Read(buf.get_ptr(), nbytes);
const u64 res = nbytes ? file->Read(buf.get_ptr(), nbytes) : 0;
if (nread) *nread = res;
return CELL_OK; return CELL_OK;
} }
@@ -125,23 +128,34 @@ s32 sys_fs_write(u32 fd, vm::ptr<const void> buf, u64 nbytes, vm::ptr<u64> nwrit
sys_fs.Log("sys_fs_write(fd=0x%x, buf=*0x%x, nbytes=0x%llx, nwrite=*0x%x)", fd, buf, nbytes, nwrite); 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<vfsStream> file; std::shared_ptr<vfsStream> 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; *nwrite = file->Write(buf.get_ptr(), nbytes);
if (nwrite) *nwrite = res;
return CELL_OK; return CELL_OK;
} }
s32 sys_fs_close(u32 fd) 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<vfsStream>(fd)) std::shared_ptr<vfsStream> file;
return CELL_ESRCH;
if (!Emu.GetIdManager().GetIDData(fd, file))
{
return CELL_FS_EBADF;
}
if (false)
{
return CELL_FS_EBUSY; // TODO: return if locked
}
Emu.GetIdManager().RemoveID<vfsStream>(fd);
return CELL_OK; return CELL_OK;
} }
@@ -151,13 +165,15 @@ s32 sys_fs_opendir(vm::ptr<const char> path, vm::ptr<u32> fd)
sys_fs.Warning("sys_fs_opendir(path=*0x%x, fd=*0x%x)", path, fd); sys_fs.Warning("sys_fs_opendir(path=*0x%x, fd=*0x%x)", path, fd);
sys_fs.Warning("*** path = '%s'", path.get_ptr()); sys_fs.Warning("*** path = '%s'", path.get_ptr());
std::shared_ptr<vfsDirBase> dir(Emu.GetVFS().OpenDir(path.get_ptr())); std::shared_ptr<vfsDirBase> directory(Emu.GetVFS().OpenDir(path.get_ptr()));
if (!dir || !dir->IsOpened())
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; return CELL_OK;
} }
@@ -166,10 +182,14 @@ s32 sys_fs_readdir(u32 fd, vm::ptr<CellFsDirent> dir, vm::ptr<u64> nread)
sys_fs.Warning("sys_fs_readdir(fd=0x%x, dir=*0x%x, nread=*0x%x)", fd, dir, nread); sys_fs.Warning("sys_fs_readdir(fd=0x%x, dir=*0x%x, nread=*0x%x)", fd, dir, nread);
std::shared_ptr<vfsDirBase> directory; std::shared_ptr<vfsDirBase> directory;
if (!Emu.GetIdManager().GetIDData(fd, directory)) if (!Emu.GetIdManager().GetIDData(fd, directory))
{
return CELL_ESRCH; return CELL_ESRCH;
}
const DirEntryInfo* info = directory->Read(); const DirEntryInfo* info = directory->Read();
if (info) if (info)
{ {
dir->d_type = (info->flags & DirEntry_TypeFile) ? CELL_FS_TYPE_REGULAR : CELL_FS_TYPE_DIRECTORY; 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<CellFsDirent> dir, vm::ptr<u64> nread)
s32 sys_fs_closedir(u32 fd) 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<vfsDirBase>(fd)) std::shared_ptr<vfsDirBase> directory;
if (!Emu.GetIdManager().GetIDData(fd, directory))
{
return CELL_ESRCH; return CELL_ESRCH;
}
Emu.GetIdManager().RemoveID<vfsDirBase>(fd);
return CELL_OK; return CELL_OK;
} }