still working on a more robust vfs
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
#include <drivers/cpio/cpio.h>
|
||||
|
||||
#include <lib/memory.h>
|
||||
#include <lib/string.h>
|
||||
|
||||
#define MAX_INITRD_FILES 64
|
||||
static vfs_node_t cpio_nodes[MAX_INITRD_FILES];
|
||||
static uint32_t cpio_node_count = 0;
|
||||
|
||||
static uint32_t parse_hex_ascii(const char *str, int len) {
|
||||
uint32_t result = 0;
|
||||
@@ -20,13 +19,15 @@ static uint32_t parse_hex_ascii(const char *str, int len) {
|
||||
static vfs_node_t* cpio_find(vfs_node_t* _dir, const char* name) {
|
||||
if (!(_dir->flags & VFS_DIRECTORY)) return NULL;
|
||||
|
||||
for (uint32_t i = 0; i < cpio_node_count; i++) {
|
||||
if (strcmp(cpio_nodes[i].name, name) == 0) {
|
||||
return &cpio_nodes[i];
|
||||
vfs_node_t* child = _dir->first_child;
|
||||
while (child != NULL) {
|
||||
if (strcmp(child->name, name) == 0) {
|
||||
return child;
|
||||
}
|
||||
child = child->next_sibling;
|
||||
}
|
||||
|
||||
return NULL; // File not found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint32_t cpio_read(struct vfs_node* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
|
||||
@@ -38,18 +39,47 @@ static uint32_t cpio_read(struct vfs_node* node, uint32_t offset, uint32_t size,
|
||||
return size;
|
||||
}
|
||||
|
||||
static vfs_node_t* cpio_get_or_create(vfs_node_t* root_node, const char* path) {
|
||||
vfs_node_t* current = root_node;
|
||||
|
||||
char path_cpy[256];
|
||||
strcpy(path_cpy, path);
|
||||
|
||||
char* sav = NULL;
|
||||
char* tkn = strtok_r(path_cpy, "/", &sav);
|
||||
|
||||
while (tkn != NULL) {
|
||||
char* next_tkn = strtok_r(NULL, "/", &sav);
|
||||
|
||||
vfs_node_t* next_node = cpio_find(current, tkn);
|
||||
if (!next_node) {
|
||||
next_node = kalloc(sizeof(vfs_node_t));
|
||||
memset((void*)next_node, 0, sizeof(vfs_node_t));
|
||||
|
||||
strcpy(next_node->name, tkn);
|
||||
next_node->flags = VFS_DIRECTORY;
|
||||
next_node->find = cpio_find;
|
||||
|
||||
next_node->next_sibling = current->first_child;
|
||||
current->first_child = next_node;
|
||||
}
|
||||
|
||||
current = next_node;
|
||||
tkn = next_tkn;
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
vfs_node_t* cpio_read_fs(uint32_t _vaddr) {
|
||||
cpio_header_t* header = (cpio_header_t*)_vaddr;
|
||||
|
||||
vfs_node_t* cpio_root = kalloc(sizeof(vfs_node_t));
|
||||
memset((uint8_t*)cpio_root, 0, sizeof(vfs_node_t));
|
||||
|
||||
strcpy(cpio_root->name, "cpio_root");
|
||||
cpio_root->flags = VFS_DIRECTORY;
|
||||
cpio_root->find = cpio_find;
|
||||
|
||||
cpio_root->flags |= VFS_DIRECTORY;
|
||||
cpio_root->finddir = cpio_find;
|
||||
|
||||
uint32_t cnt = 0;
|
||||
while (1) {
|
||||
if (strncmp(header->c_magic, "070701", 6) != 0 &&
|
||||
strncmp(header->c_magic, "070702", 6) != 0) {
|
||||
@@ -59,34 +89,50 @@ vfs_node_t* cpio_read_fs(uint32_t _vaddr) {
|
||||
uint32_t namesize = parse_hex_ascii(header->c_namesize, 8);
|
||||
uint32_t filesize = parse_hex_ascii(header->c_filesize, 8);
|
||||
uint32_t mode = parse_hex_ascii(header->c_mode, 8);
|
||||
|
||||
char* filename = (char*)header + sizeof(cpio_header_t);
|
||||
char* filename = (char*)header + sizeof(cpio_header_t);
|
||||
|
||||
if (strcmp(filename, "TRAILER!!!") == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t file_data_offset = sizeof(cpio_header_t) + namesize;
|
||||
file_data_offset = (file_data_offset + 3) & ~3; // align to 4 bytes
|
||||
|
||||
uint32_t file_data_offset = (sizeof(cpio_header_t) + namesize + 3) & ~3;
|
||||
uint8_t* file_data = (uint8_t*)header + file_data_offset;
|
||||
|
||||
if (strcmp(".", filename) != 0 && cnt < MAX_INITRD_FILES) {
|
||||
vfs_node_t* current = &cpio_nodes[cpio_node_count++];
|
||||
memset((uint8_t*)current, 0, sizeof(vfs_node_t));
|
||||
if (strcmp(".", filename) != 0) {
|
||||
vfs_node_t* parent = cpio_get_or_create(cpio_root, filename);
|
||||
|
||||
strcpy(current->name, filename);
|
||||
current->size = filesize;
|
||||
char* base_name = filename;
|
||||
for (int i = strlen(filename) - 1; i >= 0; i--) {
|
||||
if (filename[i] == '/') {
|
||||
base_name = &filename[i + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
current->flags = VFS_FILE;
|
||||
current->read = cpio_read;
|
||||
current->data = file_data;
|
||||
vfs_node_t* current = cpio_find(parent, base_name);
|
||||
if (!current) {
|
||||
current = kalloc(sizeof(vfs_node_t));
|
||||
memset((void*)current, 0, sizeof(vfs_node_t));
|
||||
strcpy(current->name, base_name);
|
||||
|
||||
current->next_sibling = parent->first_child;
|
||||
parent->first_child = current;
|
||||
}
|
||||
|
||||
if ((mode & 0xF000) == 0x4000) {
|
||||
current->flags = VFS_DIRECTORY;
|
||||
current->find = cpio_find;
|
||||
} else {
|
||||
current->flags = VFS_FILE;
|
||||
current->size = filesize;
|
||||
current->data = file_data;
|
||||
current->read = cpio_read;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t next_header_offset = file_data_offset + filesize;
|
||||
next_header_offset = (next_header_offset + 3) & ~3;
|
||||
uint32_t next_header_offset = (file_data_offset + filesize + 3) & ~3;
|
||||
header = (cpio_header_t*)((uint8_t*)header + next_header_offset);
|
||||
}
|
||||
|
||||
|
||||
return cpio_root;
|
||||
}
|
||||
Reference in New Issue
Block a user