Kernel: Add a seek() system call
Now, time for libc support!!
This commit is contained in:
parent
97b7572933
commit
854f585e1a
@ -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();
|
||||
|
||||
|
@ -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);
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user