Compare commits

..

2 Commits

Author SHA1 Message Date
5c61252061 Kernel: Add a new fcntl() system call 2022-10-15 10:56:06 +02:00
3eb1bff2e9 Task: add an alloc_fd() function 2022-10-15 10:45:12 +02:00
5 changed files with 70 additions and 14 deletions

View File

@ -16,6 +16,7 @@
#define SYS_close 11 #define SYS_close 11
#define SYS_seek 12 #define SYS_seek 12
#define SYS_exec 13 #define SYS_exec 13
#define SYS_fcntl 14
namespace Syscall namespace Syscall
{ {
@ -37,4 +38,5 @@ 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); void sys_seek(Context* context, int fd, long offset, int whence);
void sys_exec(Context* context, const char* pathname); void sys_exec(Context* context, const char* pathname);
void sys_fcntl(Context* context, int fd, int command, uintptr_t arg);

View File

@ -46,6 +46,8 @@ struct Task
Descriptor files[TASK_MAX_FDS]; Descriptor files[TASK_MAX_FDS];
AddressSpace address_space; AddressSpace address_space;
int alloc_fd();
}; };
void set_context_from_task(Task& task, Context* ctx); void set_context_from_task(Task& task, Context* ctx);

View File

@ -25,12 +25,13 @@ void Syscall::entry(Context* context)
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); break; case SYS_seek: sys_seek(context, (int)context->rdi, (long)context->rsi, (int)context->rdx); break;
case SYS_exec: sys_exec(context, (const char*)context->rdi); break; case SYS_exec: sys_exec(context, (const char*)context->rdi); break;
case SYS_fcntl: sys_fcntl(context, (int)context->rdi, (int)context->rsi, context->rdx); break;
default: context->rax = -ENOSYS; break; default: context->rax = -ENOSYS; break;
} }
VMM::exit_syscall_context(); VMM::exit_syscall_context();
} }
char* Syscall::strdup_from_user(const char* user_string) char* Syscall::strdup_from_user(const char* user_string) // FIXME: This function is a little hacky.
{ {
uint64_t phys = VMM::get_physical((uint64_t)user_string); uint64_t phys = VMM::get_physical((uint64_t)user_string);
if (phys == (uint64_t)-1) { return nullptr; } if (phys == (uint64_t)-1) { return nullptr; }

View File

@ -18,6 +18,42 @@
#define SEEK_CUR 1 #define SEEK_CUR 1
#define SEEK_END 2 #define SEEK_END 2
#define FNCTL_DUPFD 0
void sys_fcntl(Context* context, int fd, int command, uintptr_t arg)
{
if (fd >= TASK_MAX_FDS || fd < 0)
{
context->rax = -EBADF;
return;
}
Task* current_task = Scheduler::current_task();
if (!current_task->files[fd].is_open())
{
context->rax = -EBADF;
return;
}
Descriptor& file = current_task->files[fd];
if (command == FNCTL_DUPFD)
{
int dupfd = current_task->alloc_fd();
if (dupfd < 0)
{
context->rax = -EMFILE;
return;
}
current_task->files[dupfd] = file;
context->rax = dupfd;
kdbgln("fcntl(F_DUPFD): duplicated fd %d, result is %d", fd, dupfd);
return;
}
else
{
context->rax = -EINVAL;
return;
}
}
void sys_seek(Context* context, int fd, long offset, int whence) void sys_seek(Context* context, int fd, long offset, int whence)
{ {
if (whence < SEEK_SET || whence > SEEK_END) if (whence < SEEK_SET || whence > SEEK_END)
@ -36,12 +72,13 @@ void sys_seek(Context* context, int fd, long offset, int whence)
context->rax = -EBADF; context->rax = -EBADF;
return; return;
} }
Descriptor& file = current_task->files[fd];
long new_offset; long new_offset;
if (whence == SEEK_SET) new_offset = offset; if (whence == SEEK_SET) new_offset = offset;
else if (whence == SEEK_CUR) else if (whence == SEEK_CUR)
new_offset = offset + current_task->files[fd].offset(); new_offset = offset + file.offset();
else if (whence == SEEK_END) else if (whence == SEEK_END)
new_offset = current_task->files[fd].length() + offset; new_offset = file.length() + offset;
else else
__builtin_unreachable(); __builtin_unreachable();
if (new_offset < 0) if (new_offset < 0)
@ -49,7 +86,12 @@ void sys_seek(Context* context, int fd, long offset, int whence)
context->rax = -EINVAL; // FIXME: Is this the right error? context->rax = -EINVAL; // FIXME: Is this the right error?
return; return;
} }
int result = current_task->files[fd].seek(new_offset); if (new_offset == file.offset())
{
context->rax = new_offset;
return;
}
int result = file.seek(new_offset);
if (result < 0) if (result < 0)
{ {
context->rax = result; context->rax = result;
@ -77,12 +119,13 @@ void sys_write(Context* context, int fd, size_t size, const char* addr)
context->rax = -EBADF; context->rax = -EBADF;
return; return;
} }
if (!current_task->files[fd].can_write()) Descriptor& file = current_task->files[fd];
if (!file.can_write())
{ {
context->rax = -EBADF; context->rax = -EBADF;
return; return;
} }
ssize_t result = current_task->files[fd].write(size, (const char*)VMM::get_physical((uint64_t)addr)); ssize_t result = file.write(size, (const char*)VMM::get_physical((uint64_t)addr));
context->rax = (size_t)result; context->rax = (size_t)result;
return; return;
} }
@ -90,13 +133,8 @@ void sys_write(Context* context, int fd, size_t size, const char* addr)
void sys_open(Context* context, const char* filename, int flags) void sys_open(Context* context, const char* filename, int flags)
{ {
Task* current_task = Scheduler::current_task(); Task* current_task = Scheduler::current_task();
int fd; int fd = current_task->alloc_fd();
for (fd = 0; fd < TASK_MAX_FDS; fd++) if (fd < 0)
{
if (!current_task->files[fd].is_open()) break;
}
if (fd == TASK_MAX_FDS)
{ {
context->rax = -EMFILE; context->rax = -EMFILE;
return; return;

View File

@ -26,4 +26,17 @@ void task_restore_floating(Task& task)
bool Task::is_user_task() bool Task::is_user_task()
{ {
return user_task; return user_task;
}
int Task::alloc_fd()
{
int fd;
for (fd = 0; fd < TASK_MAX_FDS; fd++)
{
if (!files[fd].is_open()) break;
}
if (fd == TASK_MAX_FDS) { return -1; }
return fd;
} }