mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-26 00:52:50 +00:00
Initial commit: SUB-OS 64-Bit Production Monolithic Operating System with LazyBox userland suite
This commit is contained in:
commit
cd9c786d14
88 files changed
+7132
No files matched your search
+79
@@ -0,0 +1,79 @@
|
||||
#include <fs/devfs.h>
|
||||
#include <fs/ramfs.h>
|
||||
#include <drivers/tty.h>
|
||||
#include <crypto/crypto.h>
|
||||
#include <lib/string.h>
|
||||
#include <mm/kmalloc.h>
|
||||
|
||||
static vfs_node_t* devfs_root = NULL;
|
||||
|
||||
static ssize_t dev_null_write(vfs_node_t* node, off_t offset, size_t size, const uint8_t* buffer) {
|
||||
(void)node; (void)offset; (void)buffer;
|
||||
return (ssize_t)size; // Discard everything
|
||||
}
|
||||
|
||||
static ssize_t dev_null_read(vfs_node_t* node, off_t offset, size_t size, uint8_t* buffer) {
|
||||
(void)node; (void)offset; (void)size; (void)buffer;
|
||||
return 0; // EOF immediately
|
||||
}
|
||||
|
||||
static ssize_t dev_zero_read(vfs_node_t* node, off_t offset, size_t size, uint8_t* buffer) {
|
||||
(void)node; (void)offset;
|
||||
memset(buffer, 0, size);
|
||||
return (ssize_t)size;
|
||||
}
|
||||
|
||||
static ssize_t dev_random_read(vfs_node_t* node, off_t offset, size_t size, uint8_t* buffer) {
|
||||
(void)node; (void)offset;
|
||||
prng_get_bytes(buffer, size);
|
||||
return (ssize_t)size;
|
||||
}
|
||||
|
||||
static ssize_t dev_tty_write(vfs_node_t* node, off_t offset, size_t size, const uint8_t* buffer) {
|
||||
(void)node; (void)offset;
|
||||
tty_write((const char*)buffer, size);
|
||||
return (ssize_t)size;
|
||||
}
|
||||
|
||||
void devfs_init(void) {
|
||||
devfs_root = ramfs_add_dir(NULL, "dev");
|
||||
|
||||
// 1. /dev/null
|
||||
vfs_node_t* null_dev = ramfs_add_file(devfs_root, "null", NULL, 0);
|
||||
if (null_dev) {
|
||||
null_dev->flags = FS_CHARDEVICE;
|
||||
null_dev->read = dev_null_read;
|
||||
null_dev->write = dev_null_write;
|
||||
}
|
||||
|
||||
// 2. /dev/zero
|
||||
vfs_node_t* zero_dev = ramfs_add_file(devfs_root, "zero", NULL, 0);
|
||||
if (zero_dev) {
|
||||
zero_dev->flags = FS_CHARDEVICE;
|
||||
zero_dev->read = dev_zero_read;
|
||||
zero_dev->write = dev_null_write;
|
||||
}
|
||||
|
||||
// 3. /dev/random & /dev/urandom
|
||||
vfs_node_t* rand_dev = ramfs_add_file(devfs_root, "random", NULL, 0);
|
||||
if (rand_dev) {
|
||||
rand_dev->flags = FS_CHARDEVICE;
|
||||
rand_dev->read = dev_random_read;
|
||||
}
|
||||
vfs_node_t* urand_dev = ramfs_add_file(devfs_root, "urandom", NULL, 0);
|
||||
if (urand_dev) {
|
||||
urand_dev->flags = FS_CHARDEVICE;
|
||||
urand_dev->read = dev_random_read;
|
||||
}
|
||||
|
||||
// 4. /dev/tty
|
||||
vfs_node_t* tty_dev = ramfs_add_file(devfs_root, "tty", NULL, 0);
|
||||
if (tty_dev) {
|
||||
tty_dev->flags = FS_CHARDEVICE;
|
||||
tty_dev->write = dev_tty_write;
|
||||
}
|
||||
}
|
||||
|
||||
vfs_node_t* devfs_get_root(void) {
|
||||
return devfs_root;
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
#include <fs/procfs.h>
|
||||
#include <fs/ramfs.h>
|
||||
#include <arch/x86_64/cpuid.h>
|
||||
#include <arch/x86_64/pit.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <mm/kmalloc.h>
|
||||
#include <drivers/e1000.h>
|
||||
#include <lib/printf.h>
|
||||
#include <lib/string.h>
|
||||
|
||||
static vfs_node_t* procfs_root = NULL;
|
||||
|
||||
static ssize_t proc_version_read(vfs_node_t* node, off_t offset, size_t size, uint8_t* buffer) {
|
||||
(void)node;
|
||||
char text[256];
|
||||
int len = sprintf(text, "SUB-OS version 0.2.0-lts (subhobhai@sub-os) (x86_64-elf-gcc 13.3.0) #1 SMP PREEMPT Sun Aug 16 2026\n");
|
||||
if (offset >= len) return 0;
|
||||
if (offset + size > (size_t)len) size = len - offset;
|
||||
memcpy(buffer, text + offset, size);
|
||||
return (ssize_t)size;
|
||||
}
|
||||
|
||||
static ssize_t proc_uptime_read(vfs_node_t* node, off_t offset, size_t size, uint8_t* buffer) {
|
||||
(void)node;
|
||||
uint64_t ticks = pit_get_ticks();
|
||||
uint64_t secs = ticks / 100;
|
||||
uint64_t frac = (ticks % 100);
|
||||
|
||||
char text[64];
|
||||
int len = sprintf(text, "%llu.%02llu %llu.%02llu\n", secs, frac, secs, frac);
|
||||
if (offset >= len) return 0;
|
||||
if (offset + size > (size_t)len) size = len - offset;
|
||||
memcpy(buffer, text + offset, size);
|
||||
return (ssize_t)size;
|
||||
}
|
||||
|
||||
static ssize_t proc_meminfo_read(vfs_node_t* node, off_t offset, size_t size, uint8_t* buffer) {
|
||||
(void)node;
|
||||
uint64_t total_kb = (pmm_get_total_pages() * 4096) / 1024;
|
||||
uint64_t free_kb = (pmm_get_free_pages() * 4096) / 1024;
|
||||
uint64_t used_kb = (pmm_get_used_pages() * 4096) / 1024;
|
||||
|
||||
char text[512];
|
||||
int len = sprintf(text,
|
||||
"MemTotal: %8llu kB\n"
|
||||
"MemFree: %8llu kB\n"
|
||||
"MemAvailable: %8llu kB\n"
|
||||
"Buffers: 0 kB\n"
|
||||
"Cached: %8llu kB\n"
|
||||
"HeapTotal: %8llu kB\n"
|
||||
"HeapUsed: %8llu kB\n"
|
||||
"HeapFree: %8llu kB\n",
|
||||
total_kb, free_kb, free_kb,
|
||||
(heap_get_used_bytes() / 1024),
|
||||
heap_get_total_bytes() / 1024,
|
||||
heap_get_used_bytes() / 1024,
|
||||
heap_get_free_bytes() / 1024);
|
||||
|
||||
if (offset >= len) return 0;
|
||||
if (offset + size > (size_t)len) size = len - offset;
|
||||
memcpy(buffer, text + offset, size);
|
||||
return (ssize_t)size;
|
||||
}
|
||||
|
||||
static ssize_t proc_cpuinfo_read(vfs_node_t* node, off_t offset, size_t size, uint8_t* buffer) {
|
||||
(void)node;
|
||||
const cpu_info_t* cpu = cpuid_get_info();
|
||||
|
||||
char text[1024];
|
||||
int len = sprintf(text,
|
||||
"processor\t: 0\n"
|
||||
"vendor_id\t: %s\n"
|
||||
"cpu family\t: %u\n"
|
||||
"model\t\t: %u\n"
|
||||
"model name\t: %s\n"
|
||||
"stepping\t: %u\n"
|
||||
"flags\t\t: %s%s%s%s%s%s%s%s%s\n"
|
||||
"bogomips\t: 4800.00\n"
|
||||
"clflush size\t: 64\n",
|
||||
cpu->vendor,
|
||||
cpu->family,
|
||||
cpu->model_id,
|
||||
cpu->model,
|
||||
cpu->stepping,
|
||||
cpu->has_fpu ? "fpu " : "",
|
||||
cpu->has_tsc ? "tsc " : "",
|
||||
cpu->has_pae ? "pae " : "",
|
||||
cpu->has_apic ? "apic " : "",
|
||||
cpu->has_sse ? "sse " : "",
|
||||
cpu->has_sse2 ? "sse2 " : "",
|
||||
cpu->has_sse3 ? "sse3 " : "",
|
||||
cpu->has_sse4_1 ? "sse4_1 " : "",
|
||||
cpu->has_avx ? "avx " : "");
|
||||
|
||||
if (offset >= len) return 0;
|
||||
if (offset + size > (size_t)len) size = len - offset;
|
||||
memcpy(buffer, text + offset, size);
|
||||
return (ssize_t)size;
|
||||
}
|
||||
|
||||
static ssize_t proc_net_dev_read(vfs_node_t* node, off_t offset, size_t size, uint8_t* buffer) {
|
||||
(void)node;
|
||||
char text[512];
|
||||
int len = sprintf(text,
|
||||
"Inter-| Receive | Transmit\n"
|
||||
" face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed\n"
|
||||
" lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
|
||||
" eth0: %7llu %7llu 0 0 0 0 0 0 %7llu %7llu 0 0 0 0 0 0\n",
|
||||
e1000_get_rx_bytes(), e1000_get_rx_packets(),
|
||||
e1000_get_tx_bytes(), e1000_get_tx_packets());
|
||||
|
||||
if (offset >= len) return 0;
|
||||
if (offset + size > (size_t)len) size = len - offset;
|
||||
memcpy(buffer, text + offset, size);
|
||||
return (ssize_t)size;
|
||||
}
|
||||
|
||||
void procfs_init(void) {
|
||||
procfs_root = ramfs_add_dir(NULL, "proc");
|
||||
|
||||
vfs_node_t* ver = ramfs_add_file(procfs_root, "version", NULL, 0);
|
||||
if (ver) { ver->flags = FS_FILE; ver->read = proc_version_read; }
|
||||
|
||||
vfs_node_t* uptime = ramfs_add_file(procfs_root, "uptime", NULL, 0);
|
||||
if (uptime) { uptime->flags = FS_FILE; uptime->read = proc_uptime_read; }
|
||||
|
||||
vfs_node_t* mem = ramfs_add_file(procfs_root, "meminfo", NULL, 0);
|
||||
if (mem) { mem->flags = FS_FILE; mem->read = proc_meminfo_read; }
|
||||
|
||||
vfs_node_t* cpu = ramfs_add_file(procfs_root, "cpuinfo", NULL, 0);
|
||||
if (cpu) { cpu->flags = FS_FILE; cpu->read = proc_cpuinfo_read; }
|
||||
|
||||
vfs_node_t* net_dir = ramfs_add_dir(procfs_root, "net");
|
||||
if (net_dir) {
|
||||
vfs_node_t* net_dev = ramfs_add_file(net_dir, "dev", NULL, 0);
|
||||
if (net_dev) { net_dev->flags = FS_FILE; net_dev->read = proc_net_dev_read; }
|
||||
}
|
||||
}
|
||||
|
||||
vfs_node_t* procfs_get_root(void) {
|
||||
return procfs_root;
|
||||
}
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
#include <fs/ramfs.h>
|
||||
#include <mm/kmalloc.h>
|
||||
#include <lib/string.h>
|
||||
|
||||
#define MAX_CHILDREN 32
|
||||
|
||||
typedef struct ramfs_entry {
|
||||
vfs_node_t node;
|
||||
uint8_t* data;
|
||||
size_t capacity;
|
||||
struct ramfs_entry* children[MAX_CHILDREN];
|
||||
uint32_t child_count;
|
||||
} ramfs_entry_t;
|
||||
|
||||
static vfs_dirent_t shared_dirent;
|
||||
|
||||
static int ramfs_mkdir_impl(vfs_node_t* parent, const char* name, mode_t mode);
|
||||
static int ramfs_create_impl(vfs_node_t* parent, const char* name, mode_t mode);
|
||||
static struct vfs_dirent* ramfs_readdir(vfs_node_t* node, uint32_t index);
|
||||
static struct vfs_node* ramfs_finddir(vfs_node_t* node, const char* name);
|
||||
|
||||
static ssize_t ramfs_read(vfs_node_t* node, off_t offset, size_t size, uint8_t* buffer) {
|
||||
ramfs_entry_t* entry = (ramfs_entry_t*)node;
|
||||
if (!entry || !entry->data || (size_t)offset >= node->length) return 0;
|
||||
|
||||
if (offset + size > node->length) {
|
||||
size = node->length - offset;
|
||||
}
|
||||
|
||||
memcpy(buffer, entry->data + offset, size);
|
||||
return (ssize_t)size;
|
||||
}
|
||||
|
||||
static ssize_t ramfs_write(vfs_node_t* node, off_t offset, size_t size, const uint8_t* buffer) {
|
||||
ramfs_entry_t* entry = (ramfs_entry_t*)node;
|
||||
if (!entry) return -1;
|
||||
|
||||
if (offset + size > entry->capacity) {
|
||||
size_t new_cap = (offset + size + 256) & ~255;
|
||||
uint8_t* new_data = (uint8_t*)kmalloc(new_cap);
|
||||
if (!new_data) return -1;
|
||||
|
||||
if (entry->data) {
|
||||
memcpy(new_data, entry->data, node->length);
|
||||
kfree(entry->data);
|
||||
}
|
||||
entry->data = new_data;
|
||||
entry->capacity = new_cap;
|
||||
}
|
||||
|
||||
memcpy(entry->data + offset, buffer, size);
|
||||
if (offset + size > node->length) {
|
||||
node->length = offset + size;
|
||||
}
|
||||
return (ssize_t)size;
|
||||
}
|
||||
|
||||
static struct vfs_dirent* ramfs_readdir(vfs_node_t* node, uint32_t index) {
|
||||
ramfs_entry_t* entry = (ramfs_entry_t*)node;
|
||||
if (!entry || index >= entry->child_count) return NULL;
|
||||
|
||||
strncpy(shared_dirent.name, entry->children[index]->node.name, sizeof(shared_dirent.name) - 1);
|
||||
shared_dirent.inode = entry->children[index]->node.inode;
|
||||
shared_dirent.type = entry->children[index]->node.flags;
|
||||
return &shared_dirent;
|
||||
}
|
||||
|
||||
static struct vfs_node* ramfs_finddir(vfs_node_t* node, const char* name) {
|
||||
ramfs_entry_t* entry = (ramfs_entry_t*)node;
|
||||
if (!entry) return NULL;
|
||||
|
||||
for (uint32_t i = 0; i < entry->child_count; i++) {
|
||||
if (strcmp(entry->children[i]->node.name, name) == 0) {
|
||||
return &entry->children[i]->node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ramfs_mkdir_impl(vfs_node_t* parent, const char* name, mode_t mode) {
|
||||
ramfs_entry_t* p = (ramfs_entry_t*)parent;
|
||||
if (!p || p->child_count >= MAX_CHILDREN) return -1;
|
||||
|
||||
ramfs_entry_t* child = (ramfs_entry_t*)kzalloc(sizeof(ramfs_entry_t));
|
||||
if (!child) return -1;
|
||||
|
||||
strncpy(child->node.name, name, sizeof(child->node.name) - 1);
|
||||
child->node.flags = FS_DIRECTORY;
|
||||
child->node.mode = mode;
|
||||
child->node.readdir = ramfs_readdir;
|
||||
child->node.finddir = ramfs_finddir;
|
||||
child->node.mkdir = ramfs_mkdir_impl;
|
||||
child->node.create = ramfs_create_impl;
|
||||
|
||||
p->children[p->child_count++] = child;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ramfs_create_impl(vfs_node_t* parent, const char* name, mode_t mode) {
|
||||
ramfs_entry_t* p = (ramfs_entry_t*)parent;
|
||||
if (!p || p->child_count >= MAX_CHILDREN) return -1;
|
||||
|
||||
ramfs_entry_t* child = (ramfs_entry_t*)kzalloc(sizeof(ramfs_entry_t));
|
||||
if (!child) return -1;
|
||||
|
||||
strncpy(child->node.name, name, sizeof(child->node.name) - 1);
|
||||
child->node.flags = FS_FILE;
|
||||
child->node.mode = mode;
|
||||
child->node.read = ramfs_read;
|
||||
child->node.write = ramfs_write;
|
||||
|
||||
p->children[p->child_count++] = child;
|
||||
return 0;
|
||||
}
|
||||
|
||||
vfs_node_t* ramfs_add_file(vfs_node_t* parent, const char* name, const void* content, size_t size) {
|
||||
ramfs_entry_t* p = (ramfs_entry_t*)parent;
|
||||
if (!p || p->child_count >= MAX_CHILDREN) return NULL;
|
||||
|
||||
ramfs_entry_t* child = (ramfs_entry_t*)kzalloc(sizeof(ramfs_entry_t));
|
||||
if (!child) return NULL;
|
||||
|
||||
strncpy(child->node.name, name, sizeof(child->node.name) - 1);
|
||||
child->node.flags = FS_FILE;
|
||||
child->node.mode = 0644;
|
||||
child->node.length = size;
|
||||
child->node.read = ramfs_read;
|
||||
child->node.write = ramfs_write;
|
||||
|
||||
if (size > 0 && content) {
|
||||
child->capacity = size;
|
||||
child->data = (uint8_t*)kmalloc(size);
|
||||
if (child->data) {
|
||||
memcpy(child->data, content, size);
|
||||
}
|
||||
}
|
||||
|
||||
p->children[p->child_count++] = child;
|
||||
return &child->node;
|
||||
}
|
||||
|
||||
vfs_node_t* ramfs_add_dir(vfs_node_t* parent, const char* name) {
|
||||
ramfs_entry_t* child = (ramfs_entry_t*)kzalloc(sizeof(ramfs_entry_t));
|
||||
if (!child) return NULL;
|
||||
|
||||
strncpy(child->node.name, name, sizeof(child->node.name) - 1);
|
||||
child->node.flags = FS_DIRECTORY;
|
||||
child->node.mode = 0755;
|
||||
child->node.readdir = ramfs_readdir;
|
||||
child->node.finddir = ramfs_finddir;
|
||||
child->node.mkdir = ramfs_mkdir_impl;
|
||||
child->node.create = ramfs_create_impl;
|
||||
|
||||
if (parent) {
|
||||
ramfs_entry_t* p = (ramfs_entry_t*)parent;
|
||||
if (p->child_count < MAX_CHILDREN) {
|
||||
p->children[p->child_count++] = child;
|
||||
}
|
||||
}
|
||||
|
||||
return &child->node;
|
||||
}
|
||||
|
||||
vfs_node_t* ramfs_create_root(void) {
|
||||
ramfs_entry_t* root = (ramfs_entry_t*)kzalloc(sizeof(ramfs_entry_t));
|
||||
if (!root) return NULL;
|
||||
|
||||
strcpy(root->node.name, "/");
|
||||
root->node.flags = FS_DIRECTORY;
|
||||
root->node.mode = 0755;
|
||||
root->node.readdir = ramfs_readdir;
|
||||
root->node.finddir = ramfs_finddir;
|
||||
root->node.mkdir = ramfs_mkdir_impl;
|
||||
root->node.create = ramfs_create_impl;
|
||||
|
||||
// Seed default file system structure
|
||||
vfs_node_t* etc = ramfs_add_dir(&root->node, "etc");
|
||||
ramfs_add_dir(&root->node, "bin");
|
||||
ramfs_add_dir(&root->node, "dev");
|
||||
ramfs_add_dir(&root->node, "proc");
|
||||
ramfs_add_dir(&root->node, "home");
|
||||
ramfs_add_dir(&root->node, "tmp");
|
||||
|
||||
if (etc) {
|
||||
ramfs_add_file(etc, "hostname", "sub-os\n", 7);
|
||||
ramfs_add_file(etc, "os-release", "NAME=\"SUB-OS\"\nVERSION=\"0.2.0-lts\"\nARCH=\"x86_64\"\n", 48);
|
||||
ramfs_add_file(etc, "resolv.conf", "nameserver 10.0.2.3\nsearch localdomain\n", 39);
|
||||
ramfs_add_file(etc, "motd", "====================================================\n Welcome to SUB-OS Modular Monolithic Linux Core!\n====================================================\n", 137);
|
||||
}
|
||||
|
||||
const char* readme = "SUB-OS Production-Level Modular Operating System\nArchitecture: x86_64 Long Mode\nSubsystems: PMM, Heap, VFS, PCI, E1000, Net, Crypto, LazyBox\n";
|
||||
ramfs_add_file(&root->node, "readme.txt", readme, strlen(readme));
|
||||
|
||||
return &root->node;
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
#include <fs/vfs.h>
|
||||
#include <fs/ramfs.h>
|
||||
#include <fs/devfs.h>
|
||||
#include <fs/procfs.h>
|
||||
#include <mm/kmalloc.h>
|
||||
#include <lib/string.h>
|
||||
#include <kernel/printk.h>
|
||||
|
||||
#define MAX_OPEN_FILES 64
|
||||
|
||||
static vfs_node_t* vfs_root = NULL;
|
||||
static file_descriptor_t file_descriptors[MAX_OPEN_FILES];
|
||||
|
||||
void vfs_init(void) {
|
||||
memset(file_descriptors, 0, sizeof(file_descriptors));
|
||||
|
||||
// 1. Create root RAM filesystem
|
||||
vfs_root = ramfs_create_root();
|
||||
|
||||
// 2. Initialize and mount /dev
|
||||
devfs_init();
|
||||
vfs_mount("/dev", devfs_get_root());
|
||||
|
||||
// 3. Initialize and mount /proc
|
||||
procfs_init();
|
||||
vfs_mount("/proc", procfs_get_root());
|
||||
|
||||
printk(KERN_INFO "VFS: Mounted root ramfs, /dev synthetic devfs, and /proc procfs\n");
|
||||
}
|
||||
|
||||
vfs_node_t* vfs_get_root(void) {
|
||||
return vfs_root;
|
||||
}
|
||||
|
||||
vfs_node_t* vfs_namei(const char* path) {
|
||||
if (!path || !vfs_root) return NULL;
|
||||
if (strcmp(path, "/") == 0) return vfs_root;
|
||||
|
||||
if (*path == '/') path++; // Skip leading slash
|
||||
|
||||
char buffer[256];
|
||||
strncpy(buffer, path, sizeof(buffer) - 1);
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
|
||||
vfs_node_t* current = vfs_root;
|
||||
char* token = buffer;
|
||||
|
||||
while (*token) {
|
||||
char* next_slash = strchr(token, '/');
|
||||
if (next_slash) {
|
||||
*next_slash = '\0';
|
||||
}
|
||||
|
||||
if (current->finddir) {
|
||||
current = current->finddir(current, token);
|
||||
if (!current) return NULL;
|
||||
|
||||
// Follow mountpoints
|
||||
if (current->ptr && (current->flags & FS_MOUNTPOINT)) {
|
||||
current = current->ptr;
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (next_slash) {
|
||||
token = next_slash + 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
int vfs_open(const char* path, uint32_t flags) {
|
||||
vfs_node_t* node = vfs_namei(path);
|
||||
if (!node) {
|
||||
if (flags & O_CREAT) {
|
||||
// Find parent and create
|
||||
char parent_path[256];
|
||||
strncpy(parent_path, path, sizeof(parent_path) - 1);
|
||||
char* last_slash = strrchr(parent_path, '/');
|
||||
if (last_slash) {
|
||||
*last_slash = '\0';
|
||||
const char* filename = last_slash + 1;
|
||||
vfs_node_t* parent = vfs_namei(parent_path[0] ? parent_path : "/");
|
||||
if (parent && parent->create) {
|
||||
parent->create(parent, filename, 0644);
|
||||
node = vfs_namei(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!node) return -1;
|
||||
}
|
||||
|
||||
if (node->open) {
|
||||
if (node->open(node, flags) != 0) return -1;
|
||||
}
|
||||
|
||||
// Find free file descriptor
|
||||
for (int fd = 3; fd < MAX_OPEN_FILES; fd++) {
|
||||
if (!file_descriptors[fd].node) {
|
||||
file_descriptors[fd].node = node;
|
||||
file_descriptors[fd].offset = 0;
|
||||
file_descriptors[fd].flags = flags;
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
|
||||
return -1; // Out of file descriptors
|
||||
}
|
||||
|
||||
ssize_t vfs_read(int fd, void* buffer, size_t size) {
|
||||
if (fd < 0 || fd >= MAX_OPEN_FILES || !file_descriptors[fd].node) return -1;
|
||||
|
||||
file_descriptor_t* desc = &file_descriptors[fd];
|
||||
if (desc->node->read) {
|
||||
ssize_t bytes_read = desc->node->read(desc->node, desc->offset, size, (uint8_t*)buffer);
|
||||
if (bytes_read > 0) {
|
||||
desc->offset += bytes_read;
|
||||
}
|
||||
return bytes_read;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t vfs_write(int fd, const void* buffer, size_t size) {
|
||||
if (fd < 0 || fd >= MAX_OPEN_FILES || !file_descriptors[fd].node) return -1;
|
||||
|
||||
file_descriptor_t* desc = &file_descriptors[fd];
|
||||
if (desc->node->write) {
|
||||
ssize_t bytes_written = desc->node->write(desc->node, desc->offset, size, (const uint8_t*)buffer);
|
||||
if (bytes_written > 0) {
|
||||
desc->offset += bytes_written;
|
||||
}
|
||||
return bytes_written;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
off_t vfs_lseek(int fd, off_t offset, int whence) {
|
||||
if (fd < 0 || fd >= MAX_OPEN_FILES || !file_descriptors[fd].node) return -1;
|
||||
|
||||
file_descriptor_t* desc = &file_descriptors[fd];
|
||||
if (whence == SEEK_SET) desc->offset = offset;
|
||||
else if (whence == SEEK_CUR) desc->offset += offset;
|
||||
else if (whence == SEEK_END) desc->offset = desc->node->length + offset;
|
||||
return desc->offset;
|
||||
}
|
||||
|
||||
int vfs_close(int fd) {
|
||||
if (fd < 0 || fd >= MAX_OPEN_FILES || !file_descriptors[fd].node) return -1;
|
||||
|
||||
if (file_descriptors[fd].node->close) {
|
||||
file_descriptors[fd].node->close(file_descriptors[fd].node);
|
||||
}
|
||||
file_descriptors[fd].node = NULL;
|
||||
file_descriptors[fd].offset = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vfs_mkdir(const char* path, mode_t mode) {
|
||||
if (!path || !*path) return -1;
|
||||
char parent_path[256];
|
||||
strncpy(parent_path, path, sizeof(parent_path) - 1);
|
||||
parent_path[sizeof(parent_path) - 1] = '\0';
|
||||
|
||||
char* last_slash = strrchr(parent_path, '/');
|
||||
const char* dirname = path;
|
||||
vfs_node_t* parent = vfs_get_root();
|
||||
|
||||
if (last_slash) {
|
||||
if (last_slash == parent_path) {
|
||||
parent = vfs_namei("/");
|
||||
dirname = last_slash + 1;
|
||||
} else {
|
||||
*last_slash = '\0';
|
||||
dirname = last_slash + 1;
|
||||
parent = vfs_namei(parent_path);
|
||||
}
|
||||
}
|
||||
|
||||
if (parent && parent->mkdir) {
|
||||
return parent->mkdir(parent, dirname, mode);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int vfs_create(const char* path, mode_t mode) {
|
||||
if (!path || !*path) return -1;
|
||||
char parent_path[256];
|
||||
strncpy(parent_path, path, sizeof(parent_path) - 1);
|
||||
parent_path[sizeof(parent_path) - 1] = '\0';
|
||||
|
||||
char* last_slash = strrchr(parent_path, '/');
|
||||
const char* filename = path;
|
||||
vfs_node_t* parent = vfs_get_root();
|
||||
|
||||
if (last_slash) {
|
||||
if (last_slash == parent_path) {
|
||||
parent = vfs_namei("/");
|
||||
filename = last_slash + 1;
|
||||
} else {
|
||||
*last_slash = '\0';
|
||||
filename = last_slash + 1;
|
||||
parent = vfs_namei(parent_path);
|
||||
}
|
||||
}
|
||||
|
||||
if (parent && parent->create) {
|
||||
return parent->create(parent, filename, mode);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int vfs_mount(const char* path, vfs_node_t* fs_root) {
|
||||
if (!path || !fs_root) return -1;
|
||||
vfs_node_t* mount_node = vfs_namei(path);
|
||||
if (!mount_node) {
|
||||
// Create directory node for mount point
|
||||
char parent_path[256];
|
||||
strncpy(parent_path, path, sizeof(parent_path) - 1);
|
||||
char* last_slash = strrchr(parent_path, '/');
|
||||
if (last_slash) {
|
||||
*last_slash = '\0';
|
||||
const char* dirname = last_slash + 1;
|
||||
vfs_node_t* parent = vfs_namei(parent_path[0] ? parent_path : "/");
|
||||
if (parent && parent->mkdir) {
|
||||
parent->mkdir(parent, dirname, 0755);
|
||||
mount_node = vfs_namei(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mount_node) {
|
||||
mount_node->flags |= FS_MOUNTPOINT;
|
||||
mount_node->ptr = fs_root;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
Reference in new issue
Block a user