diff --git a/src/fs/tmpfs.c b/src/fs/tmpfs.c index 73c2845a..df5f0fc3 100644 --- a/src/fs/tmpfs.c +++ b/src/fs/tmpfs.c @@ -1,28 +1,75 @@ #include #include #include +#include -static int tmpfs_mount(dirnode_t** rootptr, vnode_t* device, int mountflags, void* fsinfo){ +static int tmpfs_mount(dirnode_t* mountpoint, vnode_t* device, int mountflags, void* fsinfo){ fs_t* desc = alloc(sizeof(fs_t)); if(!desc) return ENOMEM; - dirnode_t* root = vfs_newdirnode(desc, NULL); + dirnode_t* root = vfs_newdirnode(mountpoint->vnode.name, desc, NULL); if(!root){ free(desc); return ENOMEM; } - *rootptr = root; + desc->calls = tmpfs_getfuncs(); + mountpoint->mount = root; + + return 0; +} + +static int tmpfs_unmount(fs_t* fs) UNIMPLEMENTED +static int tmpfs_open(dirnode_t* parent, char* name) UNIMPLEMENTED +static int tmpfs_close(vnode_t* node) UNIMPLEMENTED + +static int tmpfs_mkdir(dirnode_t* parent, char* name, mode_t mode){ + dirnode_t* node = vfs_newdirnode(name, parent->vnode.fs, NULL); + + if(!node) + return ENOMEM; + + if(!hashtable_insert(&parent->children, name, node)){ + vfs_destroynode(node); + return ENOMEM; + } + + node->vnode.parent = parent; + stat* st = &node->vnode.st; + st->st_mode = MAKETYPE(TYPE_DIR) | GETMODE(mode); + st->st_blksize = PAGE_SIZE; + + return 0; + +} + +static int tmpfs_create(dirnode_t* parent, char* name, mode_t mode){ + + vnode_t* node = vfs_newnode(name, parent->vnode.fs, NULL); + + if(!node) + return ENOMEM; + + if(!hashtable_insert(&parent->children, name, node)){ + vfs_destroynode(node); + return ENOMEM; + } + + node->parent = parent; + stat* st = &node->st; + st->st_mode = MAKETYPE(TYPE_DIR) | GETMODE(mode); + st->st_blksize = PAGE_SIZE; + return 0; } static fscalls_t funcs = { - tmpfs_mount + tmpfs_mount, tmpfs_unmount, tmpfs_open, tmpfs_close, tmpfs_mkdir, tmpfs_create }; diff --git a/src/fs/vfs.c b/src/fs/vfs.c index b61b9939..0b3d22e4 100644 --- a/src/fs/vfs.c +++ b/src/fs/vfs.c @@ -14,6 +14,50 @@ static inline dirnode_t* mountpoint(dirnode_t* node){ return ret; } +int vfs_create(dirnode_t* ref, char* path, mode_t mode){ + + dirnode_t* parent = NULL; + dirnode_t* buff = NULL; + + char name[512]; + + int result = vfs_resolvepath(&buff, &parent, ref, path, name); + + if(!parent) + return result; + + if(buff) + return EEXIST; + + result = parent->vnode.fs->calls->create(parent, name, NULL); + + if(result) return result; + + return 0; +} + +int vfs_mkdir(dirnode_t* ref, char* path, mode_t mode){ + + dirnode_t* parent = NULL; + dirnode_t* buff = NULL; + + char name[512]; + + int result = vfs_resolvepath(&buff, &parent, ref, path, name); + + if(!parent) + return result; + + if(buff) + return EEXIST; + + result = parent->vnode.fs->calls->mkdir(parent, name, NULL); + + if(result) return result; + + return 0; +} + int vfs_mount(dirnode_t* ref, char* device, char* mountpoint, char* fs, int mountflags, void* fsinfo){ fscalls_t* fscalls = hashtable_get(&fsfuncs, fs); @@ -23,11 +67,12 @@ int vfs_mount(dirnode_t* ref, char* device, char* mountpoint, char* fs, int moun vnode_t* dev = NULL; dirnode_t* mountdir = ref; + dirnode_t* parent; if(device){ dev = ref; if(*device){ - int result = vfs_resolvepath(&dev, ref, device); + int result = vfs_resolvepath(&dev, &parent, ref, device, NULL); if(result) return result; @@ -35,7 +80,7 @@ int vfs_mount(dirnode_t* ref, char* device, char* mountpoint, char* fs, int moun } - int result = vfs_resolvepath(&mountdir, ref, mountpoint); + int result = vfs_resolvepath(&mountdir, &parent, ref, mountpoint, NULL); if(result) return result; @@ -43,16 +88,9 @@ int vfs_mount(dirnode_t* ref, char* device, char* mountpoint, char* fs, int moun if(GETTYPE(mountdir->vnode.st.st_mode) != TYPE_DIR) return ENOTDIR; - dirnode_t* mount; - - result = fscalls->mount(&mount, dev, mountflags, fsinfo); + result = fscalls->mount(mountdir, dev, mountflags, fsinfo); - if(result) - return result; - - mountdir->mount = mount; - - return 0; + return result; } vnode_t* vfs_newnode(char* name, fs_t* fs, void* fsdata){ @@ -100,7 +138,7 @@ dirnode_t* vfs_newdirnode(char* name, fs_t* fs, void* fsdata){ } -int vfs_resolvepath(vnode_t** result, dirnode_t* ref, char *path){ +int vfs_resolvepath(vnode_t** result, dirnode_t** resultparent, dirnode_t* ref, char *path, char* namebuff){ dirnode_t* iterator = ref; char name[512]; @@ -114,10 +152,13 @@ int vfs_resolvepath(vnode_t** result, dirnode_t* ref, char *path){ size_t offset = 0; + while(path[nameoffset] == '/') + ++nameoffset; + while(path[nameoffset] && path[nameoffset] != '/') name[offset++] = path[nameoffset++]; - - if(path[nameoffset] == '/') + + while(path[nameoffset] == '/') ++nameoffset; name[offset] = 0; @@ -132,14 +173,20 @@ int vfs_resolvepath(vnode_t** result, dirnode_t* ref, char *path){ iterator = mountpoint(iterator); // now try to get the right child - + vnode_t* child = hashtable_get(&iterator->children, name); if(!child){ // open it int status = iterator->vnode.fs->calls->open(iterator, name); - if(status) + if(status){ + if(!path[nameoffset]){ + if(namebuff) + strcpy(namebuff, name); + *resultparent = iterator; + } return status; + } child = hashtable_get(&iterator->children, name); @@ -148,7 +195,11 @@ int vfs_resolvepath(vnode_t** result, dirnode_t* ref, char *path){ iterator = (dirnode_t*)child; } + + if(namebuff) + strcpy(namebuff, name); + *resultparent = iterator->vnode.parent; *result = (vnode_t*)iterator; return 0; diff --git a/src/include/errno.h b/src/include/errno.h index 42312ea5..6ccd045b 100644 --- a/src/include/errno.h +++ b/src/include/errno.h @@ -5,5 +5,7 @@ #define ENODEV 2 #define ENOMEM 3 #define EINVAL 4 +#define ENOSYS 5 +#define EEXIST 6 #endif diff --git a/src/include/kernel/vfs.h b/src/include/kernel/vfs.h index a5449a25..d156a12d 100644 --- a/src/include/kernel/vfs.h +++ b/src/include/kernel/vfs.h @@ -37,7 +37,7 @@ typedef struct _dirnode_t{ typedef struct _fscalls_t { // prepares the filesystem using a filesystem data pointer and device, returning the root node in rootptr - int (*mount)(dirnode_t** rootptr, vnode_t* device, int mountflags, void* fsinfo); + int (*mount)(dirnode_t* mountpoint, vnode_t* device, int mountflags, void* fsinfo); // cleanup of the filesystem int (*umount)(fs_t* fs); // opens a file under a dirnode @@ -70,6 +70,8 @@ void vfs_releasenode(vnode_t* node); vnode_t* vfs_newnode(char* name, fs_t* fs, void* fsdata); dirnode_t* vfs_newdirnode(char* name, fs_t* fs, void* fsdata); void vfs_destroynode(vnode_t* node); -int vfs_resolvepath(vnode_t** result, dirnode_t* ref, char* path); +int vfs_resolvepath(vnode_t** result, dirnode_t** parent, dirnode_t* ref, char* path, char* name); + +#define UNIMPLEMENTED { return ENOSYS; } #endif