Virtual filesystem and ramdiskfs
All checks were successful
Build documentation / build-and-deploy (push) Successful in 27s

This commit is contained in:
2026-02-11 21:36:50 +01:00
parent 9e6035bd68
commit 4ad1519e06
21 changed files with 528 additions and 128 deletions

1
kernel/fs/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.o

96
kernel/fs/path.c Normal file
View File

@@ -0,0 +1,96 @@
#include <fs/vfs.h>
#include <libk/fieldsizeof.h>
#include <libk/std.h>
bool path_validate_char (char ch) {
return ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
(ch == '_') || (ch == '_'));
}
bool path_validate (const char* path) {
if (path == NULL || *path == '\0')
return false;
const char* ptr = path;
if (*ptr == ':')
return false;
while (*ptr != ':' && *ptr != '\0') {
if (!path_validate_char (*ptr))
return false;
ptr++;
}
if (*ptr != ':')
return false;
ptr++;
if (*ptr != '/')
return false;
while (*ptr != '\0') {
if (*ptr == '/' && *(ptr + 1) == '/')
return false;
if (!path_validate_char (*ptr))
return false;
ptr++;
}
if (ptr > path && *(ptr - 1) == '/' && *(ptr - 2) != ':')
return false;
return true;
}
bool path_parse (const char* source, char* mountpoint, const char** path) {
if (source == NULL || mountpoint == NULL || path == NULL)
return false;
size_t i = 0;
while (source[i] != ':' && source[i] != '\0') {
if (i >= (fieldsizeof (struct vfs_mountpoint, key) - 1))
return false;
mountpoint[i] = source[i];
i++;
}
if (source[i] != ':' || i == 0)
return false;
mountpoint[i] = '\0';
const char* internal_path = &source[i + 1];
if (!path_validate (internal_path))
return false;
*path = internal_path;
return true;
}
const char* path_basename (const char* path) {
if (path == NULL)
return NULL;
const char* last_slash = NULL;
const char* ptr = path;
while (*ptr != '\0') {
if (*ptr == '/')
last_slash = ptr;
ptr++;
}
if (last_slash == NULL)
return path;
return last_slash + 1;
}

13
kernel/fs/path.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef _KERNEL_FS_PATH_H
#define _KERNEL_FS_PATH_H
#include <libk/std.h>
/* Path scheme: MOUNTPOINT:/path/to/file.txt */
bool path_validate_char (char ch);
bool path_validate (const char* path);
bool path_parse (const char* source, char* mountpoint, const char** path);
const char* path_basename (const char* path);
#endif // _KERNEL_FS_PATH_H

138
kernel/fs/ramdiskfs.c Normal file
View File

@@ -0,0 +1,138 @@
#include <fs/path.h>
#include <fs/ramdiskfs.h>
#include <fs/vfs.h>
#include <libk/std.h>
#include <libk/string.h>
#include <limine/requests.h>
#include <m/fs_desc_buffer.h>
struct ramdisk_tar_header {
char filename[100];
uint8_t mode[8];
uint8_t uid[8];
uint8_t gid[8];
uint8_t size[12];
uint8_t mtime[12];
uint8_t checksum[8];
uint8_t type_flag;
} PACKED;
struct ramdisk_tar_file {
struct ramdisk_tar_header* header;
uint8_t* content;
size_t size;
};
#define RAMDISK_FILES_MAX 128
#define RAMDISK_PATH "/boot/mop3dist.tar"
static struct ramdisk_tar_file ramdisk_files[RAMDISK_FILES_MAX];
static struct ramdisk_tar_file* ramdisk_get_file (const char* filename) {
for (size_t i = 0; i < RAMDISK_FILES_MAX; i++) {
if ((ramdisk_files[i].header != NULL) &&
(memcmp (ramdisk_files[i].header->filename, filename, strlen (filename)) == 0))
return &ramdisk_files[i];
}
return NULL;
}
static size_t ramdisk_tar_get_size (uint8_t* in) {
size_t size = 0;
size_t j;
size_t count = 1;
for (j = 11; j > 0; j--, count *= 8)
size += ((in[j - 1] - '0') * count);
return size;
}
static size_t ramdisk_tar_parse (uint8_t* addr) {
size_t i;
for (i = 0;; i++) {
struct ramdisk_tar_header* hdr = (struct ramdisk_tar_header*)addr;
if (hdr->filename[i] == '\0')
break;
size_t size = ramdisk_tar_get_size (hdr->size);
ramdisk_files[i].header = hdr;
ramdisk_files[i].content = (uint8_t*)((uintptr_t)hdr + 512);
ramdisk_files[i].size = ramdisk_tar_get_size ((uint8_t*)hdr->size);
addr += ((size / 512) + 1) * 512;
if (size % 512)
addr += 512;
}
return i;
}
bool ramdiskfs_mount (struct vfs_mountpoint* mountpoint) {
(void)mountpoint;
struct limine_module_response* module = limine_module_request.response;
uint8_t* rd_addr = NULL;
for (size_t i = 0; i < module->module_count; i++) {
struct limine_file* file = module->modules[i];
if (memcmp (file->path, RAMDISK_PATH, strlen (RAMDISK_PATH)) == 0) {
rd_addr = file->address;
}
}
if (rd_addr == NULL)
return false;
ramdisk_tar_parse (rd_addr);
return true;
}
int ramdiskfs_describe (struct vfs_mountpoint* mountpoint, const char* path,
struct fs_desc_buffer* desc) {
(void)mountpoint;
const char* filename = path_basename (path);
if (filename == NULL)
return -VFS_BAD_PATH;
struct ramdisk_tar_file* file = ramdisk_get_file (filename);
if (file == NULL)
return -VFS_NOT_FOUND;
desc->size = file->size;
desc->type = FS_FILE;
return VFS_OK;
}
int ramdiskfs_read (struct vfs_mountpoint* mountpoint, const char* path, uint8_t* buffer,
size_t off, size_t size) {
(void)mountpoint;
const char* filename = path_basename (path);
if (filename == NULL)
return -VFS_BAD_PATH;
struct ramdisk_tar_file* file = ramdisk_get_file (filename);
if (file == NULL)
return -VFS_NOT_FOUND;
if (off + size > file->size)
return -VFS_OOB_ERROR;
memcpy (buffer, (void*)((uintptr_t)file->content + off), size);
return VFS_OK;
}

15
kernel/fs/ramdiskfs.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef _KERNEL_FS_RAMDISKFS_H
#define _KERNEL_FS_RAMDISKFS_H
#include <libk/std.h>
#include <m/fs_desc_buffer.h>
struct vfs_mountpoint;
bool ramdiskfs_mount (struct vfs_mountpoint* mountpoint);
int ramdiskfs_describe (struct vfs_mountpoint* mountpoint, const char* path,
struct fs_desc_buffer* desc);
int ramdiskfs_read (struct vfs_mountpoint* mountpoint, const char* path, uint8_t* buffer,
size_t off, size_t size);
#endif // _KERNEL_FS_RAMDISKFS_H

7
kernel/fs/src.mk Normal file
View File

@@ -0,0 +1,7 @@
c += fs/vfs.c \
fs/ramdiskfs.c \
fs/path.c
o += fs/vfs.o \
fs/ramdiskfs.o \
fs/path.o

99
kernel/fs/vfs.c Normal file
View File

@@ -0,0 +1,99 @@
#include <fs/ramdiskfs.h>
#include <fs/vfs.h>
#include <libk/fieldsizeof.h>
#include <libk/hash.h>
#include <libk/lengthof.h>
#include <libk/std.h>
#include <libk/string.h>
#include <mm/liballoc.h>
#include <sync/spin_lock.h>
#include <sys/debug.h>
static struct vfs_mount_table mount_table;
static struct vfs_mountpoint* vfs_find_mountpoint (const char* mountpoint) {
struct hash_node_link* found_link = NULL;
size_t mountpoint_len = strlen (mountpoint);
uint32_t hash = hash_fnv32 (mountpoint, strlen (mountpoint));
spin_lock (&mount_table.lock);
hash_find (&mount_table, mountpoint, mountpoint_len, hash,
lengthof (mount_table.mountpoint_buckets), mountpoint_buckets, struct vfs_mountpoint,
mount_table_link, key, found_link);
spin_unlock (&mount_table.lock);
if (found_link == NULL)
return NULL;
return hash_entry (found_link, struct vfs_mountpoint, mount_table_link);
}
struct vfs_mountpoint* vfs_create_mountpoint (const char* key, int fs_type) {
if (strlen_null (key) > fieldsizeof (struct vfs_mountpoint, key))
return NULL;
struct vfs_mountpoint* mountpoint = malloc (sizeof (*mountpoint));
if (mountpoint == NULL)
return NULL;
memset (mountpoint, 0, sizeof (*mountpoint));
memcpy (mountpoint->key, key, strlen_null (key));
mountpoint->fs_type = fs_type;
mountpoint->lock = SPIN_LOCK_INIT;
switch (mountpoint->fs_type) {
case VFS_RAMDISKFS: {
mountpoint->driver_ops.mount = &ramdiskfs_mount;
mountpoint->driver_ops.describe = &ramdiskfs_describe;
mountpoint->driver_ops.read = &ramdiskfs_read;
} break;
default: {
free (mountpoint);
return NULL;
} break;
}
bool ok = mountpoint->driver_ops.mount (mountpoint);
if (!ok) {
free (mountpoint);
return NULL;
}
uint32_t mp_hash = hash_fnv32 (mountpoint->key, strlen (mountpoint->key));
spin_lock (&mount_table.lock);
hash_insert (&mount_table, &mountpoint->mount_table_link, mp_hash,
lengthof (mount_table.mountpoint_buckets), mountpoint_buckets);
spin_unlock (&mount_table.lock);
return mountpoint;
}
int vfs_describe (const char* mountpoint, const char* path, struct fs_desc_buffer* desc) {
struct vfs_mountpoint* vmp = vfs_find_mountpoint (mountpoint);
if (vmp == NULL)
return -VFS_NOT_FOUND;
return vmp->driver_ops.describe (vmp, path, desc);
}
int vfs_read (const char* mountpoint, const char* path, uint8_t* buffer, size_t off, size_t size) {
struct vfs_mountpoint* vmp = vfs_find_mountpoint (mountpoint);
if (vmp == NULL)
return -VFS_NOT_FOUND;
return vmp->driver_ops.read (vmp, path, buffer, off, size);
}
void vfs_init (void) {
memset (&mount_table, 0, sizeof (mount_table));
mount_table.lock = SPIN_LOCK_INIT;
}

42
kernel/fs/vfs.h Normal file
View File

@@ -0,0 +1,42 @@
#ifndef _KERNEL_FS_VFS_H
#define _KERNEL_FS_VFS_H
#include <libk/hash.h>
#include <libk/list.h>
#include <libk/std.h>
#include <m/fs_desc_buffer.h>
#include <sync/spin_lock.h>
#define VFS_OK 0
#define VFS_EXISTS 1
#define VFS_NOT_FOUND 2
#define VFS_BAD_PATH 3
#define VFS_OOB_ERROR 4
#define VFS_RAMDISKFS 0
struct vfs_mountpoint {
char key[0x100];
struct hash_node_link mount_table_link;
int fs_type;
spin_lock_t lock;
struct {
bool (*mount) (struct vfs_mountpoint* mountpoint);
int (*describe) (struct vfs_mountpoint* mountpoint, const char* path,
struct fs_desc_buffer* desc);
int (*read) (struct vfs_mountpoint* mountpoint, const char* path, uint8_t* buffer, size_t off,
size_t size);
} driver_ops;
};
struct vfs_mount_table {
struct hash_node_link* mountpoint_buckets[1024];
spin_lock_t lock;
};
struct vfs_mountpoint* vfs_create_mountpoint (const char* key, int fs_type);
int vfs_describe (const char* mountpoint, const char* path, struct fs_desc_buffer* desc);
int vfs_read (const char* mountpoint, const char* path, uint8_t* buffer, size_t off, size_t size);
void vfs_init (void);
#endif // _KERNEL_FS_VFS_H