Luna/kernel/src/sys/stdio.cpp

168 lines
3.8 KiB
C++
Raw Normal View History

#define MODULE "stdio"
#include "errno.h"
2022-09-29 17:17:43 +00:00
#include "interrupts/Context.h"
#include "io/Serial.h"
#include "log/Log.h"
#include "render/TextRenderer.h"
#include "thread/Scheduler.h"
#include "thread/Task.h"
#define OPEN_READ 1
#define OPEN_WRITE 2
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
void sys_seek(Context* context, int fd, long offset, int whence)
{
if (whence < SEEK_SET || whence > SEEK_END)
{
context->rax = -EINVAL;
return;
}
if (fd >= TASK_MAX_FDS || fd < 0)
{
context->rax = -EBADF;
return;
}
Task* current_task = Scheduler::current_task();
if (!current_task->files[fd].is_open())
{
context->rax = -EBADF;
return;
}
long new_offset;
if (whence == SEEK_SET) new_offset = offset;
else if (whence == SEEK_CUR)
new_offset = offset + current_task->files[fd].offset();
else if (whence == SEEK_END)
new_offset = current_task->files[fd].length() + offset;
else
__builtin_unreachable();
if (new_offset < 0)
{
context->rax = -EINVAL; // FIXME: Is this the right error?
return;
}
int result = current_task->files[fd].seek(new_offset);
if (result < 0)
{
context->rax = result;
return;
}
context->rax = new_offset;
return;
}
void sys_write(Context* context, int fd, size_t size, const char* addr)
2022-09-29 17:17:43 +00:00
{
if (!addr)
{
2022-10-12 17:25:35 +00:00
context->rax = -EFAULT;
return;
}
if (fd >= TASK_MAX_FDS || fd < 0)
{
context->rax = -EBADF;
return;
}
Task* current_task = Scheduler::current_task();
if (!current_task->files[fd].is_open())
{
context->rax = -EBADF;
return;
}
if (!current_task->files[fd].can_write())
{
context->rax = -EBADF;
return;
}
ssize_t result = current_task->files[fd].write(size, addr);
context->rax = (size_t)result;
return;
}
void sys_open(Context* context, const char* filename, int flags)
{
Task* current_task = Scheduler::current_task();
int fd;
for (fd = 0; fd < TASK_MAX_FDS; fd++)
{
if (!current_task->files[fd].is_open()) break;
}
if (fd == TASK_MAX_FDS)
{
context->rax = -EMFILE;
return;
}
VFS::Node* node = VFS::resolve_path(filename);
if (!node)
{
context->rax = -ENOENT;
return;
}
bool can_read = (flags & OPEN_READ) > 0;
bool can_write = (flags & OPEN_WRITE) > 0;
if (!can_read && !can_write)
{
context->rax = -EINVAL;
return;
}
kdbgln("open(): opening %s %s, allocated file descriptor %d", filename,
(can_read && can_write) ? "rw"
: can_read ? "r-"
: "-w",
fd);
current_task->files[fd].open(node, can_read, can_write);
context->rax = fd;
return;
}
void sys_read(Context* context, int fd, size_t size, char* buffer)
{
if (!buffer)
{
2022-10-12 17:25:35 +00:00
context->rax = -EFAULT;
return;
}
2022-10-11 15:10:44 +00:00
if (fd >= TASK_MAX_FDS || fd < 0)
{
context->rax = -EBADF;
return;
}
Task* current_task = Scheduler::current_task();
2022-10-11 15:10:44 +00:00
if (!current_task->files[fd].is_open() || !current_task->files[fd].can_read())
{
context->rax = -EBADF;
return;
}
ssize_t result = current_task->files[fd].read(size, buffer);
context->rax = (size_t)result;
return;
}
void sys_close(Context* context, int fd)
{
2022-10-11 15:10:44 +00:00
if (fd >= TASK_MAX_FDS || fd < 0)
{
context->rax = -EBADF;
return;
}
Task* current_task = Scheduler::current_task();
if (!current_task->files[fd].is_open())
{
context->rax = -EBADF;
return;
}
2022-10-11 15:19:03 +00:00
kdbgln("close(): releasing file descriptor %d", fd);
current_task->files[fd].close();
context->rax = 0;
return;
2022-09-29 17:17:43 +00:00
}