cellFsGetDirectoryEntries rewritten

This commit is contained in:
Nekotekina 2017-04-22 15:29:20 +03:00
parent d05b6135c6
commit 0f95736c36
4 changed files with 94 additions and 37 deletions

View File

@ -260,49 +260,37 @@ s32 cellFsGetFreeSize(vm::cptr<char> path, vm::ptr<u32> block_size, vm::ptr<u64>
return CELL_OK; return CELL_OK;
} }
s32 cellFsGetDirectoryEntries(u32 fd, vm::ptr<CellFsDirectoryEntry> entries, u32 entries_size, vm::ptr<u32> data_count) error_code cellFsGetDirectoryEntries(u32 fd, vm::ptr<CellFsDirectoryEntry> entries, u32 entries_size, vm::ptr<u32> data_count)
{ {
cellFs.warning("cellFsGetDirectoryEntries(fd=%d, entries=*0x%x, entries_size=0x%x, data_count=*0x%x)", fd, entries, entries_size, data_count); cellFs.trace("cellFsGetDirectoryEntries(fd=%d, entries=*0x%x, entries_size=0x%x, data_count=*0x%x)", fd, entries, entries_size, data_count);
const auto directory = idm::get<lv2_fs_object, lv2_dir>(fd); if (!data_count || !entries)
{
return CELL_EFAULT;
}
if (!directory) if (fd - 3 > 252)
{ {
return CELL_EBADF; return CELL_EBADF;
} }
u32 count = 0; vm::var<lv2_file_op_dir> op;
entries_size /= sizeof(CellFsDirectoryEntry); op->_vtable = vm::cast(0xfae12000); // Intentionally wrong (provide correct vtable if necessary)
for (; count < entries_size; count++) op->op = 0xe0000012;
{ op->arg._code = 0;
fs::dir_entry info; op->arg._size = 0;
op->arg.ptr = entries;
op->arg.max = entries_size / sizeof(CellFsDirectoryEntry);
if (directory->dir.read(info)) // Call the syscall
{ const s32 rc = sys_fs_fcntl(fd, 0xe0000012, op.ptr(&lv2_file_op_dir::arg), 0x10);
entries[count].attribute.mode = info.is_directory ? CELL_FS_S_IFDIR | 0777 : CELL_FS_S_IFREG | 0666;
entries[count].attribute.uid = 1; // ???
entries[count].attribute.gid = 1; // ???
entries[count].attribute.atime = info.atime;
entries[count].attribute.mtime = info.mtime;
entries[count].attribute.ctime = info.ctime;
entries[count].attribute.size = info.size;
entries[count].attribute.blksize = 4096; // ???
entries[count].entry_name.d_type = info.is_directory ? CELL_FS_TYPE_DIRECTORY : CELL_FS_TYPE_REGULAR; *data_count = op->arg._size;
entries[count].entry_name.d_namlen = u8(std::min<size_t>(info.name.size(), CELL_FS_MAX_FS_FILE_NAME_LENGTH));
strcpy_trunc(entries[count].entry_name.d_name, info.name);
}
else
{
break;
}
}
*data_count = count; // Select the result
return not_an_error(rc ? rc : +op->arg._code);
return CELL_OK;
} }
error_code cellFsReadWithOffset(u32 fd, u64 offset, vm::ptr<void> buf, u64 buffer_size, vm::ptr<u64> nread) error_code cellFsReadWithOffset(u32 fd, u64 offset, vm::ptr<void> buf, u64 buffer_size, vm::ptr<u64> nread)

View File

@ -2,12 +2,6 @@
#include "Emu/Cell/lv2/sys_fs.h" #include "Emu/Cell/lv2/sys_fs.h"
struct CellFsDirectoryEntry
{
CellFsStat attribute;
CellFsDirent entry_name;
};
// CellFsRingBuffer.copy // CellFsRingBuffer.copy
enum : s32 enum : s32
{ {

View File

@ -675,6 +675,53 @@ error_code sys_fs_fcntl(u32 fd, u32 op, vm::ptr<void> _arg, u32 _size)
return CELL_EMFILE; return CELL_EMFILE;
} }
case 0xe0000012: // cellFsGetDirectoryEntries
{
const auto arg = vm::static_ptr_cast<lv2_file_op_dir::dir_info>(_arg);
if (_size < arg.size())
{
return CELL_EINVAL;
}
const auto directory = idm::get<lv2_fs_object, lv2_dir>(fd);
if (!directory)
{
return CELL_EBADF;
}
for (; arg->_size < arg->max; arg->_size++)
{
fs::dir_entry info;
if (directory->dir.read(info))
{
auto& entry = arg->ptr[arg->_size];
entry.attribute.mode = info.is_directory ? CELL_FS_S_IFDIR | 0777 : CELL_FS_S_IFREG | 0666;
entry.attribute.uid = 0;
entry.attribute.gid = 0;
entry.attribute.atime = info.atime;
entry.attribute.mtime = info.mtime;
entry.attribute.ctime = info.ctime;
entry.attribute.size = info.size;
entry.attribute.blksize = 4096; // ???
entry.entry_name.d_type = info.is_directory ? CELL_FS_TYPE_DIRECTORY : CELL_FS_TYPE_REGULAR;
entry.entry_name.d_namlen = u8(std::min<size_t>(info.name.size(), CELL_FS_MAX_FS_FILE_NAME_LENGTH));
strcpy_trunc(entry.entry_name.d_name, info.name);
}
else
{
break;
}
}
arg->_code = CELL_OK;
return CELL_OK;
}
default: default:
{ {
sys_fs.todo("sys_fs_fcntl(): Unknown operation 0x%08x (fd=%d, arg=*0x%x, size=0x%x)", op, fd, _arg, _size); sys_fs.todo("sys_fs_fcntl(): Unknown operation 0x%08x (fd=%d, arg=*0x%x, size=0x%x)", op, fd, _arg, _size);

View File

@ -83,6 +83,12 @@ struct CellFsStat
CHECK_SIZE_ALIGN(CellFsStat, 52, 4); CHECK_SIZE_ALIGN(CellFsStat, 52, 4);
struct CellFsDirectoryEntry
{
CellFsStat attribute;
CellFsDirent entry_name;
};
struct CellFsUtimbuf struct CellFsUtimbuf
{ {
be_t<s64, 4> actime; be_t<s64, 4> actime;
@ -238,6 +244,28 @@ struct lv2_file_op_09 : lv2_file_op
CHECK_SIZE(lv2_file_op_09, 0x40); CHECK_SIZE(lv2_file_op_09, 0x40);
// sys_fs_fnctl: cellFsGetDirectoryEntries
struct lv2_file_op_dir : lv2_file_op
{
struct dir_info : lv2_file_op
{
be_t<s32> _code; // Op result
be_t<u32> _size; // Number of entries written
vm::bptrb<CellFsDirectoryEntry> ptr;
be_t<u32> max;
};
CHECK_SIZE(dir_info, 0x10);
vm::bptrb<vtable::lv2_file_op> _vtable;
be_t<u32> op;
be_t<u32> _x8;
dir_info arg;
};
CHECK_SIZE(lv2_file_op_dir, 0x1c);
// Syscalls // Syscalls
error_code sys_fs_test(u32 arg1, u32 arg2, vm::ps3::ptr<u32> arg3, u32 arg4, vm::ps3::ptr<char> arg5, u32 arg6); error_code sys_fs_test(u32 arg1, u32 arg2, vm::ps3::ptr<u32> arg3, u32 arg4, vm::ps3::ptr<char> arg5, u32 arg6);