apio
b54a7f3a80
All checks were successful
continuous-integration/drone/push Build is passing
O_RDONLY, O_WRONLY, O_RDWR, O_TRUNC, O_CREAT and O_EXCL are fully implemented. O_APPEND is partially implemented. Other flags are not here yet.
68 lines
1.9 KiB
C++
68 lines
1.9 KiB
C++
#include "Log.h"
|
|
#include "fs/VFS.h"
|
|
#include "memory/MemoryManager.h"
|
|
#include "sys/Syscall.h"
|
|
#include "thread/Scheduler.h"
|
|
#include <bits/open-flags.h>
|
|
|
|
// These flags are needed after open(), the rest only affect open().
|
|
constexpr int FLAGS_TO_KEEP = O_RDWR | O_APPEND;
|
|
|
|
Result<u64> sys_open(Registers*, SyscallArgs args)
|
|
{
|
|
u64 path_address = args[0];
|
|
if (!MemoryManager::validate_userspace_string(path_address)) return err(EFAULT);
|
|
|
|
const char* path = (const char*)path_address;
|
|
int flags = (int)args[1];
|
|
|
|
Thread* current = Scheduler::current();
|
|
|
|
kinfoln("open: trying to open file %s, flags %d", path, flags);
|
|
|
|
SharedPtr<VFS::Inode> inode;
|
|
|
|
// Caller did not pass either O_RDONLY, O_WRONLY or O_RDWR
|
|
if ((flags & O_RDWR) == 0) { return err(EINVAL); }
|
|
|
|
auto maybe_inode = VFS::resolve_path(path);
|
|
if (maybe_inode.has_error())
|
|
{
|
|
if (maybe_inode.error() == ENOENT && (flags & O_CREAT)) inode = TRY(VFS::create_file(path));
|
|
else
|
|
return maybe_inode.release_error();
|
|
}
|
|
else if (flags & O_EXCL)
|
|
return err(EEXIST);
|
|
else
|
|
inode = maybe_inode.release_value();
|
|
|
|
if ((flags & O_WRONLY) && (flags & O_TRUNC)) inode->truncate(0);
|
|
|
|
int fd = TRY(current->allocate_fd(0));
|
|
|
|
current->fd_table[fd] = FileDescriptor { inode, 0, flags & FLAGS_TO_KEEP };
|
|
|
|
kinfoln("open: allocated file descriptor %d for inode %zu", fd, inode->inode_number());
|
|
|
|
return (u64)fd;
|
|
}
|
|
|
|
Result<u64> sys_close(Registers*, SyscallArgs args)
|
|
{
|
|
int fd = (int)args[0];
|
|
if (fd < 0 || fd >= FD_MAX) return err(EBADF);
|
|
|
|
Thread* current = Scheduler::current();
|
|
|
|
Option<FileDescriptor>& descriptor = current->fd_table[fd];
|
|
|
|
if (!descriptor.has_value()) return err(EBADF);
|
|
|
|
kinfoln("close: closing file descriptor %d (was referencing inode %zu)", fd, descriptor->inode->inode_number());
|
|
|
|
descriptor = {};
|
|
|
|
return 0;
|
|
}
|