mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
vfs: initial symlink implementation
This commit is contained in:
@@ -178,6 +178,12 @@ void initrd_parse(){
|
||||
if(err)
|
||||
printf("Failed creating %s: ERROR %lu\n", entry.name, err);
|
||||
break;
|
||||
case TAR_SYMLINK:
|
||||
err = vfs_symlink(vfs_root(), entry.name, entry.link, entry.mode);
|
||||
if(err)
|
||||
printf("Failed creating %s: ERROR %lu\n", entry.name, err);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+39
-1
@@ -182,8 +182,46 @@ static int tmpfs_mksocket(dirnode_t* parent, char* name, mode_t mode){
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int tmpfs_symlink(dirnode_t* parent, char* name, char* target, mode_t mode){
|
||||
int error = tmpfs_create(parent, name, mode);
|
||||
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
vnode_t* node = hashtable_get(&parent->children, name);
|
||||
|
||||
node->st.st_mode = MAKETYPE(TYPE_LINK) | mode;
|
||||
|
||||
tmpfs_write(&error, node, target, strlen(target)+1, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int tmpfs_readlink(vnode_t *node, char** buff, size_t* linksize){
|
||||
|
||||
if(node->st.st_size >= 512)
|
||||
return ENAMETOOLONG;
|
||||
|
||||
*buff = alloc(node->st.st_size+1);
|
||||
|
||||
if(!*buff)
|
||||
return ENOMEM;
|
||||
|
||||
int error;
|
||||
|
||||
*linksize = tmpfs_read(&error, node, *buff, 512, 0);
|
||||
|
||||
if(error)
|
||||
free(*buff);
|
||||
|
||||
return error;
|
||||
|
||||
}
|
||||
|
||||
static fscalls_t funcs = {
|
||||
tmpfs_mount, tmpfs_unmount, tmpfs_open, tmpfs_close, tmpfs_mkdir, tmpfs_create, tmpfs_write, tmpfs_read, tmpfs_getdirent, tmpfs_chmod, tmpfs_mksocket
|
||||
tmpfs_mount, tmpfs_unmount, tmpfs_open, tmpfs_close, tmpfs_mkdir, tmpfs_create, tmpfs_write, tmpfs_read, tmpfs_getdirent, tmpfs_chmod, tmpfs_mksocket, tmpfs_symlink, tmpfs_readlink
|
||||
};
|
||||
|
||||
|
||||
|
||||
+107
-8
@@ -9,6 +9,8 @@
|
||||
#include <kernel/pipe.h>
|
||||
#include <arch/timekeeper.h>
|
||||
|
||||
#define VFS_MAX_LOOP 5
|
||||
|
||||
dirnode_t* vfsroot;
|
||||
hashtable fsfuncs;
|
||||
static int lock;
|
||||
@@ -219,7 +221,7 @@ int vfs_open(vnode_t** buff, dirnode_t* ref, char* path){
|
||||
|
||||
spinlock_acquire(&lock);
|
||||
|
||||
int res = vfs_resolvepath(&node, NULL, ref, path, NULL);
|
||||
int res = vfs_resolvepath(&node, NULL, ref, path, NULL, true, VFS_MAX_LOOP);
|
||||
|
||||
if(res){
|
||||
spinlock_release(&lock);
|
||||
@@ -244,7 +246,7 @@ int vfs_create(dirnode_t* ref, char* path, mode_t mode){
|
||||
|
||||
spinlock_acquire(&lock);
|
||||
|
||||
int result = vfs_resolvepath(&buff, &parent, ref, path, name);
|
||||
int result = vfs_resolvepath(&buff, &parent, ref, path, name, true, VFS_MAX_LOOP);
|
||||
|
||||
if(buff){
|
||||
spinlock_release(&lock);
|
||||
@@ -274,7 +276,7 @@ int vfs_mksocket(dirnode_t* ref, char* path, mode_t mode){
|
||||
|
||||
spinlock_acquire(&lock);
|
||||
|
||||
int result = vfs_resolvepath(&buff, &parent, ref, path, name);
|
||||
int result = vfs_resolvepath(&buff, &parent, ref, path, name, true, VFS_MAX_LOOP);
|
||||
|
||||
if(buff){
|
||||
spinlock_release(&lock);
|
||||
@@ -300,6 +302,44 @@ int vfs_mksocket(dirnode_t* ref, char* path, mode_t mode){
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vfs_symlink(dirnode_t* ref, char* path, char* target, mode_t mode){
|
||||
|
||||
if(strlen(target) >= 512)
|
||||
return ENAMETOOLONG;
|
||||
|
||||
dirnode_t* parent = NULL;
|
||||
dirnode_t* buff = NULL;
|
||||
char name[512];
|
||||
|
||||
spinlock_acquire(&lock);
|
||||
|
||||
int result = vfs_resolvepath(&buff, &parent, ref, path, name, true, VFS_MAX_LOOP);
|
||||
|
||||
if(buff){
|
||||
spinlock_release(&lock);
|
||||
return EEXIST;
|
||||
}
|
||||
|
||||
if(!parent){
|
||||
spinlock_release(&lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
if(!parent->vnode.fs->calls->symlink){
|
||||
spinlock_release(&lock);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
result = parent->vnode.fs->calls->symlink(parent, name, target, mode);
|
||||
|
||||
spinlock_release(&lock);
|
||||
|
||||
if(result) return result;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
int vfs_mkdir(dirnode_t* ref, char* path, mode_t mode){
|
||||
|
||||
dirnode_t* parent = NULL;
|
||||
@@ -309,7 +349,7 @@ int vfs_mkdir(dirnode_t* ref, char* path, mode_t mode){
|
||||
|
||||
spinlock_acquire(&lock);
|
||||
|
||||
int result = vfs_resolvepath(&buff, &parent, ref, path, name);
|
||||
int result = vfs_resolvepath(&buff, &parent, ref, path, name, true, VFS_MAX_LOOP);
|
||||
|
||||
if(buff){
|
||||
spinlock_release(&lock);
|
||||
@@ -346,7 +386,7 @@ int vfs_mount(dirnode_t* ref, char* device, char* mountpoint, char* fs, int moun
|
||||
if(device){
|
||||
dev = ref;
|
||||
if(*device){
|
||||
int result = vfs_resolvepath(&dev, &parent, ref, device, NULL);
|
||||
int result = vfs_resolvepath(&dev, &parent, ref, device, NULL, true, VFS_MAX_LOOP);
|
||||
|
||||
if(result){
|
||||
spinlock_release(&lock);
|
||||
@@ -356,7 +396,7 @@ int vfs_mount(dirnode_t* ref, char* device, char* mountpoint, char* fs, int moun
|
||||
}
|
||||
|
||||
|
||||
int result = vfs_resolvepath(&mountdir, &parent, ref, mountpoint, NULL);
|
||||
int result = vfs_resolvepath(&mountdir, &parent, ref, mountpoint, NULL, true, VFS_MAX_LOOP);
|
||||
|
||||
if(result){
|
||||
spinlock_release(&lock);
|
||||
@@ -429,13 +469,21 @@ dirnode_t* vfs_newdirnode(char* name, fs_t* fs, void* fsdata, dirnode_t* parent)
|
||||
|
||||
}
|
||||
|
||||
int vfs_resolvepath(vnode_t** result, dirnode_t** resultparent, dirnode_t* ref, char *path, char* namebuff){
|
||||
// TODO the stack usage is scarily high
|
||||
|
||||
int vfs_resolvepath(vnode_t** result, dirnode_t** resultparent, dirnode_t* ref, char *path, char* namebuff, bool followlinks, int maxloop){
|
||||
|
||||
if(strlen(path) >= 512)
|
||||
return ENAMETOOLONG;
|
||||
|
||||
if(maxloop == 0)
|
||||
return ELOOP;
|
||||
|
||||
dirnode_t* iterator = ref;
|
||||
char name[512];
|
||||
off_t nameoffset = 0;
|
||||
|
||||
memset(name, 0, 512);
|
||||
memset(name, 0, 256);
|
||||
|
||||
iterator = mountpoint(iterator);
|
||||
|
||||
@@ -457,6 +505,33 @@ int vfs_resolvepath(vnode_t** result, dirnode_t** resultparent, dirnode_t* ref,
|
||||
++nameoffset;
|
||||
|
||||
name[offset] = 0;
|
||||
|
||||
// do we need to follow a symlink
|
||||
|
||||
if(GETTYPE(iterator->vnode.st.st_mode) == TYPE_LINK && followlinks){
|
||||
|
||||
if(!iterator->vnode.fs->calls->readlink)
|
||||
return ENOSYS;
|
||||
|
||||
size_t size;
|
||||
char* linkname;
|
||||
|
||||
int error = iterator->vnode.fs->calls->readlink(iterator, &linkname, &size);
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
linkname[size] = '\0';
|
||||
|
||||
printf("reading link: %s\n", linkname);
|
||||
|
||||
error = vfs_resolvepath(&iterator, NULL, iterator, linkname, namebuff, true, maxloop-1); // XXX this might break some parent stuff when following links
|
||||
|
||||
free(linkname);
|
||||
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
}
|
||||
|
||||
// make sure we're a directory
|
||||
|
||||
@@ -501,6 +576,30 @@ int vfs_resolvepath(vnode_t** result, dirnode_t** resultparent, dirnode_t* ref,
|
||||
if(GETTYPE(iterator->vnode.st.st_mode) == TYPE_DIR)
|
||||
iterator = mountpoint(iterator);
|
||||
|
||||
|
||||
// check if result is a symlink
|
||||
|
||||
if(GETTYPE(iterator->vnode.st.st_mode) == TYPE_LINK && followlinks){
|
||||
if(!iterator->vnode.fs->calls->readlink)
|
||||
return ENOSYS;
|
||||
|
||||
size_t size;
|
||||
char* linkname;
|
||||
|
||||
int error = iterator->vnode.fs->calls->readlink(iterator, &linkname, &size);
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
linkname[size] = '\0';
|
||||
|
||||
error = vfs_resolvepath(&iterator, NULL, iterator->vnode.parent, linkname, namebuff, true, maxloop-1); // XXX this might break some parent stuff when following links
|
||||
|
||||
free(linkname);
|
||||
|
||||
if(error)
|
||||
return error;
|
||||
}
|
||||
|
||||
*result = (vnode_t*)iterator;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <poll.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct _vnode_t;
|
||||
struct _fscalls_t;
|
||||
@@ -65,6 +66,10 @@ typedef struct _fscalls_t {
|
||||
int (*chmod)(vnode_t* node, mode_t mode);
|
||||
// create socket in address
|
||||
int (*mksocket)(dirnode_t* ref, char* path, mode_t mode);
|
||||
// creates a symlink
|
||||
int (*symlink)(dirnode_t* ref, char* path, char* target, mode_t mode);
|
||||
// reads a symlink
|
||||
int (*readlink)(vnode_t* node, char** buff, size_t* linksize);
|
||||
} fscalls_t;
|
||||
|
||||
int vfs_mksocket(dirnode_t* ref, char* path, mode_t mode);
|
||||
@@ -81,6 +86,7 @@ int vfs_getdirent(dirnode_t* node, dent_t* buff, size_t count, uintmax_t offset,
|
||||
int vfs_ioctl(vnode_t* node, unsigned long request, void* arg, int* result);
|
||||
int vfs_poll(vnode_t* node, pollfd* fd);
|
||||
int vfs_chmod(vnode_t* node, mode_t mode);
|
||||
int vfs_symlink(dirnode_t* ref, char* path, char* target, mode_t mode);
|
||||
|
||||
void vfs_init();
|
||||
dirnode_t* vfs_root();
|
||||
@@ -89,7 +95,7 @@ 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, dirnode_t* parent);
|
||||
void vfs_destroynode(vnode_t* node);
|
||||
int vfs_resolvepath(vnode_t** result, dirnode_t** parent, dirnode_t* ref, char* path, char* name);
|
||||
int vfs_resolvepath(vnode_t** result, dirnode_t** parent, dirnode_t* ref, char* path, char* name, bool followlinks, int maxloop);
|
||||
|
||||
#define UNIMPLEMENTED { return ENOSYS; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user