#define MODULE "stdio" #include "errno.h" #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 STDIO_FAIL(function, error) kwarnln("%s failed with %s", #function, #error) void sys_write(Context* context, const char* addr, size_t size) { context->rax = size; TextRenderer::write(addr, size); } 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) { 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; } kdbgln("open(): opening %s, allocated file descriptor %d", filename, fd); 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); context->rax = -EINVAL; // FIXME: This should probably return EFAULT. return; } if (fd >= TASK_MAX_FDS || fd < 0) { STDIO_FAIL(read, EBADF); context->rax = -EBADF; return; } Task* current_task = Scheduler::current_task(); if (!current_task->files[fd].is_open() || !current_task->files[fd].can_read()) { 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) { if (fd >= TASK_MAX_FDS || fd < 0) { 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; } kdbgln("close(): releasing file descriptor %d", fd); current_task->files[fd].close(); context->rax = 0; return; }