diff --git a/kernel/include/kernel/FS/Ext2.h b/kernel/include/kernel/FS/Ext2.h index bd7817a492..ecec57ac9c 100644 --- a/kernel/include/kernel/FS/Ext2.h +++ b/kernel/include/kernel/FS/Ext2.h @@ -131,12 +131,13 @@ namespace Kernel virtual BAN::StringView name() const override { return m_name; } - virtual BAN::ErrorOr> read_all() override; + virtual BAN::ErrorOr read(size_t, void*, size_t) override; virtual BAN::ErrorOr>> directory_inodes() override; virtual BAN::ErrorOr> directory_find(BAN::StringView) override; private: - BAN::ErrorOr for_each_block(BAN::Function(const BAN::Vector&)>&); + using block_callback_t = BAN::ErrorOr(*)(const BAN::Vector&, void*); + BAN::ErrorOr for_each_block(block_callback_t, void*); private: Ext2Inode() {} diff --git a/kernel/include/kernel/FS/Inode.h b/kernel/include/kernel/FS/Inode.h index 68b6d23b1d..31bf1df87f 100644 --- a/kernel/include/kernel/FS/Inode.h +++ b/kernel/include/kernel/FS/Inode.h @@ -36,6 +36,8 @@ namespace Kernel }; public: + virtual ~Inode() {} + bool ifdir() const { return mode().IFDIR; } bool ifreg() const { return mode().IFREG; } @@ -47,7 +49,7 @@ namespace Kernel virtual BAN::StringView name() const = 0; - virtual BAN::ErrorOr> read_all() = 0; + virtual BAN::ErrorOr read(size_t, void*, size_t) = 0; virtual BAN::ErrorOr>> directory_inodes() = 0; virtual BAN::ErrorOr> directory_find(BAN::StringView) = 0; }; diff --git a/kernel/include/kernel/FS/VirtualFileSystem.h b/kernel/include/kernel/FS/VirtualFileSystem.h index 7197feecf8..3dc75ddd56 100644 --- a/kernel/include/kernel/FS/VirtualFileSystem.h +++ b/kernel/include/kernel/FS/VirtualFileSystem.h @@ -15,19 +15,22 @@ namespace Kernel static VirtualFileSystem& get(); virtual ~VirtualFileSystem() {}; - virtual const BAN::RefPtr root_inode() const override; + virtual const BAN::RefPtr root_inode() const override { return m_root_inode; } - void close_inode(BAN::StringView); - - BAN::ErrorOr> from_absolute_path(BAN::StringView); + struct File + { + BAN::RefPtr inode; + BAN::String canonical_path; + }; + BAN::ErrorOr file_from_absolute_path(BAN::StringView); private: VirtualFileSystem() = default; BAN::ErrorOr initialize_impl(); private: - BAN::HashMap> m_open_inodes; - BAN::Vector m_storage_controllers; + BAN::RefPtr m_root_inode; + BAN::Vector m_storage_controllers; }; } \ No newline at end of file diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index fa45ae2ceb..f968d37565 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -1,7 +1,9 @@ #pragma once #include +#include #include +#include #include namespace Kernel @@ -24,12 +26,39 @@ namespace Kernel pid_t pid() const { return m_pid; } + BAN::ErrorOr open(BAN::StringView, int); + BAN::ErrorOr close(int); + BAN::ErrorOr read(int, void*, size_t); + + BAN::StringView working_directory() const { return m_working_directory; } + BAN::ErrorOr set_working_directory(BAN::StringView); + + Inode& inode_for_fd(int); + static BAN::RefPtr current() { return Thread::current()->process(); } private: Process(pid_t pid) : m_pid(pid) {} + BAN::ErrorOr absolute_path_of(BAN::StringView) const; + private: + struct OpenFileDescription + { + BAN::RefPtr inode; + BAN::String path; + size_t offset = 0; + uint8_t flags = 0; + + BAN::ErrorOr read(void*, size_t); + }; + + BAN::ErrorOr validate_fd(int); + OpenFileDescription& open_file_description(int); + BAN::ErrorOr get_free_fd(); + + BAN::Vector m_open_files; + pid_t m_pid = 0; BAN::String m_working_directory; BAN::Vector> m_threads; diff --git a/kernel/include/kernel/Shell.h b/kernel/include/kernel/Shell.h index 4788dbb10a..2e81680dd6 100644 --- a/kernel/include/kernel/Shell.h +++ b/kernel/include/kernel/Shell.h @@ -13,7 +13,7 @@ namespace Kernel public: Shell(TTY*); Shell(const Shell&) = delete; - void set_prompt(BAN::StringView); + BAN::ErrorOr set_prompt(BAN::StringView); void run(); private: @@ -21,11 +21,13 @@ namespace Kernel BAN::Vector parse_arguments(BAN::StringView) const; BAN::ErrorOr process_command(const BAN::Vector&); void key_event_callback(Input::KeyEvent); + BAN::ErrorOr update_prompt(); private: TTY* m_tty; BAN::Vector m_old_buffer; BAN::Vector m_buffer; + BAN::String m_prompt_string; BAN::String m_prompt; uint32_t m_prompt_length = 0; diff --git a/kernel/kernel/FS/Ext2.cpp b/kernel/kernel/FS/Ext2.cpp index 09272f5ca9..02e794105a 100644 --- a/kernel/kernel/FS/Ext2.cpp +++ b/kernel/kernel/FS/Ext2.cpp @@ -138,7 +138,7 @@ namespace Kernel } - BAN::ErrorOr Ext2Inode::for_each_block(BAN::Function(const BAN::Vector&)>& func) + BAN::ErrorOr Ext2Inode::for_each_block(block_callback_t callback, void* callback_data) { uint32_t data_blocks_left = m_inode.blocks / (2 << m_fs->superblock().log_block_size); uint32_t block_array_block_count = (1024 << m_fs->superblock().log_block_size) / sizeof(uint32_t); @@ -150,7 +150,7 @@ namespace Kernel continue; auto block_data = TRY(m_fs->read_block(m_inode.block[i])); - if (!TRY(func(block_data))) + if (!TRY(callback(block_data, callback_data))) return {}; if (--data_blocks_left == 0) return {}; @@ -166,7 +166,7 @@ namespace Kernel if (block == 0) continue; auto block_data = TRY(m_fs->read_block(block)); - if (!TRY(func(block_data))) + if (!TRY(callback(block_data, callback_data))) return {}; if (--data_blocks_left == 0) return {}; @@ -187,7 +187,7 @@ namespace Kernel if (block == 0) continue; auto block_data = TRY(m_fs->read_block(block)); - if (!TRY(func(block_data))) + if (!TRY(callback(block_data, callback_data))) return {}; if (--data_blocks_left == 0) return {}; @@ -213,7 +213,7 @@ namespace Kernel if (block == 0) continue; auto block_data = TRY(m_fs->read_block(block)); - if (!TRY(func(block_data))) + if (!TRY(callback(block_data, callback_data))) return {}; if (--data_blocks_left == 0) return {}; @@ -225,32 +225,63 @@ namespace Kernel return BAN::Error::from_c_string("Inode did not contain enough blocks"); } - BAN::ErrorOr> Ext2Inode::read_all() + BAN::ErrorOr Ext2Inode::read(size_t offset, void* buffer, size_t count) { if (ifdir()) return BAN::Error::from_errno(EISDIR); - BAN::Vector data_buffer; - TRY(data_buffer.resize(m_inode.size)); + struct read_info + { + size_t file_current_offset; + size_t file_start_offset; + size_t file_bytes_left; + uint8_t* out_byte_buffer; + size_t out_bytes_read; + size_t out_byte_buffer_size; + }; - uint32_t bytes_done = 0; - uint32_t bytes_left = m_inode.size; + read_info info; + info.file_current_offset = 0; + info.file_start_offset = offset; + info.file_bytes_left = m_inode.size; + info.out_byte_buffer = (uint8_t*)buffer; + info.out_bytes_read = 0; + info.out_byte_buffer_size = count; - BAN::Function(const BAN::Vector&)> read_func( - [&](const BAN::Vector& block_data) + block_callback_t read_func = + [](const BAN::Vector& block_data, void* info_) -> BAN::ErrorOr { - uint32_t to_copy = BAN::Math::min(block_data.size(), bytes_left); - memcpy(data_buffer.data() + bytes_done, block_data.data(), to_copy); - bytes_done += to_copy; - bytes_left -= to_copy; - return bytes_left > 0; - } - ); + read_info& info = *(read_info*)info_; - TRY(for_each_block(read_func)); - ASSERT(bytes_left == 0); + size_t block_size = BAN::Math::min(block_data.size(), info.file_bytes_left); - return data_buffer; + // Skip blocks before 'offset' + if (info.file_current_offset + block_size <= info.file_start_offset) + { + info.file_current_offset += block_size; + info.file_bytes_left -= block_size; + return info.file_bytes_left > 0; + } + + size_t read_offset = 0; + if (info.file_current_offset < info.file_start_offset) + read_offset = info.file_start_offset - info.file_current_offset; + + size_t to_read = BAN::Math::min(block_size - read_offset, info.out_byte_buffer_size - info.out_bytes_read); + memcpy(info.out_byte_buffer + info.out_bytes_read, block_data.data() + read_offset, to_read); + + info.out_bytes_read += to_read; + if (info.out_bytes_read >= info.out_byte_buffer_size) + return false; + + info.file_current_offset += block_size; + info.file_bytes_left -= block_size; + return info.file_bytes_left > 0; + }; + + TRY(for_each_block(read_func, &info)); + + return info.out_bytes_read; } BAN::ErrorOr> Ext2Inode::directory_find(BAN::StringView file_name) @@ -258,33 +289,45 @@ namespace Kernel if (!ifdir()) return BAN::Error::from_errno(ENOTDIR); - BAN::RefPtr result; - BAN::Function(const BAN::Vector&)> function( - [&](const BAN::Vector& block_data) -> BAN::ErrorOr + struct search_info + { + BAN::StringView file_name; + BAN::RefPtr result; + Ext2FS* fs; + }; + + search_info info; + info.file_name = file_name; + info.result = {}; + info.fs = m_fs; + + block_callback_t function = + [](const BAN::Vector& block_data, void* info_) -> BAN::ErrorOr { + search_info& info = *(search_info*)info_; + uintptr_t block_data_end = (uintptr_t)block_data.data() + block_data.size(); uintptr_t entry_addr = (uintptr_t)block_data.data(); while (entry_addr < block_data_end) { Ext2::LinkedDirectoryEntry* entry = (Ext2::LinkedDirectoryEntry*)entry_addr; BAN::StringView entry_name = BAN::StringView(entry->name, entry->name_len); - if (entry->inode && file_name == entry_name) + if (entry->inode && info.file_name == entry_name) { - Ext2Inode* inode = new Ext2Inode(m_fs, TRY(m_fs->read_inode(entry->inode)), entry_name); + Ext2Inode* inode = new Ext2Inode(info.fs, TRY(info.fs->read_inode(entry->inode)), entry_name); if (inode == nullptr) return BAN::Error::from_errno(ENOMEM); - result = BAN::RefPtr::adopt(inode); + info.result = BAN::RefPtr::adopt(inode); return false; } entry_addr += entry->rec_len; } return true; - } - ); + }; - TRY(for_each_block(function)); - if (result) - return result; + TRY(for_each_block(function, &info)); + if (info.result) + return info.result; return BAN::Error::from_errno(ENOENT); } @@ -293,10 +336,21 @@ namespace Kernel if (!ifdir()) return BAN::Error::from_errno(ENOTDIR); - BAN::Vector> inodes; - BAN::Function(const BAN::Vector&)> function( - [&](const BAN::Vector& block_data) -> BAN::ErrorOr + struct directory_info + { + BAN::Vector> inodes; + Ext2FS* fs; + }; + + directory_info info; + info.inodes = {}; + info.fs = m_fs; + + block_callback_t function = + [](const BAN::Vector& block_data, void* info_) -> BAN::ErrorOr { + directory_info& info = *(directory_info*)info_; + uintptr_t block_data_end = (uintptr_t)block_data.data() + block_data.size(); uintptr_t entry_addr = (uintptr_t)block_data.data(); while (entry_addr < block_data_end) @@ -305,22 +359,21 @@ namespace Kernel if (entry->inode) { BAN::StringView entry_name = BAN::StringView(entry->name, entry->name_len); - Ext2::Inode current_inode = TRY(m_fs->read_inode(entry->inode)); + Ext2::Inode current_inode = TRY(info.fs->read_inode(entry->inode)); - Ext2Inode* inode = new Ext2Inode(m_fs, BAN::move(current_inode), entry_name); + Ext2Inode* inode = new Ext2Inode(info.fs, BAN::move(current_inode), entry_name); if (inode == nullptr) return BAN::Error::from_errno(ENOMEM); - TRY(inodes.push_back(BAN::RefPtr::adopt(inode))); + TRY(info.inodes.push_back(BAN::RefPtr::adopt(inode))); } entry_addr += entry->rec_len; } return true; - } - ); + }; - TRY(for_each_block(function)); + TRY(for_each_block(function, &info)); - return inodes; + return info.inodes; } BAN::ErrorOr Ext2FS::create(StorageDevice::Partition& partition) diff --git a/kernel/kernel/FS/VirtualFileSystem.cpp b/kernel/kernel/FS/VirtualFileSystem.cpp index 3601d331af..2379087872 100644 --- a/kernel/kernel/FS/VirtualFileSystem.cpp +++ b/kernel/kernel/FS/VirtualFileSystem.cpp @@ -103,7 +103,7 @@ namespace Kernel else // FIXME: We leave a dangling pointer to ext2fs. This might be okay since // root fs sould probably be always mounted - TRY(m_open_inodes.insert("/"sv, ext2fs_or_error.release_value()->root_inode())); + m_root_inode = ext2fs_or_error.value()->root_inode(); } } } @@ -115,40 +115,52 @@ namespace Kernel return {}; } - const BAN::RefPtr VirtualFileSystem::root_inode() const - { - if (!m_open_inodes.contains("/"sv)) - return nullptr; - return m_open_inodes["/"sv]; - } - - void VirtualFileSystem::close_inode(BAN::StringView path) - { - ASSERT(m_open_inodes.contains(path)); - - // Delete the cached inode, if we are the only one holding a reference to it - if (m_open_inodes[path]->ref_count() == 1) - m_open_inodes.remove(path); - } - - BAN::ErrorOr> VirtualFileSystem::from_absolute_path(BAN::StringView path) + BAN::ErrorOr VirtualFileSystem::file_from_absolute_path(BAN::StringView path) { ASSERT(path.front() == '/'); - - if (m_open_inodes.contains(path)) - return m_open_inodes[path]; auto inode = root_inode(); if (!inode) return BAN::Error::from_c_string("No root inode available"); auto path_parts = TRY(path.split('/')); - for (BAN::StringView part : path_parts) - inode = TRY(inode->directory_find(part)); - - TRY(m_open_inodes.insert(path, inode)); - return inode; + for (size_t i = 0; i < path_parts.size();) + { + if (path_parts[i] == "."sv) + { + path_parts.remove(i); + } + else if (path_parts[i] == ".."sv) + { + inode = TRY(inode->directory_find(path_parts[i])); + path_parts.remove(i); + if (i > 0) + { + path_parts.remove(i - 1); + i--; + } + } + else + { + inode = TRY(inode->directory_find(path_parts[i])); + i++; + } + } + + File file; + file.inode = inode; + + for (const auto& part : path_parts) + { + TRY(file.canonical_path.push_back('/')); + TRY(file.canonical_path.append(part)); + } + + if (file.canonical_path.empty()) + TRY(file.canonical_path.push_back('/')); + + return file; } } \ No newline at end of file diff --git a/kernel/kernel/Font.cpp b/kernel/kernel/Font.cpp index 20b65f912a..88074e290e 100644 --- a/kernel/kernel/Font.cpp +++ b/kernel/kernel/Font.cpp @@ -1,6 +1,9 @@ #include +#include #include -#include +#include + +#include #define PSF1_MODE_512 0x01 #define PSF1_MODE_HASTAB 0x02 @@ -25,9 +28,13 @@ namespace Kernel BAN::ErrorOr Font::load(BAN::StringView path) { - auto inode = TRY(VirtualFileSystem::get().from_absolute_path(path)); + int fd = TRY(Process::current()->open(path, O_RDONLY)); + BAN::ScopeGuard _([fd] { MUST(Process::current()->close(fd)); }); - auto file_data = TRY(inode->read_all()); + size_t file_size = Process::current()->inode_for_fd(fd).size(); + BAN::Vector file_data; + TRY(file_data.resize(file_size)); + TRY(Process::current()->read(fd, file_data.data(), file_size)); if (file_data.size() < 4) return BAN::Error::from_c_string("Font file is too small"); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index ce540232c3..1a7a2b8e5f 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -1,6 +1,9 @@ #include #include #include +#include + +#include namespace Kernel { @@ -9,8 +12,8 @@ namespace Kernel { static pid_t next_pid = 1; auto process = TRY(BAN::RefPtr::create(next_pid++)); + TRY(process->m_working_directory.push_back('/')); TRY(process->add_thread(entry, data)); - TRY(process->m_working_directory.append("/"sv)); return process; } @@ -24,14 +27,112 @@ namespace Kernel return res; } - dprintln("add thread {} to process {}", thread->tid(), pid()); - return {}; } void Process::on_thread_exit(Thread& thread) { - dprintln("thread {} exited from process", thread.tid(), pid()); + (void)thread; + } + + BAN::ErrorOr Process::open(BAN::StringView path, int flags) + { + if (flags != O_RDONLY) + return BAN::Error::from_errno(ENOTSUP); + + BAN::String absolute_path = TRY(absolute_path_of(path)); + + auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(absolute_path)); + + int fd = TRY(get_free_fd()); + auto& open_file_description = m_open_files[fd]; + open_file_description.inode = file.inode; + open_file_description.path = BAN::move(file.canonical_path); + open_file_description.offset = 0; + open_file_description.flags = flags; + + return fd; + } + + BAN::ErrorOr Process::close(int fd) + { + TRY(validate_fd(fd)); + auto& open_file_description = this->open_file_description(fd); + open_file_description.inode = nullptr; + return {}; + } + + BAN::ErrorOr Process::read(int fd, void* buffer, size_t count) + { + TRY(validate_fd(fd)); + auto& open_file_description = this->open_file_description(fd); + if (open_file_description.offset >= open_file_description.inode->size()) + return 0; + size_t n_read = TRY(open_file_description.read(buffer, count)); + return n_read; + } + + Inode& Process::inode_for_fd(int fd) + { + MUST(validate_fd(fd)); + return *open_file_description(fd).inode; + } + + BAN::ErrorOr Process::set_working_directory(BAN::StringView path) + { + BAN::String absolute_path = TRY(absolute_path_of(path)); + + auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(absolute_path)); + if (!file.inode->ifdir()) + return BAN::Error::from_errno(ENOTDIR); + + m_working_directory = BAN::move(file.canonical_path); + + return {}; + } + + BAN::ErrorOr Process::absolute_path_of(BAN::StringView path) const + { + if (path.empty()) + return m_working_directory; + BAN::String absolute_path; + if (path.front() != '/') + { + TRY(absolute_path.append(m_working_directory)); + if (m_working_directory.sv().back() != '/') + TRY(absolute_path.push_back('/')); + } + TRY(absolute_path.append(path)); + return absolute_path; + } + + BAN::ErrorOr Process::OpenFileDescription::read(void* buffer, size_t count) + { + size_t n_read = TRY(inode->read(offset, buffer, count)); + offset += n_read; + return n_read; + } + + BAN::ErrorOr Process::validate_fd(int fd) + { + if (fd < 0 || m_open_files.size() <= (size_t)fd || !m_open_files[fd].inode) + return BAN::Error::from_errno(EBADF); + return {}; + } + + Process::OpenFileDescription& Process::open_file_description(int fd) + { + MUST(validate_fd(fd)); + return m_open_files[fd]; + } + + BAN::ErrorOr Process::get_free_fd() + { + for (size_t fd = 0; fd < m_open_files.size(); fd++) + if (!m_open_files[fd].inode) + return fd; + TRY(m_open_files.push_back({})); + return m_open_files.size() - 1; } } \ No newline at end of file diff --git a/kernel/kernel/Shell.cpp b/kernel/kernel/Shell.cpp index 69005d2f89..58d30a2c16 100644 --- a/kernel/kernel/Shell.cpp +++ b/kernel/kernel/Shell.cpp @@ -1,16 +1,17 @@ #include +#include #include #include #include #include #include #include +#include #include #include #include -#include - +#include #include #define TTY_PRINT(...) Formatter::print([this](char c) { m_tty->putchar(c); }, __VA_ARGS__) @@ -20,38 +21,62 @@ namespace Kernel { using namespace BAN; - static auto s_default_prompt = "\\[\e[32m\\]user\\[\e[m\\]# "sv; + static auto s_default_prompt = "\\[\e[32m\\]user\\[\e[m\\]:\\[\e[34m\\]\\w\\[\e[m\\]# "sv; Shell::Shell(TTY* tty) : m_tty(tty) { Input::register_key_event_callback({ &Shell::key_event_callback, this }); - set_prompt(s_default_prompt); + MUST(set_prompt(s_default_prompt)); MUST(m_buffer.push_back(""sv)); } - void Shell::set_prompt(StringView prompt) + BAN::ErrorOr Shell::set_prompt(StringView prompt) + { + m_prompt_string = prompt; + TRY(update_prompt()); + return {}; + } + + BAN::ErrorOr Shell::update_prompt() { m_prompt_length = 0; m_prompt = String(); bool skipping = false; - for (size_t i = 0; i < prompt.size(); i++) + for (size_t i = 0; i < m_prompt_string.size(); i++) { - if (i < prompt.size() - 1 && prompt[i] == '\\') + if (i < m_prompt_string.size() - 1 && m_prompt_string[i] == '\\') { - if (prompt[i + 1] == '[') - skipping = true; - if (prompt[i + 1] == ']') - skipping = false; + switch (m_prompt_string[i + 1]) + { + case '[': + skipping = true; + break; + case ']': + skipping = false; + break; + case 'w': + { + auto working_directory = Process::current()->working_directory(); + TRY(m_prompt.append(working_directory)); + m_prompt_length += working_directory.size(); + break; + } + default: + dprintln("unknown escape character '{}' in shell prompt", m_prompt_string[i + 1]); + break; + } i++; continue; } - MUST(m_prompt.push_back(prompt[i])); + TRY(m_prompt.push_back(m_prompt_string[i])); if (!skipping) m_prompt_length++; } + + return {}; } void Shell::run() @@ -276,12 +301,13 @@ argument_done: if (arguments.size() > 2) return BAN::Error::from_c_string("usage: 'ls [path]'"); - BAN::StringView path = (arguments.size() == 2) ? arguments[1].sv() : "/"; - if (path.front() != '/') - return BAN::Error::from_c_string("ls currently works only with absolute paths"); + BAN::StringView path = (arguments.size() == 2) ? arguments[1].sv() : Process::current()->working_directory(); - auto directory = TRY(VirtualFileSystem::get().from_absolute_path(path)); - auto inodes = TRY(directory->directory_inodes()); + int fd = TRY(Process::current()->open(path, O_RDONLY)); + BAN::ScopeGuard _([fd] { MUST(Process::current()->close(fd)); }); + + auto& directory = Process::current()->inode_for_fd(fd); + auto inodes = TRY(directory.directory_inodes()); auto mode_string = [](Inode::Mode mode) { @@ -299,7 +325,6 @@ argument_done: return (const char*)buffer; }; - TTY_PRINTLN("{}", path); for (auto& inode : inodes) if (inode->ifdir()) TTY_PRINTLN(" {} {7} \e[34m{}\e[m", mode_string(inode->mode()), inode->size(), inode->name()); @@ -312,9 +337,26 @@ argument_done: if (arguments.size() != 2) return BAN::Error::from_c_string("usage: 'cat path'"); - auto file = TRY(VirtualFileSystem::get().from_absolute_path(arguments[1])); - auto data = TRY(file->read_all()); - TTY_PRINTLN("{}", BAN::StringView((const char*)data.data(), data.size())); + int fd = TRY(Process::current()->open(arguments[1], O_RDONLY)); + BAN::ScopeGuard _([fd] { MUST(Process::current()->close(fd)); }); + + char buffer[1024] {}; + while (true) + { + size_t n_read = TRY(Process::current()->read(fd, buffer, sizeof(buffer))); + if (n_read == 0) + break; + TTY_PRINT("{}", BAN::StringView(buffer, n_read)); + } + TTY_PRINTLN(""); + } + else if (arguments.front() == "cd") + { + if (arguments.size() > 2) + return BAN::Error::from_c_string("usage 'cd path'"); + BAN::StringView path = arguments.size() == 2 ? arguments[1].sv() : "/"sv; + TRY(Process::current()->set_working_directory(path)); + TRY(update_prompt()); } else if (arguments.front() == "loadfont") { diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index 499afdc2e5..772dba59fa 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -196,12 +196,6 @@ void init2(void* tty1_ptr) MUST(VirtualFileSystem::initialize()); - auto font_or_error = Font::load("/usr/share/fonts/zap-ext-vga16.psf"); - if (font_or_error.is_error()) - dprintln("{}", font_or_error.error()); - else - tty1->set_font(font_or_error.release_value()); - MUST(Process::create_kernel( [](void* tty1) {