mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 10:26:59 +00:00
FEAT: VFS overhaul
This commit is contained in:
181
src/fs/sysfs.c
Normal file
181
src/fs/sysfs.c
Normal file
@@ -0,0 +1,181 @@
|
||||
#include "vfs.h"
|
||||
#include "../sys/kernel_subsystem.h"
|
||||
#include "memory_manager.h"
|
||||
#include "core/kutils.h"
|
||||
|
||||
typedef struct {
|
||||
kernel_subsystem_t *sub;
|
||||
subsystem_file_t *file;
|
||||
int offset;
|
||||
} sysfs_handle_t;
|
||||
|
||||
static void* sysfs_open(void *fs_private, const char *path, const char *mode) {
|
||||
if (path[0] == '/') path++;
|
||||
if (path[0] == '\0') return NULL;
|
||||
|
||||
kernel_subsystem_t *sub = NULL;
|
||||
int last_slash = -1;
|
||||
for (int j = 0; path[j]; j++) if (path[j] == '/') last_slash = j;
|
||||
|
||||
if (last_slash != -1) {
|
||||
char prefix[64];
|
||||
k_memcpy(prefix, path, last_slash);
|
||||
prefix[last_slash] = 0;
|
||||
sub = subsystem_get_by_name(prefix);
|
||||
|
||||
if (sub) {
|
||||
const char *filename = path + last_slash + 1;
|
||||
for (int j = 0; j < sub->file_count; j++) {
|
||||
if (k_strcmp(sub->files[j].name, filename) == 0) {
|
||||
sysfs_handle_t *h = (sysfs_handle_t*)kmalloc(sizeof(sysfs_handle_t));
|
||||
h->sub = sub;
|
||||
h->file = &sub->files[j];
|
||||
h->offset = 0;
|
||||
return h;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sysfs_close(void *fs_private, void *handle) {
|
||||
if (handle) kfree(handle);
|
||||
}
|
||||
|
||||
static int sysfs_read(void *fs_private, void *handle, void *buf, int size) {
|
||||
sysfs_handle_t *h = (sysfs_handle_t*)handle;
|
||||
if (!h || !h->file || !h->file->read) return -1;
|
||||
|
||||
int bytes = h->file->read((char*)buf, size, h->offset);
|
||||
if (bytes > 0) h->offset += bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static int sysfs_write(void *fs_private, void *handle, const void *buf, int size) {
|
||||
sysfs_handle_t *h = (sysfs_handle_t*)handle;
|
||||
if (!h || !h->file || !h->file->write) return -1;
|
||||
|
||||
int bytes = h->file->write((const char*)buf, size, h->offset);
|
||||
if (bytes > 0) h->offset += bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static int sysfs_readdir(void *fs_private, const char *path, vfs_dirent_t *entries, int max) {
|
||||
if (path[0] == '/') path++;
|
||||
|
||||
kernel_subsystem_t *exact_sub = subsystem_get_by_name(path);
|
||||
int out = 0;
|
||||
|
||||
if (exact_sub) {
|
||||
for (int i = 0; i < exact_sub->file_count && out < max; i++) {
|
||||
k_strcpy(entries[out].name, exact_sub->files[i].name);
|
||||
entries[out].is_directory = 0;
|
||||
entries[out].size = 0;
|
||||
out++;
|
||||
}
|
||||
}
|
||||
|
||||
int count = subsystem_get_count();
|
||||
int path_len = k_strlen(path);
|
||||
|
||||
for (int i = 0; i < count && out < max; i++) {
|
||||
kernel_subsystem_t *s = subsystem_get_by_index(i);
|
||||
if (path_len == 0 || (k_strlen(s->name) > path_len && k_strncmp(s->name, path, path_len) == 0 && s->name[path_len] == '/')) {
|
||||
const char *sub_path = s->name + (path_len ? path_len + 1 : 0);
|
||||
char comp[64];
|
||||
int j = 0;
|
||||
while (sub_path[j] && sub_path[j] != '/' && j < 63) {
|
||||
comp[j] = sub_path[j];
|
||||
j++;
|
||||
}
|
||||
comp[j] = 0;
|
||||
|
||||
if (comp[0] == '\0') continue;
|
||||
|
||||
bool found = false;
|
||||
for (int k = 0; k < out; k++) {
|
||||
if (k_strcmp(entries[k].name, comp) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
k_strcpy(entries[out].name, comp);
|
||||
entries[out].is_directory = 1;
|
||||
entries[out].size = 0;
|
||||
out++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static bool sysfs_exists(void *fs_private, const char *path) {
|
||||
if (path[0] == '/') path++;
|
||||
if (path[0] == '\0') return true;
|
||||
|
||||
if (subsystem_get_by_name(path)) return true;
|
||||
|
||||
// File check
|
||||
int last_slash = -1;
|
||||
for (int j = 0; path[j]; j++) if (path[j] == '/') last_slash = j;
|
||||
if (last_slash != -1) {
|
||||
char prefix[64];
|
||||
k_memcpy(prefix, path, last_slash);
|
||||
prefix[last_slash] = 0;
|
||||
kernel_subsystem_t *sub = subsystem_get_by_name(prefix);
|
||||
if (sub) {
|
||||
const char *filename = path + last_slash + 1;
|
||||
for (int j = 0; j < sub->file_count; j++) {
|
||||
if (k_strcmp(sub->files[j].name, filename) == 0) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int count = subsystem_get_count();
|
||||
int path_len = k_strlen(path);
|
||||
for (int i = 0; i < count; i++) {
|
||||
kernel_subsystem_t *s = subsystem_get_by_index(i);
|
||||
if (k_strlen(s->name) > path_len && k_strncmp(s->name, path, path_len) == 0 && s->name[path_len] == '/') return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool sysfs_is_dir(void *fs_private, const char *path) {
|
||||
if (path[0] == '/') path++;
|
||||
if (path[0] == '\0') return true;
|
||||
|
||||
int last_slash = -1;
|
||||
for (int j = 0; path[j]; j++) if (path[j] == '/') last_slash = j;
|
||||
if (last_slash != -1) {
|
||||
char prefix[64];
|
||||
k_memcpy(prefix, path, last_slash);
|
||||
prefix[last_slash] = 0;
|
||||
kernel_subsystem_t *sub = subsystem_get_by_name(prefix);
|
||||
if (sub) {
|
||||
const char *filename = path + last_slash + 1;
|
||||
for (int j = 0; j < sub->file_count; j++) {
|
||||
if (k_strcmp(sub->files[j].name, filename) == 0) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sysfs_exists(fs_private, path);
|
||||
}
|
||||
|
||||
vfs_fs_ops_t sysfs_ops = {
|
||||
.open = sysfs_open,
|
||||
.close = sysfs_close,
|
||||
.read = sysfs_read,
|
||||
.write = sysfs_write,
|
||||
.readdir = sysfs_readdir,
|
||||
.exists = sysfs_exists,
|
||||
.is_dir = sysfs_is_dir
|
||||
};
|
||||
|
||||
vfs_fs_ops_t* sysfs_get_ops(void) {
|
||||
return &sysfs_ops;
|
||||
}
|
||||
Reference in New Issue
Block a user