Skip to content

Commit

Permalink
Implement a file explorer
Browse files Browse the repository at this point in the history
  • Loading branch information
hgruniaux committed May 22, 2024
1 parent 4e4bc94 commit ccaf48c
Show file tree
Hide file tree
Showing 19 changed files with 316 additions and 39 deletions.
2 changes: 2 additions & 0 deletions kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ add_executable(kernel
fs/fat/ramdisk.hpp
fs/file.hpp
fs/file.cpp
fs/dir.hpp
fs/dir.cpp
)

target_include_directories(kernel PUBLIC .)
Expand Down
15 changes: 15 additions & 0 deletions kernel/fs/dir.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "dir.hpp"
#include <libk/assert.hpp>
#include <libk/string.hpp>

bool Dir::read(sys_file_info_t* file_info) {
KASSERT(file_info != nullptr);

FILINFO filinfo;
if (f_readdir(&m_handle, &filinfo) != FR_OK || filinfo.fname[0] == 0)
return false;

libk::memcpy(file_info->name, filinfo.fname, sizeof(filinfo.fname));
file_info->is_dir = (filinfo.fattrib & AM_DIR) != 0;
return true;
}
14 changes: 14 additions & 0 deletions kernel/fs/dir.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include <sys/file.h>
#include <cstddef>
#include "fat/ff.h"

class Dir {
public:
bool read(sys_file_info_t* file_info);

private:
friend class FileSystem;
DIR m_handle;
}; // class Dir
21 changes: 21 additions & 0 deletions kernel/fs/filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ void FileSystem::init() {
}

File* FileSystem::open(const char* path, int flags) {
KASSERT(path != nullptr);

File* file = new File;

BYTE mode = 0;
Expand All @@ -42,3 +44,22 @@ void FileSystem::close(File* handle) {
f_close(&handle->m_handle);
delete handle;
}

Dir* FileSystem::open_dir(const char* path) {
KASSERT(path != nullptr);

Dir* dir = new Dir;

if (f_opendir(&dir->m_handle, path) == FR_OK)
return dir;

delete dir;
return nullptr;
}

void FileSystem::close_dir(Dir* handle) {
KASSERT(handle != nullptr);

f_closedir(&handle->m_handle);
delete handle;
}
6 changes: 4 additions & 2 deletions kernel/fs/filesystem.hpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
#pragma once

#include "dir.hpp"
#include "file.hpp"

class FileSystem {
public:
using FileHandle = void*;

static FileSystem& get();

void init();

File* open(const char* path, int flags);
void close(File* handle);

Dir* open_dir(const char* path);
void close_dir(Dir* handle);
}; // class FileSystem
49 changes: 49 additions & 0 deletions kernel/task/pika_syscalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,52 @@ static void pika_sys_get_file_size(Registers& regs) {
regs.gp_regs.x0 = file->get_size();
}

static bool check_dir(Registers& regs, Dir* dir) {
if (Task::current()->own_dir(dir))
return true;

set_error(regs, SYS_ERR_INVALID_DIR);
return false;
}

static void pika_sys_open_dir(Registers& regs) {
const char* path = (const char*)regs.gp_regs.x0;
if (!check_ptr(regs, (void*)path))
return;

auto* dir = FileSystem::get().open_dir(path);
regs.gp_regs.x0 = (sys_word_t)dir;
if (dir == nullptr)
return;

Task::current()->register_dir(dir);
}

static void pika_sys_close_dir(Registers& regs) {
Dir* dir = (Dir*)regs.gp_regs.x0;
if (!check_dir(regs, dir))
return;

FileSystem::get().close_dir(dir);
Task::current()->unregister_dir(dir);
set_error(regs, SYS_ERR_OK);
}

static void pika_sys_read_dir(Registers& regs) {
Dir* dir = (Dir*)regs.gp_regs.x0;
if (!check_dir(regs, dir))
return;

sys_file_info_t* file_info = (sys_file_info_t*)regs.gp_regs.x1;
if (!check_dir(regs, dir))
return;

if (dir->read(file_info))
set_error(regs, SYS_ERR_OK);
else
set_error(regs, SYS_ERR_GENERIC);
}

static bool check_window(Registers& regs, Window* window) {
if (Task::current()->own_window(window))
return true;
Expand Down Expand Up @@ -473,6 +519,9 @@ SyscallTable* create_pika_syscalls() {
table->register_syscall(SYS_CLOSE_FILE, pika_sys_close_file);
table->register_syscall(SYS_READ_FILE, pika_sys_read_file);
table->register_syscall(SYS_GET_FILE_SIZE, pika_sys_get_file_size);
table->register_syscall(SYS_OPEN_DIR, pika_sys_open_dir);
table->register_syscall(SYS_CLOSE_DIR, pika_sys_close_dir);
table->register_syscall(SYS_READ_DIR, pika_sys_read_dir);

// Window manager system calls.
table->register_syscall(SYS_POLL_MESSAGE, pika_sys_poll_msg);
Expand Down
29 changes: 29 additions & 0 deletions kernel/task/task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,28 @@ void Task::unregister_file(File* file) {
m_open_files.erase(it);
}

bool Task::own_dir(Dir* dir) const {
if (dir == nullptr)
return false;

auto it = std::find(m_open_dirs.begin(), m_open_dirs.end(), dir);
return it != m_open_dirs.end();
}

void Task::register_dir(Dir* dir) {
KASSERT(dir != nullptr);

m_open_dirs.push_back(dir);
}

void Task::unregister_dir(Dir* dir) {
KASSERT(dir != nullptr);

auto it = std::find(m_open_dirs.begin(), m_open_dirs.end(), dir);
KASSERT(it != m_open_dirs.end());
m_open_dirs.erase(it);
}

void Task::free_resources() {
// Destroy the windows.
auto& window_manager = WindowManager::get();
Expand All @@ -101,4 +123,11 @@ void Task::free_resources() {
}

m_open_files.clear();

// Free all open dirs.
for (auto* dir : m_open_dirs) {
fs.close_dir(dir);
}

m_open_dirs.clear();
}
6 changes: 6 additions & 0 deletions kernel/task/task.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct TaskSavedState {
class TaskManager;
class Window;
class File;
class Dir;

/**
* Represents a runnable task in the system. This can be a user process, a thread, etc.
Expand Down Expand Up @@ -112,6 +113,10 @@ class Task {
void register_file(File* file);
void unregister_file(File* file);

[[nodiscard]] bool own_dir(Dir* dir) const;
void register_dir(Dir* dir);
void unregister_dir(Dir* dir);

[[nodiscard]] bool can_preempt() const { return m_preempt_count == 0; }
void disable_preempt() { m_preempt_count++; }
void enable_preempt() {
Expand Down Expand Up @@ -145,6 +150,7 @@ class Task {
// Task resources
libk::LinkedList<Window*> m_windows;
libk::LinkedList<File*> m_open_files;
libk::LinkedList<Dir*> m_open_dirs;
libk::LinkedList<MemoryChunk> m_mapped_chunks;
}; // class Task

Expand Down
6 changes: 4 additions & 2 deletions kernel/wm/window_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,15 @@ void WindowManager::set_window_geometry(Window* window, int32_t x, int32_t y, in

// Handle special values.
if (x == SYS_POS_DEFAULT) {
x = 50;
x = m_last_window_x;
m_last_window_x += 50;
} else if (x == SYS_POS_CENTERED) {
x = m_screen_width / 2 - w / 2;
}

if (y == SYS_POS_DEFAULT) {
y = 50;
y = m_last_window_y;
m_last_window_y += 50;
} else if (y == SYS_POS_CENTERED) {
y = m_screen_height / 2 - h / 2;
}
Expand Down
2 changes: 2 additions & 0 deletions kernel/wm/window_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ class WindowManager {
libk::LinkedList<Window*> m_windows;
size_t m_window_count = 0;

uint32_t m_last_window_x = 50, m_last_window_y = 50;

#if defined(CONFIG_USE_DMA) && defined(CONFIG_USE_DMA_FOR_WALLPAPER)
libk::ScopedPointer<Buffer> m_wallpaper;
#else
Expand Down
11 changes: 11 additions & 0 deletions lib/libsyscall/include/sys/file.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ __SYS_EXTERN_C_BEGIN

typedef struct sys_file_t sys_file_t;

typedef struct sys_dir_t sys_dir_t;

typedef struct sys_file_info_t {
char name[256];
sys_bool_t is_dir;
} sys_file_info_t;

typedef enum sys_file_mode_t {
SYS_FM_READ = 0x1,
SYS_FM_WRITE = 0x2,
Expand All @@ -19,6 +26,10 @@ void sys_close_file(sys_file_t* file);
sys_error_t sys_file_read(sys_file_t* file, void* buffer, size_t bytes_to_read, size_t* read_bytes);
size_t sys_get_file_size(sys_file_t* file);

sys_dir_t* sys_open_dir(const char* path);
void sys_close_dir(sys_dir_t* dir);
sys_error_t sys_read_dir(sys_dir_t* dir, sys_file_info_t* info);

__SYS_EXTERN_C_END

#endif // !__PIKAOS_LIBC_SYS_FILE_H__
3 changes: 2 additions & 1 deletion lib/libsyscall/include/sys/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ enum {
SYS_ERR_MSG_QUEUE_EMPTY,
SYS_ERR_OUT_OF_MEM,
SYS_ERR_INVALID_WINDOW,
SYS_ERR_INVALID_FILE
SYS_ERR_INVALID_FILE,
SYS_ERR_INVALID_DIR,
};

#define SYS_IS_OK(e) ((e) == SYS_ERR_OK)
Expand Down
5 changes: 3 additions & 2 deletions lib/libsyscall/include/sys/syscall_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ enum {
SYS_READ_FILE,
SYS_GET_FILE_SIZE,

SYS_FIND_FIRST_FILE,
SYS_FIND_NEXT_FILE,
SYS_OPEN_DIR,
SYS_CLOSE_DIR,
SYS_READ_DIR,

/* Window manager system calls. */
SYS_POLL_MESSAGE,
Expand Down
15 changes: 15 additions & 0 deletions lib/libsyscall/src/sys/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,18 @@ size_t sys_get_file_size(sys_file_t* file) {
assert(file != NULL);
return __syscall1(SYS_GET_FILE_SIZE, (sys_word_t)file);
}

sys_dir_t* sys_open_dir(const char* path) {
assert(path != NULL);
return (sys_dir_t*)__syscall1(SYS_OPEN_DIR, (sys_word_t)path);
}

void sys_close_dir(sys_dir_t* dir) {
assert(dir != NULL);
__syscall1(SYS_CLOSE_DIR, (sys_word_t)dir);
}

sys_error_t sys_read_dir(sys_dir_t* dir, sys_file_info_t* info) {
assert(dir != NULL && info != NULL);
return __syscall2(SYS_READ_DIR, (sys_word_t)dir, (sys_word_t)info);
}
15 changes: 9 additions & 6 deletions make-fs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ set -e

mkdir -p ./fs/usr/bin

cd cmake-build-release-clang-17 || exit
cd cmake-build-gcc-release || exit

make init
ninja init
mv usr/init ../fs/init

make credits
ninja credits
mv usr/credits ../fs/usr/bin/credits

make slides
ninja slides
mv usr/slides ../fs/usr/bin/slides

#cd ../tools || exit
#./create-fs.sh ../home_made/gen-files/fs.img
ninja explorer
mv usr/explorer ../fs/usr/bin/explorer

cd ../tools || exit
./create-fs.sh ../fs.bin
1 change: 1 addition & 0 deletions usr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ endfunction()
add_userspace_executable(init init.c)
add_userspace_executable(credits credits.c)
add_userspace_executable(slides slides.c stb_image.c)
add_userspace_executable(explorer explorer.c)
Loading

0 comments on commit ccaf48c

Please sign in to comment.