Kernel: Add a seek() system call

Now, time for libc support!!
This commit is contained in:
apio 2022-10-12 15:28:52 +02:00
parent 97b7572933
commit 854f585e1a
5 changed files with 72 additions and 4 deletions

View File

@ -29,6 +29,17 @@ struct Descriptor
void open(VFS::Node* node, bool can_read, bool can_write);
int seek(long offset);
long offset()
{
return (long)m_offset;
}
unsigned long length()
{
return m_node->length;
}
Descriptor(const Descriptor& other);
Descriptor();

View File

@ -14,6 +14,7 @@
#define SYS_open 9
#define SYS_read 10
#define SYS_close 11
#define SYS_seek 12
namespace Syscall
{
@ -31,4 +32,5 @@ void sys_mmap(Context* context, void* address, size_t size, int flags);
void sys_munmap(Context* context, void* address, size_t size);
void sys_open(Context* context, const char* filename, int flags);
void sys_read(Context* context, int fd, size_t size, char* buffer);
void sys_close(Context* context, int fd);
void sys_close(Context* context, int fd);
void sys_seek(Context* context, int fd, long offset, int whence);

View File

@ -1,4 +1,5 @@
#include "fs/FileDescriptor.h"
#include "errno.h"
Descriptor::Descriptor() : m_is_open(false)
{
@ -31,4 +32,11 @@ ssize_t Descriptor::write(size_t size, const char* buffer)
ssize_t result = VFS::write(m_node, m_offset, size, buffer);
m_offset += result;
return result;
}
int Descriptor::seek(long offset)
{
if (m_node->type != VFS_DEVICE && offset > m_node->length)
return -EINVAL; // FIXME: Support seeking beyond the current file's length.
m_offset = (uint64_t)offset;
}

View File

@ -20,6 +20,7 @@ void Syscall::entry(Context* context)
case SYS_open: sys_open(context, (const char*)context->rdi, (int)context->rsi); break;
case SYS_read: sys_read(context, (int)context->rdi, context->rsi, (char*)context->rdx); break;
case SYS_close: sys_close(context, (int)context->rdi); break;
case SYS_seek: sys_seek(context, (int)context->rdi, (long)context->rsi, (int)context->rdx);
default: context->rax = -ENOSYS; break;
}
}

View File

@ -11,8 +11,57 @@
#define OPEN_READ 1
#define OPEN_WRITE 2
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#define STDIO_FAIL(function, error) kwarnln("%s failed with %s", #function, #error)
void sys_seek(Context* context, int fd, long offset, int whence)
{
if (whence < SEEK_SET || whence > SEEK_END)
{
STDIO_FAIL(seek, EINVAL);
context->rax = -EINVAL;
return;
}
if (fd >= TASK_MAX_FDS || fd < 0)
{
STDIO_FAIL(seek, EBADF);
context->rax = -EBADF;
return;
}
Task* current_task = Scheduler::current_task();
if (!current_task->files[fd].is_open())
{
STDIO_FAIL(seek, EBADF);
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)
{
STDIO_FAIL(seek, EINVAL);
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)
{
if (!addr)
@ -23,7 +72,6 @@ void sys_write(Context* context, int fd, size_t size, const char* addr)
}
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;
@ -31,14 +79,12 @@ void sys_write(Context* context, int fd, size_t size, const char* addr)
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;