61 lines
1.4 KiB
C++
61 lines
1.4 KiB
C++
#define MODULE "dir"
|
|
|
|
#include "luna/dirent.h"
|
|
#include "fs/VFS.h"
|
|
#include "interrupts/Context.h"
|
|
#include "std/errno.h"
|
|
#include "std/string.h"
|
|
#include "sys/UserMemory.h"
|
|
#include "thread/Scheduler.h"
|
|
|
|
void sys_getdents(Context* context, int fd, struct luna_dirent* buf, size_t count)
|
|
{
|
|
if (fd < 0 || fd > TASK_MAX_FDS)
|
|
{
|
|
context->rax = -EBADF;
|
|
return;
|
|
}
|
|
Task* current_task = Scheduler::current_task();
|
|
if (!current_task->files[fd].is_open())
|
|
{
|
|
context->rax = -EBADF;
|
|
return;
|
|
}
|
|
Descriptor& dir = current_task->files[fd];
|
|
VFS::Node* node = dir.node();
|
|
if (node->type != VFS_DIRECTORY)
|
|
{
|
|
context->rax = -ENOTDIR;
|
|
return;
|
|
}
|
|
size_t nread = 0;
|
|
while (count)
|
|
{
|
|
VFS::Node* entry = VFS::readdir(node, dir.offset());
|
|
if (!entry)
|
|
{
|
|
context->rax = nread;
|
|
return;
|
|
}
|
|
|
|
auto* kdirent = obtain_user_ref(buf);
|
|
if (!kdirent)
|
|
{
|
|
context->rax = -EFAULT;
|
|
return;
|
|
}
|
|
|
|
kdirent->total = node->length;
|
|
kdirent->offset = dir.offset();
|
|
kdirent->inode = entry->inode;
|
|
strlcpy(kdirent->name, entry->name, sizeof(kdirent->name));
|
|
|
|
release_user_ref(kdirent);
|
|
|
|
dir.seek(dir.offset() + 1);
|
|
buf++;
|
|
nread++;
|
|
count--;
|
|
}
|
|
context->rax = nread;
|
|
} |