From 5d31e89574f76268dd9a19ee4110b87517ea20e1 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 22 Feb 2023 01:23:11 +0200 Subject: [PATCH] Kernel: Update ErrorOr API and add path find to VFS These two are done on the same commit since Changes to Shell were annoying to make work with only one change --- BAN/include/BAN/Errors.h | 67 +++++++++++++++----- kernel/include/kernel/FS/VirtualFileSystem.h | 2 + kernel/kernel/FS/VirtualFileSystem.cpp | 16 +++++ kernel/kernel/Input.cpp | 2 +- kernel/kernel/Shell.cpp | 40 ++++-------- 5 files changed, 80 insertions(+), 47 deletions(-) diff --git a/BAN/include/BAN/Errors.h b/BAN/include/BAN/Errors.h index af29338c2..caae31bb4 100644 --- a/BAN/include/BAN/Errors.h +++ b/BAN/include/BAN/Errors.h @@ -1,18 +1,18 @@ #pragma once #include +#include #include #if defined(__is_kernel) #include - #define MUST(error) ({ auto e = error; if (e.is_error()) Kernel::panic("{}", e.get_error()); e.value(); }) - #define ASSERT(cond) do { if (!(cond)) Kernel::panic("ASSERT("#cond") failed"); } while(false) + #define MUST(expr) ({ auto e = expr; if (e.is_error()) Kernel::panic("{}", e.error()); e.release_value(); }) #else #error "NOT IMPLEMENTED" #endif -#define TRY(error) ({ auto e = error; if (e.is_error()) return e.get_error(); e.value(); }) +#define TRY(expr) ({ auto e = expr; if (e.is_error()) return e.error(); e.release_value(); }) namespace BAN { @@ -22,6 +22,7 @@ namespace BAN public: static Error from_string(const char* message) { + static_assert(sizeof(message) < 128); Error result; strncpy(result.m_message, message, sizeof(m_message)); result.m_message[sizeof(result.m_message) - 1] = '\0'; @@ -41,34 +42,66 @@ namespace BAN class [[nodiscard]] ErrorOr { public: - ErrorOr(const T& value) : m_has_error(false) { m_data = (void*)new T(value); } - ErrorOr(const Error& error) : m_has_error(true) { m_data = (void*)new Error(error); } - template ErrorOr(const ErrorOr& other) : ErrorOr(other.get_error()) {} - ~ErrorOr() { is_error() ? (delete reinterpret_cast(m_data)) : (delete reinterpret_cast(m_data)); } + ErrorOr(const T& value) + : m_data(value) + {} + ErrorOr(T&& value) + : m_data(move(value)) + {} + ErrorOr(const Error& error) + : m_data(error) + {} + ErrorOr(Error&& error) + : m_data(move(error)) + {} + template + ErrorOr(const ErrorOr& other) + : m_data(other.m_data) + {} + template + ErrorOr(ErrorOr&& other) + : m_data(move(other.m_data)) + {} + template + ErrorOr& operator=(const ErrorOr& other) + { + m_data = other.m_data; + return *this; + } + template + ErrorOr& operator=(ErrorOr&& other) + { + m_data = move(other.m_data); + return *this; + } - bool is_error() const { return m_has_error; } - const Error& get_error() const { return *reinterpret_cast(m_data); } - T& value() { return *reinterpret_cast(m_data); } + bool is_error() const { return m_data.template is(); } + const Error& error() const { return m_data.template get(); } + Error& error() { return m_data.template get(); } + const T& value() const { return m_data.template get(); } + T& value() { return m_data.template get(); } + T release_value() { return move(value()); m_data.clear(); } private: - bool m_has_error = false; - void* m_data = nullptr; + Variant m_data; }; template<> class [[nodiscard]] ErrorOr { public: - ErrorOr() { } - ErrorOr(const Error& error) : m_error(error), m_has_error(true) { } - ~ErrorOr() { } + ErrorOr() {} + ErrorOr(const Error& error) : m_data(error), m_has_error(true) {} + ErrorOr(Error&& error) : m_data(move(error)), m_has_error(true) {} bool is_error() const { return m_has_error; } - const Error& get_error() const { return m_error; } + Error& error() { return m_data; } + const Error& error() const { return m_data; } void value() { } + void release_value() { m_data = Error(); } private: - Error m_error; + Error m_data; bool m_has_error = false; }; diff --git a/kernel/include/kernel/FS/VirtualFileSystem.h b/kernel/include/kernel/FS/VirtualFileSystem.h index 9e32dabba..027cc54d7 100644 --- a/kernel/include/kernel/FS/VirtualFileSystem.h +++ b/kernel/include/kernel/FS/VirtualFileSystem.h @@ -14,6 +14,8 @@ namespace Kernel virtual const BAN::RefCounted root_inode() const override { return m_root_inode; } + BAN::ErrorOr> from_absolute_path(BAN::StringView); + private: VirtualFileSystem(BAN::RefCounted root_inode) : m_root_inode(root_inode) diff --git a/kernel/kernel/FS/VirtualFileSystem.cpp b/kernel/kernel/FS/VirtualFileSystem.cpp index 1443841ce..1e4f6efa8 100644 --- a/kernel/kernel/FS/VirtualFileSystem.cpp +++ b/kernel/kernel/FS/VirtualFileSystem.cpp @@ -1,3 +1,5 @@ +#include +#include #include namespace Kernel @@ -23,4 +25,18 @@ namespace Kernel return s_instance != nullptr; } + BAN::ErrorOr> VirtualFileSystem::from_absolute_path(BAN::StringView path) + { + if (path.front() != '/') + return BAN::Error::from_string("Path must be an absolute path"); + + auto inode = root_inode(); + auto path_parts = TRY(path.split('/')); + + for (BAN::StringView part : path_parts) + inode = TRY(inode->directory_find(part)); + + return inode; + } + } \ No newline at end of file diff --git a/kernel/kernel/Input.cpp b/kernel/kernel/Input.cpp index 688b64c3a..fee4fa91c 100644 --- a/kernel/kernel/Input.cpp +++ b/kernel/kernel/Input.cpp @@ -512,7 +512,7 @@ namespace Input { auto error_or = s_key_event_queue.push({ .key = key, .modifiers = modifiers, .pressed = pressed }); if (error_or.is_error()) - dwarnln("{}", error_or.get_error()); + dwarnln("{}", error_or.error()); } s_keyboard_key_buffer_size -= index + 1; memmove(s_keyboard_key_buffer, s_keyboard_key_buffer + index, s_keyboard_key_buffer_size); diff --git a/kernel/kernel/Shell.cpp b/kernel/kernel/Shell.cpp index 47f8f3a66..8ae9016e1 100644 --- a/kernel/kernel/Shell.cpp +++ b/kernel/kernel/Shell.cpp @@ -268,28 +268,16 @@ argument_done: BAN::StringView path = (arguments.size() == 2) ? arguments[1].sv() : "/"; if (path.front() != '/') return TTY_PRINTLN("ls currently works only with absolute paths"); - path = path.substring(1); - auto directory = VirtualFileSystem::get().root_inode(); + auto directory_or_error = VirtualFileSystem::get().from_absolute_path(path); + if (directory_or_error.is_error()) + return TTY_PRINTLN("{}", directory_or_error.error()); + auto directory = directory_or_error.release_value(); ASSERT(directory->ifdir()); - if (arguments.size() == 2) - { - auto path_parts = MUST(arguments[1].sv().split('/')); - for (auto part : path_parts) - { - auto inode_or_error = directory->directory_find(part); - if (inode_or_error.is_error()) - return TTY_PRINTLN("{}", inode_or_error.get_error().get_message()); - directory = inode_or_error.value(); - if (!directory->ifdir()) - return TTY_PRINTLN("expected argument to be path to directory"); - } - } - auto inodes_or_error = directory->directory_inodes(); if (inodes_or_error.is_error()) - return TTY_PRINTLN("{}", inodes_or_error.get_error().get_message()); + return TTY_PRINTLN("{}", inodes_or_error.error()); auto& inodes = inodes_or_error.value(); auto mode_string = [](Inode::Mode mode) @@ -324,22 +312,16 @@ argument_done: if (arguments.size() > 2) return TTY_PRINTLN("usage: 'cat path'"); - auto file = VirtualFileSystem::get().root_inode(); - - auto path_parts = MUST(arguments[1].sv().split('/')); - for (auto part : path_parts) - { - auto inode_or_error = file->directory_find(part); - if (inode_or_error.is_error()) - return TTY_PRINTLN("{}", inode_or_error.get_error().get_message()); - file = inode_or_error.value(); - } + auto file_or_error = VirtualFileSystem::get().from_absolute_path(arguments[1]); + if (file_or_error.is_error()) + return TTY_PRINTLN("{}", file_or_error.error()); + auto file = file_or_error.release_value(); auto data_or_error = file->read_all(); if (data_or_error.is_error()) - return TTY_PRINTLN("{}", data_or_error.get_error().get_message()); + return TTY_PRINTLN("{}", data_or_error.error()); + auto data = data_or_error.release_value(); - auto& data = data_or_error.value(); TTY_PRINTLN("{}", BAN::StringView((const char*)data.data(), data.size())); } else