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

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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; }

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(; 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

View File

@ -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;

View File

@ -199,10 +199,10 @@ public:
};
// 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_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_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_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 = 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_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)
{

View File

@ -117,6 +117,16 @@ namespace vm
{
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&()
{
@ -614,6 +624,16 @@ namespace vm
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&()
{
return *m_data.ptr;

View File

@ -537,13 +537,20 @@ int sdata_unpack(const std::string& packed_file, const std::string& unpacked_fil
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)
return CELL_EINVAL;
if (flags != CELL_FS_O_RDONLY)
{
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);
if (suffix != ".sdat" && suffix != ".SDAT")
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);
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<u32> sdata_fd, u64 offset, vm::ptr<const void> arg, u64 size)

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)
{
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<vfsStream> 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<vfsStream> 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<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);
std::shared_ptr<vfsStream> 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<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);
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;
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<vfsStream>(fd))
return CELL_ESRCH;
std::shared_ptr<vfsStream> file;
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;
}
@ -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("*** path = '%s'", path.get_ptr());
std::shared_ptr<vfsDirBase> dir(Emu.GetVFS().OpenDir(path.get_ptr()));
if (!dir || !dir->IsOpened())
std::shared_ptr<vfsDirBase> 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<CellFsDirent> dir, vm::ptr<u64> nread)
sys_fs.Warning("sys_fs_readdir(fd=0x%x, dir=*0x%x, nread=*0x%x)", fd, dir, nread);
std::shared_ptr<vfsDirBase> 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<CellFsDirent> dir, vm::ptr<u64> 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<vfsDirBase>(fd))
std::shared_ptr<vfsDirBase> directory;
if (!Emu.GetIdManager().GetIDData(fd, directory))
{
return CELL_ESRCH;
}
Emu.GetIdManager().RemoveID<vfsDirBase>(fd);
return CELL_OK;
}

View File

@ -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