diff --git a/src/Makefile b/src/Makefile index 2aba4b15..da34c1af 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,5 @@ objects := $(patsubst %.c,%.o,$(wildcard *.c)) -subdirs := arch/$(TARGET)/ include video sys +subdirs := arch/$(TARGET)/ include video sys fs OBJPATH=$(OBJDIR) export diff --git a/src/arch/x86_64/main.c b/src/arch/x86_64/main.c index baac279a..14d7825d 100644 --- a/src/arch/x86_64/main.c +++ b/src/arch/x86_64/main.c @@ -7,6 +7,7 @@ #include #include #include +#include static volatile struct limine_terminal_request liminettyr = { .id = LIMINE_TERMINAL_REQUEST, @@ -47,6 +48,8 @@ void kmain(){ alloc_init(); + vfs_init(); + _panic("End of kmain()", 0); } diff --git a/src/fs/Makefile b/src/fs/Makefile new file mode 100644 index 00000000..e17c7167 --- /dev/null +++ b/src/fs/Makefile @@ -0,0 +1,12 @@ +objects := $(patsubst %.c,%.o,$(wildcard *.c)) +subdirs := +OBJPATH=$(OBJDIR)/fs +export + +all: $(subdirs) $(objects) + for subdir in $(subdirs) ; do $(MAKE) -C $${subdir} ; done + +%.o: %.c + $(CC) $(CFLAGS) -o $@ $< + mkdir -p $(OBJPATH) + cp $@ $(OBJPATH)/$@ diff --git a/src/fs/vfs.c b/src/fs/vfs.c new file mode 100644 index 00000000..bef8a939 --- /dev/null +++ b/src/fs/vfs.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include + +dirnode_t* vfsroot; + +vnode_t* vfs_newnode(fs_t* fs, void* fsdata){ + vnode_t* node = alloc(sizeof(vnode_t)); + if(!node) return NULL; + node->fs = fs; + node->fsdata = fsdata; + + return node; +} + + +dirnode_t* vfs_newdirnode(fs_t* fs, void* fsdata){ + + dirnode_t* node = alloc(sizeof(dirnode_t)); + if(!node) return NULL; + vnode_t* vnode = (vnode_t*)node; + + if(!hashtable_init(&node->children, 10)){ // add more here later + free(node); + return NULL; + } + + vnode->st.st_mode = MAKETYPE(TYPE_DIR); + vnode->fs = fs; + vnode->fsdata = fsdata; +} + +int vfs_resolvepath(vnode_t** result, dirnode_t* ref, char *path){ + + dirnode_t* iterator = ref; + char name[512]; + off_t nameoffset = 0; + + while(nameoffset <= strlen(path)){ + + size_t offset = 0; + + while(path[nameoffset]) + name[offset++] = path[nameoffset++]; + + name[offset] = 0; + + // make sure we're a directory + + if(!GETTYPE(iterator->vnode.st.st_mode) == TYPE_DIR) + return ENOTDIR; + + // find correct node if mountmoint + + while(iterator->mountednode) + iterator = iterator->mountednode; + + vnode_t* child = hashtable_get(&iterator->children, name); + + if(!child){ + // open it + int status = iterator->vnode.fs->calls->open(iterator, name); + if(status) + return status; + + child = hashtable_get(&iterator->children, name); + + } + + iterator = (dirnode_t*)child; + + } + + *result = (vnode_t*)iterator; + + return 0; + +} + +void vfs_destroynode(vnode_t* node){ + + if(GETTYPE(node->st.st_mode) == TYPE_DIR) + hashtable_destroy(&((dirnode_t*)node)->children); + + free(node); + +} + +dirnode_t* vfs_root(){ + return vfsroot; +} + +void vfs_acquirenode(vnode_t* node){ + while(node){ + ++node->refcount; + node = (vnode_t*)node->parent; + } +} + +void vfs_releasenode(vnode_t* node){ + while(node){ + --node->refcount; + node = (vnode_t*)node->parent; + } +} + +void vfs_init(){ + printf("Creating a fake root for the VFS\n"); + + vfsroot = vfs_newdirnode(NULL, NULL); +} diff --git a/src/include/errno.h b/src/include/errno.h new file mode 100644 index 00000000..b10d1df7 --- /dev/null +++ b/src/include/errno.h @@ -0,0 +1,6 @@ +#ifndef _ERRNO_H_INCLUDE +#define _ERRNO_H_INCLUDE + +#define ENOTDIR 1 + +#endif diff --git a/src/include/kernel/vfs.h b/src/include/kernel/vfs.h new file mode 100644 index 00000000..20145340 --- /dev/null +++ b/src/include/kernel/vfs.h @@ -0,0 +1,74 @@ +#ifndef _VFS_H_INCLUDE +#define _VFS_H_INCLUDE + +#include +#include +#include + +struct _vnode_t; +struct _fscalls_t; +struct _dirnode_t; + +typedef struct { + struct _dirnode_t* rootvnode; + struct _fscalls_t* calls; + void* data; +} fs_t; + + +typedef struct _vnode_t { + stat st; + fs_t* fs; + void* fsdata; + size_t refcount; + struct _dirnode_t* parent; +} vnode_t; + +// folders are an expansion of vnode_t to save memory + +typedef struct _dirnode_t{ + vnode_t vnode; + struct _dirnode_t* mountednode; + hashtable children; +} dirnode_t; + +// fs specific calls called by the vfs on filesystems + +typedef struct _fscalls_t { + // prepares the filesystem using a filesystem data pointer and returns the root node + dirnode_t* (*mount)(void*); + // cleanup of the filesystem + int (*umount)(); + // opens a file under a dirnode + // args: parent, name + int (*open)(dirnode_t*, char*); + // cleans up a vfsnode + // args: the node to clean + int (*close)(vnode_t*); + // creates a new directory with the right mode + // args: parent, name, mode + int (*mkdir)(dirnode_t* parent, char* name, mode_t mode); + // create a new file + // args: parent, name, mode + int (*create)(dirnode_t* parent, char* name, mode_t mode); +} fscalls_t; + + +int vfs_mount(dirnode_t* ref, char* device, char* mountpoint, char* fs); +int vfs_umount(dirnode_t* ref, char* mountpoint); +int vfs_open(vnode_t* buf, dirnode_t* ref, char* path, int flags, mode_t mode); +int vfs_close(vnode_t* node); +int vfs_mkdir(dirnode_t* ref, char* path, mode_t mode); +int vfs_create(dirnode_t* ref, char* path, mode_t mode); + + +void vfs_init(); +dirnode_t* vfs_root(); +void vfs_acquirenode(vnode_t* node); +void vfs_releasenode(vnode_t* node); +vnode_t* vfs_newnode(fs_t* fs, void* fsdata); +dirnode_t* vfs_newdirnode(fs_t* fs, void* fsdata); +void vfs_destroynode(vnode_t* node); +int vfs_resolvepath(vnode_t** result, dirnode_t* ref, char* path); + +#endif diff --git a/src/include/sys/stat.h b/src/include/sys/stat.h new file mode 100644 index 00000000..d4d50179 --- /dev/null +++ b/src/include/sys/stat.h @@ -0,0 +1,32 @@ +#ifndef _STAT_H_INCLUDE +#define _STAT_H_INCLUDE + +#include + +#define TYPE_FIFO 1 +#define TYPE_CHARDEV 2 +#define TYPE_DIR 4 +#define TYPE_BLOCKDEV 6 +#define TYPE_REGULAR 8 +#define TYPE_IFLNK 10 +#define TYPE_IFSOCK 12 + +#define GETMODE(m) (0xFFF & m) +#define GETTYPE(m) ((m >> 12) & 0xF) +#define MAKETYPE(m) ((m & 0xF) << 12) + +typedef struct { + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + off_t st_size; + + blksize_t st_blksize; + blkcnt_t st_blocks; +} stat; + +#endif diff --git a/src/include/sys/types.h b/src/include/sys/types.h new file mode 100644 index 00000000..2ce3202e --- /dev/null +++ b/src/include/sys/types.h @@ -0,0 +1,22 @@ +#ifndef _TYPES_H_INCLUDE +#define _TYPES_H_INCLUDE + +#include + +typedef signed long ssize_t; + +typedef size_t blkcnt_t; +typedef size_t blksize_t; +typedef int id_t; +typedef id_t dev_t; +typedef id_t gid_t; +typedef id_t pid_t; +typedef id_t uid_t; +typedef id_t tid_t; +typedef size_t ino_t; +typedef size_t mode_t; +typedef int dev_t; +typedef ssize_t off_t; +typedef size_t nlink_t; + +#endif