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
This commit is contained in:
parent
9aab67fed8
commit
5d31e89574
|
@ -1,18 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/Formatter.h>
|
#include <BAN/Formatter.h>
|
||||||
|
#include <BAN/Variant.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#if defined(__is_kernel)
|
#if defined(__is_kernel)
|
||||||
#include <kernel/Panic.h>
|
#include <kernel/Panic.h>
|
||||||
#define MUST(error) ({ auto e = error; if (e.is_error()) Kernel::panic("{}", e.get_error()); e.value(); })
|
#define MUST(expr) ({ auto e = expr; if (e.is_error()) Kernel::panic("{}", e.error()); e.release_value(); })
|
||||||
#define ASSERT(cond) do { if (!(cond)) Kernel::panic("ASSERT("#cond") failed"); } while(false)
|
|
||||||
#else
|
#else
|
||||||
#error "NOT IMPLEMENTED"
|
#error "NOT IMPLEMENTED"
|
||||||
#endif
|
#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
|
namespace BAN
|
||||||
{
|
{
|
||||||
|
@ -22,6 +22,7 @@ namespace BAN
|
||||||
public:
|
public:
|
||||||
static Error from_string(const char* message)
|
static Error from_string(const char* message)
|
||||||
{
|
{
|
||||||
|
static_assert(sizeof(message) < 128);
|
||||||
Error result;
|
Error result;
|
||||||
strncpy(result.m_message, message, sizeof(m_message));
|
strncpy(result.m_message, message, sizeof(m_message));
|
||||||
result.m_message[sizeof(result.m_message) - 1] = '\0';
|
result.m_message[sizeof(result.m_message) - 1] = '\0';
|
||||||
|
@ -41,34 +42,66 @@ namespace BAN
|
||||||
class [[nodiscard]] ErrorOr
|
class [[nodiscard]] ErrorOr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ErrorOr(const T& value) : m_has_error(false) { m_data = (void*)new T(value); }
|
ErrorOr(const T& value)
|
||||||
ErrorOr(const Error& error) : m_has_error(true) { m_data = (void*)new Error(error); }
|
: m_data(value)
|
||||||
template<typename S> ErrorOr(const ErrorOr<S>& other) : ErrorOr(other.get_error()) {}
|
{}
|
||||||
~ErrorOr() { is_error() ? (delete reinterpret_cast<Error*>(m_data)) : (delete reinterpret_cast<T*>(m_data)); }
|
ErrorOr(T&& value)
|
||||||
|
: m_data(move(value))
|
||||||
|
{}
|
||||||
|
ErrorOr(const Error& error)
|
||||||
|
: m_data(error)
|
||||||
|
{}
|
||||||
|
ErrorOr(Error&& error)
|
||||||
|
: m_data(move(error))
|
||||||
|
{}
|
||||||
|
template<typename U>
|
||||||
|
ErrorOr(const ErrorOr<U>& other)
|
||||||
|
: m_data(other.m_data)
|
||||||
|
{}
|
||||||
|
template<typename U>
|
||||||
|
ErrorOr(ErrorOr<U>&& other)
|
||||||
|
: m_data(move(other.m_data))
|
||||||
|
{}
|
||||||
|
template<typename U>
|
||||||
|
ErrorOr<T>& operator=(const ErrorOr<U>& other)
|
||||||
|
{
|
||||||
|
m_data = other.m_data;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<typename U>
|
||||||
|
ErrorOr<T>& operator=(ErrorOr<U>&& other)
|
||||||
|
{
|
||||||
|
m_data = move(other.m_data);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_error() const { return m_has_error; }
|
bool is_error() const { return m_data.template is<Error>(); }
|
||||||
const Error& get_error() const { return *reinterpret_cast<Error*>(m_data); }
|
const Error& error() const { return m_data.template get<Error>(); }
|
||||||
T& value() { return *reinterpret_cast<T*>(m_data); }
|
Error& error() { return m_data.template get<Error>(); }
|
||||||
|
const T& value() const { return m_data.template get<T>(); }
|
||||||
|
T& value() { return m_data.template get<T>(); }
|
||||||
|
T release_value() { return move(value()); m_data.clear(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_has_error = false;
|
Variant<Error, T> m_data;
|
||||||
void* m_data = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
class [[nodiscard]] ErrorOr<void>
|
class [[nodiscard]] ErrorOr<void>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ErrorOr() { }
|
ErrorOr() {}
|
||||||
ErrorOr(const Error& error) : m_error(error), m_has_error(true) { }
|
ErrorOr(const Error& error) : m_data(error), m_has_error(true) {}
|
||||||
~ErrorOr() { }
|
ErrorOr(Error&& error) : m_data(move(error)), m_has_error(true) {}
|
||||||
|
|
||||||
bool is_error() const { return m_has_error; }
|
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 value() { }
|
||||||
|
void release_value() { m_data = Error(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Error m_error;
|
Error m_data;
|
||||||
bool m_has_error = false;
|
bool m_has_error = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ namespace Kernel
|
||||||
|
|
||||||
virtual const BAN::RefCounted<Inode> root_inode() const override { return m_root_inode; }
|
virtual const BAN::RefCounted<Inode> root_inode() const override { return m_root_inode; }
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::RefCounted<Inode>> from_absolute_path(BAN::StringView);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VirtualFileSystem(BAN::RefCounted<Inode> root_inode)
|
VirtualFileSystem(BAN::RefCounted<Inode> root_inode)
|
||||||
: m_root_inode(root_inode)
|
: m_root_inode(root_inode)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include <BAN/StringView.h>
|
||||||
|
#include <BAN/Vector.h>
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
|
@ -23,4 +25,18 @@ namespace Kernel
|
||||||
return s_instance != nullptr;
|
return s_instance != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::RefCounted<Inode>> 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -512,7 +512,7 @@ namespace Input
|
||||||
{
|
{
|
||||||
auto error_or = s_key_event_queue.push({ .key = key, .modifiers = modifiers, .pressed = pressed });
|
auto error_or = s_key_event_queue.push({ .key = key, .modifiers = modifiers, .pressed = pressed });
|
||||||
if (error_or.is_error())
|
if (error_or.is_error())
|
||||||
dwarnln("{}", error_or.get_error());
|
dwarnln("{}", error_or.error());
|
||||||
}
|
}
|
||||||
s_keyboard_key_buffer_size -= index + 1;
|
s_keyboard_key_buffer_size -= index + 1;
|
||||||
memmove(s_keyboard_key_buffer, s_keyboard_key_buffer + index, s_keyboard_key_buffer_size);
|
memmove(s_keyboard_key_buffer, s_keyboard_key_buffer + index, s_keyboard_key_buffer_size);
|
||||||
|
|
|
@ -268,28 +268,16 @@ argument_done:
|
||||||
BAN::StringView path = (arguments.size() == 2) ? arguments[1].sv() : "/";
|
BAN::StringView path = (arguments.size() == 2) ? arguments[1].sv() : "/";
|
||||||
if (path.front() != '/')
|
if (path.front() != '/')
|
||||||
return TTY_PRINTLN("ls currently works only with absolute paths");
|
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());
|
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();
|
auto inodes_or_error = directory->directory_inodes();
|
||||||
if (inodes_or_error.is_error())
|
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& inodes = inodes_or_error.value();
|
||||||
|
|
||||||
auto mode_string = [](Inode::Mode mode)
|
auto mode_string = [](Inode::Mode mode)
|
||||||
|
@ -324,22 +312,16 @@ argument_done:
|
||||||
if (arguments.size() > 2)
|
if (arguments.size() > 2)
|
||||||
return TTY_PRINTLN("usage: 'cat path'");
|
return TTY_PRINTLN("usage: 'cat path'");
|
||||||
|
|
||||||
auto file = VirtualFileSystem::get().root_inode();
|
auto file_or_error = VirtualFileSystem::get().from_absolute_path(arguments[1]);
|
||||||
|
if (file_or_error.is_error())
|
||||||
auto path_parts = MUST(arguments[1].sv().split('/'));
|
return TTY_PRINTLN("{}", file_or_error.error());
|
||||||
for (auto part : path_parts)
|
auto file = file_or_error.release_value();
|
||||||
{
|
|
||||||
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 data_or_error = file->read_all();
|
auto data_or_error = file->read_all();
|
||||||
if (data_or_error.is_error())
|
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()));
|
TTY_PRINTLN("{}", BAN::StringView((const char*)data.data(), data.size()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue