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);
|
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(const Descriptor& other);
|
||||||
Descriptor();
|
Descriptor();
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#define SYS_open 9
|
#define SYS_open 9
|
||||||
#define SYS_read 10
|
#define SYS_read 10
|
||||||
#define SYS_close 11
|
#define SYS_close 11
|
||||||
|
#define SYS_seek 12
|
||||||
|
|
||||||
namespace Syscall
|
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_munmap(Context* context, void* address, size_t size);
|
||||||
void sys_open(Context* context, const char* filename, int flags);
|
void sys_open(Context* context, const char* filename, int flags);
|
||||||
void sys_read(Context* context, int fd, size_t size, char* buffer);
|
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 "fs/FileDescriptor.h"
|
||||||
|
#include "errno.h"
|
||||||
|
|
||||||
Descriptor::Descriptor() : m_is_open(false)
|
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);
|
ssize_t result = VFS::write(m_node, m_offset, size, buffer);
|
||||||
m_offset += result;
|
m_offset += result;
|
||||||
return 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_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_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_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;
|
default: context->rax = -ENOSYS; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,8 +11,57 @@
|
|||||||
#define OPEN_READ 1
|
#define OPEN_READ 1
|
||||||
#define OPEN_WRITE 2
|
#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)
|
#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)
|
void sys_write(Context* context, int fd, size_t size, const char* addr)
|
||||||
{
|
{
|
||||||
if (!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)
|
if (fd >= TASK_MAX_FDS || fd < 0)
|
||||||
{
|
{
|
||||||
kwarnln("file descriptor %d is outside the valid range", fd);
|
|
||||||
STDIO_FAIL(write, EBADF);
|
STDIO_FAIL(write, EBADF);
|
||||||
context->rax = -EBADF;
|
context->rax = -EBADF;
|
||||||
return;
|
return;
|
||||||
@ -31,14 +79,12 @@ void sys_write(Context* context, int fd, size_t size, const char* addr)
|
|||||||
Task* current_task = Scheduler::current_task();
|
Task* current_task = Scheduler::current_task();
|
||||||
if (!current_task->files[fd].is_open())
|
if (!current_task->files[fd].is_open())
|
||||||
{
|
{
|
||||||
kwarnln("file descriptor %d is not open", fd);
|
|
||||||
STDIO_FAIL(write, EBADF);
|
STDIO_FAIL(write, EBADF);
|
||||||
context->rax = -EBADF;
|
context->rax = -EBADF;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!current_task->files[fd].can_write())
|
if (!current_task->files[fd].can_write())
|
||||||
{
|
{
|
||||||
kwarnln("file descriptor %d is not open for writing", fd);
|
|
||||||
STDIO_FAIL(write, EBADF);
|
STDIO_FAIL(write, EBADF);
|
||||||
context->rax = -EBADF;
|
context->rax = -EBADF;
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user