mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 20:15:27 +00:00
cellFsGetDirectoryEntries rewritten
This commit is contained in:
parent
d05b6135c6
commit
0f95736c36
4 changed files with 94 additions and 37 deletions
|
@ -260,49 +260,37 @@ s32 cellFsGetFreeSize(vm::cptr<char> path, vm::ptr<u32> block_size, vm::ptr<u64>
|
|||
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;
|
||||
}
|
||||
|
||||
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++)
|
||||
{
|
||||
fs::dir_entry info;
|
||||
op->op = 0xe0000012;
|
||||
op->arg._code = 0;
|
||||
op->arg._size = 0;
|
||||
op->arg.ptr = entries;
|
||||
op->arg.max = entries_size / sizeof(CellFsDirectoryEntry);
|
||||
|
||||
if (directory->dir.read(info))
|
||||
{
|
||||
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; // ???
|
||||
// Call the syscall
|
||||
const s32 rc = sys_fs_fcntl(fd, 0xe0000012, op.ptr(&lv2_file_op_dir::arg), 0x10);
|
||||
|
||||
entries[count].entry_name.d_type = info.is_directory ? CELL_FS_TYPE_DIRECTORY : CELL_FS_TYPE_REGULAR;
|
||||
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 = op->arg._size;
|
||||
|
||||
*data_count = count;
|
||||
|
||||
return CELL_OK;
|
||||
// Select the result
|
||||
return not_an_error(rc ? rc : +op->arg._code);
|
||||
}
|
||||
|
||||
error_code cellFsReadWithOffset(u32 fd, u64 offset, vm::ptr<void> buf, u64 buffer_size, vm::ptr<u64> nread)
|
||||
|
|
|
@ -2,12 +2,6 @@
|
|||
|
||||
#include "Emu/Cell/lv2/sys_fs.h"
|
||||
|
||||
struct CellFsDirectoryEntry
|
||||
{
|
||||
CellFsStat attribute;
|
||||
CellFsDirent entry_name;
|
||||
};
|
||||
|
||||
// CellFsRingBuffer.copy
|
||||
enum : s32
|
||||
{
|
||||
|
|
|
@ -675,6 +675,53 @@ error_code sys_fs_fcntl(u32 fd, u32 op, vm::ptr<void> _arg, u32 _size)
|
|||
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:
|
||||
{
|
||||
sys_fs.todo("sys_fs_fcntl(): Unknown operation 0x%08x (fd=%d, arg=*0x%x, size=0x%x)", op, fd, _arg, _size);
|
||||
|
|
|
@ -83,6 +83,12 @@ struct CellFsStat
|
|||
|
||||
CHECK_SIZE_ALIGN(CellFsStat, 52, 4);
|
||||
|
||||
struct CellFsDirectoryEntry
|
||||
{
|
||||
CellFsStat attribute;
|
||||
CellFsDirent entry_name;
|
||||
};
|
||||
|
||||
struct CellFsUtimbuf
|
||||
{
|
||||
be_t<s64, 4> actime;
|
||||
|
@ -238,6 +244,28 @@ struct lv2_file_op_09 : lv2_file_op
|
|||
|
||||
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
|
||||
|
||||
error_code sys_fs_test(u32 arg1, u32 arg2, vm::ps3::ptr<u32> arg3, u32 arg4, vm::ps3::ptr<char> arg5, u32 arg6);
|
||||
|
|
Loading…
Add table
Reference in a new issue