Compare commits

...

2 Commits

Author SHA1 Message Date
854f585e1a Kernel: Add a seek() system call
Now, time for libc support!!
2022-10-12 15:28:52 +02:00
97b7572933 VFS: Implement a new type of Node, VFS_DEVICE
This is used to differentiate normal files from devices.
2022-10-12 15:22:34 +02:00
9 changed files with 76 additions and 7 deletions

View File

@ -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();

View File

@ -6,6 +6,7 @@ typedef long ssize_t;
#define VFS_FILE 0x0 #define VFS_FILE 0x0
#define VFS_DIRECTORY 0x1 #define VFS_DIRECTORY 0x1
#define VFS_DEVICE 0x2
#define VFS_MOUNTPOINT 0x1 #define VFS_MOUNTPOINT 0x1

View File

@ -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);

View File

@ -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;
} }

View File

@ -11,7 +11,7 @@ VFS::Node* ConsoleDevice::create_new(const char* devname)
dev->write_func = ConsoleDevice::write; dev->write_func = ConsoleDevice::write;
dev->inode = 0; dev->inode = 0;
dev->length = 0; dev->length = 0;
dev->type = VFS_FILE; dev->type = VFS_DEVICE;
dev->flags = 0; dev->flags = 0;
strncpy(dev->name, devname, sizeof(dev->name)); strncpy(dev->name, devname, sizeof(dev->name));
return dev; return dev;

View File

@ -11,7 +11,7 @@ VFS::Node* SerialDevice::create_new(const char* devname)
dev->write_func = SerialDevice::write; dev->write_func = SerialDevice::write;
dev->inode = 0; dev->inode = 0;
dev->length = 0; dev->length = 0;
dev->type = VFS_FILE; dev->type = VFS_DEVICE;
dev->flags = 0; dev->flags = 0;
strncpy(dev->name, devname, sizeof(dev->name)); strncpy(dev->name, devname, sizeof(dev->name));
return dev; return dev;

View File

@ -10,7 +10,7 @@ VFS::Node* VersionDevice::create_new(const char* devname)
dev->read_func = VersionDevice::read; dev->read_func = VersionDevice::read;
dev->inode = 0; dev->inode = 0;
dev->length = strlen(moon_version()) + 5; dev->length = strlen(moon_version()) + 5;
dev->type = VFS_FILE; dev->type = VFS_DEVICE;
dev->flags = 0; dev->flags = 0;
strncpy(dev->name, devname, sizeof(dev->name)); strncpy(dev->name, devname, sizeof(dev->name));
return dev; return dev;

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_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;
} }
} }

View File

@ -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;