nshell/src/vfs/vfs.c

147 lines
3.9 KiB
C

#include "vfs.h"
#include <stdlib.h>
#include <string.h>
#include <gint/bfile.h>
#include <gint/cpu.h>
#include <gint/drivers.h>
#include <gint/keyboard.h>
#include <gint/kmalloc.h>
#include <printf.h>
#include "../term.h"
extern void _name_to_str(char *dest, const uint16_t *source, int n);
extern void _str_to_name(uint16_t *dest, const char *source, int n);
extern int _find_first(const uint16_t *pathname, int *FindHandle, const uint16_t *foundfile, struct BFile_FileInfo *fileinfo);
extern int _find_next(int FindHandle, const uint16_t *foundfile, struct BFile_FileInfo *fileinfo);
static vfs_entry_t vfs_root;
static vfs_entry_t *vfs_new_dir(const char *name, vfs_entry_t *parent) {
vfs_entry_t *newdir = kmalloc(sizeof(vfs_entry_t), NULL);
strcpy((char *)&newdir->name, name);
newdir->parent = parent;
newdir->type = vfs_dir;
newdir->driver = 0;
newdir->childs = NULL;
newdir->next = NULL;
newdir->next = parent->childs;
parent->childs = newdir;
return newdir;
}
static vfs_entry_t *vfs_new_file(const char *name, vfs_entry_t *parent) {
vfs_entry_t *newfile = kmalloc(sizeof(vfs_entry_t), NULL);
strcpy((char *)&newfile->name, name);
newfile->parent = parent;
newfile->type = vfs_file;
newfile->driver = 0;
newfile->childs = NULL;
newfile->next = NULL;
newfile->next = parent->childs;
parent->childs = newfile;
return newfile;
}
static void vfs_debug_tree_(int indent, vfs_entry_t *subtree) {
vfs_entry_t *child = subtree->childs;
while (child != NULL) {
for (int i = 0; i < indent; i++)
term_print(" ");
if (child->type == vfs_file)
term_printf("%s\n", child->name);
else if (child->type == vfs_dir) {
term_printf("%s/\n", child->name);
vfs_debug_tree_(indent + 1, child);
}
child = child->next;
}
}
static void vfs_debug_tree(void) {
term_print("/\n");
vfs_debug_tree_(1, &vfs_root);
}
static int shandle;
static void populate_vfs(const char *path, vfs_entry_t *dir) {
char glob[64];
strcpy(glob, path);
strcat(glob, "\\*");
uint16_t glob_c16[64];
_str_to_name(glob_c16, glob, 64);
uint16_t foundfile[64];
struct BFile_FileInfo fileinfo;
int ret = _find_first(glob_c16, &shandle, foundfile, &fileinfo);
while (ret == 0) {
char foundfile_str[64];
_name_to_str(foundfile_str, foundfile, 64);
if (foundfile_str[0] != '@' && strcmp(foundfile_str, ".") != 0 && strcmp(foundfile_str, "..") != 0) {
if (fileinfo.type == BFile_Type_Directory) {
vfs_new_dir(foundfile_str, dir);
} else {
vfs_new_file(foundfile_str, dir);
}
}
ret = _find_next(shandle, foundfile, &fileinfo);
}
BFile_FindClose(shandle);
// we do the recursive search when the search handle
// has been closed to avoid using too much handles
vfs_entry_t *child = dir->childs;
while (child != NULL) {
if (child->type == vfs_dir) {
char new_path[64];
sprintf(new_path, "%s\\%s", path, child->name);
populate_vfs(new_path, child);
}
child = child->next;
}
}
void vfs_init(void) {
// init fs root
strcpy((char *)&vfs_root.name, "");
vfs_root.parent = NULL;
vfs_root.type = vfs_dir;
vfs_root.driver = 0;
vfs_root.childs = NULL;
vfs_root.next = NULL;
vfs_entry_t *native = vfs_new_dir("native", &vfs_root);
vfs_entry_t *flash = vfs_new_dir("flash", native);
cpu_atomic_start();
// gint_world_switch_in(gint_world_addin, gint_world_os);
populate_vfs("\\\\fls0", flash);
// gint_world_switch_in(gint_world_os, gint_world_addin);
cpu_atomic_end();
vfs_debug_tree();
}
// const vfs_entry_t *vfs_get_root(void) { return &vfs_root; }
// vfs_entry* find_entry(const char* path) {
// // TODO
// }