2022-10-10 18:21:39 +00:00
|
|
|
#define MODULE "stdio"
|
|
|
|
|
|
|
|
#include "errno.h"
|
2022-09-29 17:17:43 +00:00
|
|
|
#include "interrupts/Context.h"
|
|
|
|
#include "io/Serial.h"
|
2022-10-10 18:21:39 +00:00
|
|
|
#include "log/Log.h"
|
2022-10-01 12:27:45 +00:00
|
|
|
#include "render/TextRenderer.h"
|
2022-10-10 18:21:39 +00:00
|
|
|
#include "thread/Scheduler.h"
|
|
|
|
#include "thread/Task.h"
|
|
|
|
|
|
|
|
#define STDIO_FAIL(function, error) kwarnln("%s failed with %s", #function, #error)
|
2022-09-29 17:17:43 +00:00
|
|
|
|
|
|
|
void sys_write(Context* context, const char* addr, size_t size)
|
|
|
|
{
|
|
|
|
context->rax = size;
|
2022-10-01 12:27:45 +00:00
|
|
|
TextRenderer::write(addr, size);
|
2022-10-10 18:21:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void sys_open(Context* context, const char* filename, int flags)
|
|
|
|
{
|
|
|
|
Task* current_task = Scheduler::current_task();
|
2022-10-11 15:03:16 +00:00
|
|
|
int fd;
|
2022-10-10 18:21:39 +00:00
|
|
|
for (fd = 0; fd < TASK_MAX_FDS; fd++)
|
|
|
|
{
|
|
|
|
if (!current_task->files[fd].is_open()) break;
|
|
|
|
}
|
2022-10-11 15:03:16 +00:00
|
|
|
if (fd == TASK_MAX_FDS)
|
2022-10-10 18:21:39 +00:00
|
|
|
{
|
|
|
|
STDIO_FAIL(open, EMFILE);
|
|
|
|
context->rax = -EMFILE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
VFS::Node* node = VFS::resolve_path(filename);
|
|
|
|
if (!node)
|
|
|
|
{
|
|
|
|
STDIO_FAIL(open, ENOENT);
|
|
|
|
context->rax = -ENOENT;
|
|
|
|
return;
|
|
|
|
}
|
2022-10-11 15:19:03 +00:00
|
|
|
kdbgln("open(): opening %s, allocated file descriptor %d", filename, fd);
|
2022-10-10 18:21:39 +00:00
|
|
|
current_task->files[fd].open(node,
|
|
|
|
(bool)flags); // FIXME: Implement more flags. (right now, 1 is can_read, 0 is not)
|
|
|
|
context->rax = fd;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void sys_read(Context* context, int fd, size_t size, char* buffer)
|
|
|
|
{
|
|
|
|
if (!buffer)
|
|
|
|
{
|
|
|
|
STDIO_FAIL(read, EINVAL);
|
2022-10-11 15:10:44 +00:00
|
|
|
context->rax = -EINVAL; // FIXME: This should probably return EFAULT.
|
2022-10-10 18:21:39 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-10-11 15:10:44 +00:00
|
|
|
if (fd >= TASK_MAX_FDS || fd < 0)
|
2022-10-10 18:21:39 +00:00
|
|
|
{
|
|
|
|
STDIO_FAIL(read, EBADF);
|
|
|
|
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())
|
2022-10-10 18:21:39 +00:00
|
|
|
{
|
|
|
|
STDIO_FAIL(read, EBADF);
|
|
|
|
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)
|
2022-10-10 18:21:39 +00:00
|
|
|
{
|
|
|
|
STDIO_FAIL(close, EBADF);
|
|
|
|
context->rax = -EBADF;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Task* current_task = Scheduler::current_task();
|
|
|
|
if (!current_task->files[fd].is_open())
|
|
|
|
{
|
|
|
|
STDIO_FAIL(close, EBADF);
|
|
|
|
context->rax = -EBADF;
|
|
|
|
return;
|
|
|
|
}
|
2022-10-11 15:19:03 +00:00
|
|
|
kdbgln("close(): releasing file descriptor %d", fd);
|
2022-10-10 18:21:39 +00:00
|
|
|
current_task->files[fd].close();
|
|
|
|
context->rax = 0;
|
|
|
|
return;
|
2022-09-29 17:17:43 +00:00
|
|
|
}
|