Kernel/syscalls: Modify sys_write to accept a file descriptor and write to it
Previously, sys_write only wrote to the tty. Now, it uses the VFS interface, as it should.
This commit is contained in:
parent
e764647133
commit
12cf37d0a7
@ -24,7 +24,7 @@ namespace Syscall
|
|||||||
void sys_exit(Context* context, int status);
|
void sys_exit(Context* context, int status);
|
||||||
void sys_yield(Context* context);
|
void sys_yield(Context* context);
|
||||||
void sys_sleep(Context* context, uint64_t ms);
|
void sys_sleep(Context* context, uint64_t ms);
|
||||||
void sys_write(Context* context, const char* addr, size_t size);
|
void sys_write(Context* context, int fd, size_t size, const char* addr);
|
||||||
void sys_paint(Context* context, uint64_t x, uint64_t y, uint64_t w, uint64_t h, uint64_t col);
|
void sys_paint(Context* context, uint64_t x, uint64_t y, uint64_t w, uint64_t h, uint64_t col);
|
||||||
void sys_rand(Context* context);
|
void sys_rand(Context* context);
|
||||||
void sys_getversion(Context* context, char* buffer, size_t max);
|
void sys_getversion(Context* context, char* buffer, size_t max);
|
||||||
|
@ -18,7 +18,7 @@ void Syscall::entry(Context* context)
|
|||||||
sys_sleep(context, context->rdi);
|
sys_sleep(context, context->rdi);
|
||||||
break;
|
break;
|
||||||
case SYS_write: // sys_write
|
case SYS_write: // sys_write
|
||||||
sys_write(context, (const char*)context->rdi, context->rsi);
|
sys_write(context, (int)context->rdi, context->rsi, (const char*)context->rdx);
|
||||||
break;
|
break;
|
||||||
case SYS_paint: sys_paint(context, context->rdi, context->rsi, context->rdx, context->r10, context->r8); break;
|
case SYS_paint: sys_paint(context, context->rdi, context->rsi, context->rdx, context->r10, context->r8); break;
|
||||||
case SYS_rand: sys_rand(context); break;
|
case SYS_rand: sys_rand(context); break;
|
||||||
|
@ -8,12 +8,44 @@
|
|||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
#include "thread/Task.h"
|
#include "thread/Task.h"
|
||||||
|
|
||||||
|
#define OPEN_READ 1
|
||||||
|
#define OPEN_WRITE 2
|
||||||
|
|
||||||
#define STDIO_FAIL(function, error) kwarnln("%s failed with %s", #function, #error)
|
#define STDIO_FAIL(function, error) kwarnln("%s failed with %s", #function, #error)
|
||||||
|
|
||||||
void sys_write(Context* context, const char* addr, size_t size)
|
void sys_write(Context* context, int fd, size_t size, const char* addr)
|
||||||
{
|
{
|
||||||
context->rax = size;
|
if (!addr)
|
||||||
TextRenderer::write(addr, size);
|
{
|
||||||
|
STDIO_FAIL(write, EINVAL);
|
||||||
|
context->rax = -EINVAL; // FIXME: This should probably return EFAULT.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fd >= TASK_MAX_FDS || fd < 0)
|
||||||
|
{
|
||||||
|
kwarnln("file descriptor %d is outside the valid range", fd);
|
||||||
|
STDIO_FAIL(write, EBADF);
|
||||||
|
context->rax = -EBADF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Task* current_task = Scheduler::current_task();
|
||||||
|
if (!current_task->files[fd].is_open())
|
||||||
|
{
|
||||||
|
kwarnln("file descriptor %d is not open", fd);
|
||||||
|
STDIO_FAIL(write, EBADF);
|
||||||
|
context->rax = -EBADF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!current_task->files[fd].can_write())
|
||||||
|
{
|
||||||
|
kwarnln("file descriptor %d is not open for writing", fd);
|
||||||
|
STDIO_FAIL(write, EBADF);
|
||||||
|
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)
|
void sys_open(Context* context, const char* filename, int flags)
|
||||||
@ -24,12 +56,14 @@ void sys_open(Context* context, const char* filename, int flags)
|
|||||||
{
|
{
|
||||||
if (!current_task->files[fd].is_open()) break;
|
if (!current_task->files[fd].is_open()) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd == TASK_MAX_FDS)
|
if (fd == TASK_MAX_FDS)
|
||||||
{
|
{
|
||||||
STDIO_FAIL(open, EMFILE);
|
STDIO_FAIL(open, EMFILE);
|
||||||
context->rax = -EMFILE;
|
context->rax = -EMFILE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VFS::Node* node = VFS::resolve_path(filename);
|
VFS::Node* node = VFS::resolve_path(filename);
|
||||||
if (!node)
|
if (!node)
|
||||||
{
|
{
|
||||||
@ -37,9 +71,23 @@ void sys_open(Context* context, const char* filename, int flags)
|
|||||||
context->rax = -ENOENT;
|
context->rax = -ENOENT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
kdbgln("open(): opening %s, allocated file descriptor %d", filename, fd);
|
|
||||||
current_task->files[fd].open(node,
|
bool can_read = (flags & OPEN_READ) > 0;
|
||||||
(bool)flags); // FIXME: Implement more flags. (right now, 1 is can_read, 0 is not)
|
bool can_write = (flags & OPEN_WRITE) > 0;
|
||||||
|
if (!can_read && !can_write)
|
||||||
|
{
|
||||||
|
STDIO_FAIL(open, EINVAL);
|
||||||
|
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;
|
context->rax = fd;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ extern "C"
|
|||||||
unsigned int sleep(unsigned int);
|
unsigned int sleep(unsigned int);
|
||||||
|
|
||||||
ssize_t read(int, void*, size_t);
|
ssize_t read(int, void*, size_t);
|
||||||
|
ssize_t write(int, const void*, size_t);
|
||||||
int close(int);
|
int close(int);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -37,7 +37,6 @@ extern "C"
|
|||||||
case SYS_exit:
|
case SYS_exit:
|
||||||
case SYS_close:
|
case SYS_close:
|
||||||
case SYS_sleep: result = __luna_syscall1(number, va_arg(ap, arg)); break;
|
case SYS_sleep: result = __luna_syscall1(number, va_arg(ap, arg)); break;
|
||||||
case SYS_write:
|
|
||||||
case SYS_munmap:
|
case SYS_munmap:
|
||||||
case SYS_open:
|
case SYS_open:
|
||||||
case SYS_getversion: {
|
case SYS_getversion: {
|
||||||
@ -46,6 +45,7 @@ extern "C"
|
|||||||
result = __luna_syscall2(number, arg0, arg1);
|
result = __luna_syscall2(number, arg0, arg1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SYS_write:
|
||||||
case SYS_read:
|
case SYS_read:
|
||||||
case SYS_mmap: {
|
case SYS_mmap: {
|
||||||
arg arg0 = va_arg(ap, arg);
|
arg arg0 = va_arg(ap, arg);
|
||||||
@ -80,6 +80,11 @@ extern "C"
|
|||||||
return syscall(SYS_read, fd, count, buf); // yes, our read() syscall is in the wrong order.
|
return syscall(SYS_read, fd, count, buf); // yes, our read() syscall is in the wrong order.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t write(int fd, const void* buf, size_t count)
|
||||||
|
{
|
||||||
|
return syscall(SYS_write, fd, count, buf); // yes, our read() syscall is in the wrong order.
|
||||||
|
}
|
||||||
|
|
||||||
int close(int fd)
|
int close(int fd)
|
||||||
{
|
{
|
||||||
return (int)syscall(SYS_close, fd);
|
return (int)syscall(SYS_close, fd);
|
||||||
|
Loading…
Reference in New Issue
Block a user