mirror of https://github.com/RPCS3/rpcs3.git
cellFsGetDirectoryEntries rewritten
This commit is contained in:
parent
d05b6135c6
commit
0f95736c36
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue