feature (kernel): Started work on a node based Virtual File System
This commit is contained in:
parent
13e1a15232
commit
0be2a54467
|
@ -0,0 +1,65 @@
|
||||||
|
/* Copyright (C) Antifallobst <antifallobst@systemausfall.org>
|
||||||
|
*
|
||||||
|
* NoxOS is free software:
|
||||||
|
* you can redistribute it and/or modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program.
|
||||||
|
* If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NOX_VFS_H
|
||||||
|
#define NOX_VFS_H
|
||||||
|
|
||||||
|
#include "utils/stdtypes.h"
|
||||||
|
#include "utils/string.h"
|
||||||
|
#include "boot/boot_info.h"
|
||||||
|
|
||||||
|
#define VFS_MAX_NAME_LENGTH 128
|
||||||
|
|
||||||
|
typedef struct vfs_node_T vfs_node_T;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
VFS_NODE_DIRECTORY,
|
||||||
|
VFS_NODE_FILE,
|
||||||
|
VFS_NODE_MOUNT,
|
||||||
|
VFS_NODE_BLOCK_DEVICE,
|
||||||
|
|
||||||
|
VFS_NODE_ENUM_END
|
||||||
|
} vfs_node_type_E;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void* buffer;
|
||||||
|
uint64_t buffer_size;
|
||||||
|
bool reclaimable;
|
||||||
|
vfs_node_T* node;
|
||||||
|
} vfs_node_cache_T;
|
||||||
|
|
||||||
|
struct vfs_node_T{
|
||||||
|
char name[VFS_MAX_NAME_LENGTH];
|
||||||
|
vfs_node_type_E type;
|
||||||
|
vfs_node_cache_T* cache;
|
||||||
|
|
||||||
|
vfs_node_T* prev;
|
||||||
|
vfs_node_T* next;
|
||||||
|
vfs_node_T* parent;
|
||||||
|
vfs_node_T* childs;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern vfs_node_T* g_vfs_root_node;
|
||||||
|
|
||||||
|
vfs_node_T* vfs_node_create (vfs_node_T* parent, string_t name, vfs_node_type_E type);
|
||||||
|
vfs_node_T* vfs_node_destruct (vfs_node_T* node);
|
||||||
|
void vfs_node_dump_info (vfs_node_T* node, uint64_t indent);
|
||||||
|
vfs_node_T* vfs_node_resolve_child (vfs_node_T* node, string_t child_name);
|
||||||
|
|
||||||
|
void vfs_init (boot_info_T* boot_info);
|
||||||
|
vfs_node_T* vfs_resolve_path (string_t path);
|
||||||
|
void vfs_unpack_archive_ustar ();
|
||||||
|
|
||||||
|
#endif //NOX_VFS_H
|
|
@ -0,0 +1,145 @@
|
||||||
|
/* Copyright (C) Antifallobst <antifallobst@systemausfall.org>
|
||||||
|
*
|
||||||
|
* NoxOS is free software:
|
||||||
|
* you can redistribute it and/or modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation, either version 3 of the License,
|
||||||
|
* or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program.
|
||||||
|
* If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "drivers/fs/vfs.h"
|
||||||
|
#include "utils/memory.h"
|
||||||
|
#include "utils/logger.h"
|
||||||
|
|
||||||
|
vfs_node_T* g_vfs_root_node;
|
||||||
|
|
||||||
|
void vfs_node_bring_to_parent_start(vfs_node_T* node) {
|
||||||
|
if (node->parent == NULL) { return; }
|
||||||
|
|
||||||
|
if (node->parent->childs == node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->parent->childs == NULL) {
|
||||||
|
node->parent->childs = node;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->prev != NULL) {
|
||||||
|
node->prev->next = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->next != NULL) {
|
||||||
|
node->next->prev = node->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->parent->childs->prev = node;
|
||||||
|
node->next = node->parent->childs;
|
||||||
|
node->parent->childs = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfs_node_T* vfs_node_create(vfs_node_T* parent, string_t name, vfs_node_type_E type) {
|
||||||
|
vfs_node_T* node = memory_allocate(sizeof(vfs_node_T));
|
||||||
|
|
||||||
|
uint64_t strlen = string_length(name);
|
||||||
|
if (strlen >= VFS_MAX_NAME_LENGTH) {
|
||||||
|
log(LOG_WARNING, "<VFS> name '%s' is too long, shrinking to '%.*s'", name, VFS_MAX_NAME_LENGTH-1, name);
|
||||||
|
}
|
||||||
|
memory_copy((void*)name, node->name, VFS_MAX_NAME_LENGTH-1); node->name[VFS_MAX_NAME_LENGTH-1] = '\0';
|
||||||
|
|
||||||
|
node->parent = parent;
|
||||||
|
node->type = type;
|
||||||
|
node->cache = NULL;
|
||||||
|
node->childs = NULL;
|
||||||
|
node->prev = NULL;
|
||||||
|
node->next = NULL;
|
||||||
|
|
||||||
|
vfs_node_bring_to_parent_start(node);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vfs_node_dump_info(vfs_node_T* node, uint64_t indent) {
|
||||||
|
char buf[indent+1];
|
||||||
|
memory_set(buf, ' ', indent);
|
||||||
|
buf[indent] = '\0';
|
||||||
|
|
||||||
|
switch (node->type) {
|
||||||
|
case VFS_NODE_DIRECTORY: {
|
||||||
|
log(LOG_NONE, "%s[dir] %s", buf, node->name);
|
||||||
|
vfs_node_T* child = node->childs;
|
||||||
|
while (child != NULL) {
|
||||||
|
vfs_node_dump_info(child, indent+2);
|
||||||
|
child = child->next;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VFS_NODE_FILE: {
|
||||||
|
log(LOG_NONE, "%s[file] %s", buf, node->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vfs_node_T* vfs_node_destruct(vfs_node_T* node) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vfs_node_T* vfs_node_resolve_child(vfs_node_T* node, string_t child_name) {
|
||||||
|
vfs_node_T* child = node->childs;
|
||||||
|
while (child != NULL) {
|
||||||
|
if (!string_compare(child_name, child->name)) {
|
||||||
|
child = child->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfs_node_bring_to_parent_start(child);
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vfs_init(boot_info_T* boot_info) {
|
||||||
|
g_vfs_root_node = vfs_node_create(NULL, "root", VFS_NODE_DIRECTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
vfs_node_T* vfs_resolve_path(string_t path) {
|
||||||
|
if (*path != '/') {
|
||||||
|
log(LOG_WARNING, "<VFS> failed to resolve node from invalid path '%s' (no root prefix)");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t length;
|
||||||
|
vfs_node_T* node = g_vfs_root_node;
|
||||||
|
|
||||||
|
do {
|
||||||
|
path++;
|
||||||
|
length = string_find_next(path, '/');
|
||||||
|
|
||||||
|
char name[length];
|
||||||
|
memory_copy((void*)path, name, length);
|
||||||
|
name[length] = '\0';
|
||||||
|
|
||||||
|
node = vfs_node_resolve_child(node, name);
|
||||||
|
if (node == NULL) {
|
||||||
|
log(LOG_WARNING, "<VFS> failed to resolve node from invalid path '%s' (node child resolve null)");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
path += length;
|
||||||
|
} while(*path != '\0');
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vfs_unpack_archive_ustar() {
|
||||||
|
|
||||||
|
}
|
|
@ -22,6 +22,7 @@
|
||||||
#include "mm/page_map.h"
|
#include "mm/page_map.h"
|
||||||
#include "drivers/time/pit.h"
|
#include "drivers/time/pit.h"
|
||||||
#include "drivers/graphics/renderer.h"
|
#include "drivers/graphics/renderer.h"
|
||||||
|
#include "drivers/fs/vfs.h"
|
||||||
#include "proc/scheduler.h"
|
#include "proc/scheduler.h"
|
||||||
|
|
||||||
#include "utils/io.h"
|
#include "utils/io.h"
|
||||||
|
@ -60,6 +61,11 @@ void kernel_init(boot_info_T* boot_info) {
|
||||||
graphics_renderer_init(boot_info);
|
graphics_renderer_init(boot_info);
|
||||||
graphical_log_init();
|
graphical_log_init();
|
||||||
limine_terminal_print(boot_info, " ok\n");
|
limine_terminal_print(boot_info, " ok\n");
|
||||||
|
|
||||||
|
limine_terminal_print(boot_info, " Initializing virtual file system...");
|
||||||
|
vfs_init(boot_info);
|
||||||
|
limine_terminal_print(boot_info, " ok\n");
|
||||||
|
|
||||||
limine_terminal_print(boot_info, " Initializing scheduler...");
|
limine_terminal_print(boot_info, " Initializing scheduler...");
|
||||||
scheduler_init();
|
scheduler_init();
|
||||||
limine_terminal_print(boot_info, " ok\n");
|
limine_terminal_print(boot_info, " ok\n");
|
||||||
|
@ -75,11 +81,19 @@ void kmain(boot_info_T boot_info) {
|
||||||
limine_terminal_print(&boot_info, "Kernel initialized\n");
|
limine_terminal_print(&boot_info, "Kernel initialized\n");
|
||||||
log(LOG_INFO, "!=====[ Kernel Initialized ]=====!\n");
|
log(LOG_INFO, "!=====[ Kernel Initialized ]=====!\n");
|
||||||
|
|
||||||
log(LOG_NONE, "test none");
|
vfs_node_T* node_temp = vfs_node_create(g_vfs_root_node, "temp", VFS_NODE_DIRECTORY);
|
||||||
log(LOG_INFO, "test info");
|
vfs_node_T* node_system = vfs_node_create(g_vfs_root_node, "system", VFS_NODE_DIRECTORY);
|
||||||
log(LOG_DEBUG, "test debug");
|
vfs_node_T* node_config = vfs_node_create(node_system, "config", VFS_NODE_DIRECTORY);
|
||||||
log(LOG_WARNING, "test warning");
|
vfs_node_T* node_test = vfs_node_create(node_config, "test.conf", VFS_NODE_FILE);
|
||||||
log(LOG_ERROR, "test error");
|
|
||||||
|
vfs_node_T* result = vfs_resolve_path("/system/config/test.conf");
|
||||||
|
if (result == node_test) {
|
||||||
|
log(LOG_DEBUG, "resolve test passed");
|
||||||
|
} else {
|
||||||
|
log(LOG_DEBUG, "resolve test failed 0x%x != 0x%x", result, node_test);
|
||||||
|
}
|
||||||
|
|
||||||
|
vfs_node_dump_info(g_vfs_root_node, 0);
|
||||||
|
|
||||||
CORE_HALT_FOREVER
|
CORE_HALT_FOREVER
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue