2023-08-12 19:38:25 +00:00
|
|
|
#include "Pledge.h"
|
2023-03-28 19:28:56 +00:00
|
|
|
#include "fs/VFS.h"
|
|
|
|
#include "memory/MemoryManager.h"
|
|
|
|
#include "sys/Syscall.h"
|
|
|
|
#include "thread/Scheduler.h"
|
|
|
|
#include <bits/getdents.h>
|
|
|
|
|
|
|
|
Result<u64> sys_getdents(Registers*, SyscallArgs args)
|
|
|
|
{
|
|
|
|
int fd = (int)args[0];
|
|
|
|
luna_dirent* ent = (luna_dirent*)args[1];
|
|
|
|
usize count = (usize)args[2];
|
|
|
|
|
|
|
|
Thread* current = Scheduler::current();
|
2023-08-12 19:38:25 +00:00
|
|
|
TRY(check_pledge(current, Promise::p_stdio));
|
2023-03-28 19:28:56 +00:00
|
|
|
|
|
|
|
auto& descriptor = *TRY(current->resolve_fd(fd));
|
|
|
|
|
2023-07-27 17:21:23 +00:00
|
|
|
if (descriptor.inode()->type() != VFS::InodeType::Directory) return err(ENOTDIR);
|
2023-03-28 19:28:56 +00:00
|
|
|
|
|
|
|
usize nwrite = 0;
|
|
|
|
while (nwrite < count)
|
|
|
|
{
|
2023-04-07 08:55:04 +00:00
|
|
|
VFS::DirectoryEntry entry;
|
2023-07-27 17:21:23 +00:00
|
|
|
bool ok = descriptor.inode()->get(descriptor.offset).try_set_value(entry);
|
2023-04-07 08:55:04 +00:00
|
|
|
if (!ok) break;
|
2023-03-28 19:28:56 +00:00
|
|
|
|
|
|
|
descriptor.offset++;
|
|
|
|
|
|
|
|
luna_dirent kent;
|
2023-08-01 15:20:28 +00:00
|
|
|
kent.inode = entry.inode->metadata().inum;
|
2023-03-28 19:28:56 +00:00
|
|
|
strlcpy(kent.name, entry.name.chars(), entry.name.length() + 1);
|
|
|
|
|
|
|
|
if (!MemoryManager::copy_to_user_typed(ent, &kent)) return err(EFAULT);
|
|
|
|
|
|
|
|
ent++;
|
|
|
|
nwrite++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nwrite;
|
|
|
|
}
|