diff --git a/src/fs/tmpfs.c b/src/fs/tmpfs.c index 32e39ba8..af6836b0 100644 --- a/src/fs/tmpfs.c +++ b/src/fs/tmpfs.c @@ -220,8 +220,17 @@ static int tmpfs_readlink(vnode_t *node, char** buff, size_t* linksize){ } +static int tmpfs_link(dirnode_t* parent, char* name, vnode_t* link){ + + if(!hashtable_insert(&parent->children, name, link)) + return ENOMEM; + + ++link->st.st_nlink; + +} + 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_symlink, tmpfs_readlink + 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, tmpfs_link }; diff --git a/src/fs/vfs.c b/src/fs/vfs.c index 3cbe5a0c..5ec0367c 100644 --- a/src/fs/vfs.c +++ b/src/fs/vfs.c @@ -297,9 +297,7 @@ int vfs_mksocket(dirnode_t* ref, char* path, mode_t mode){ spinlock_release(&lock); - if(result) return result; - - return 0; + return result; } int vfs_symlink(dirnode_t* ref, char* path, char* target, mode_t mode){ @@ -334,12 +332,49 @@ int vfs_symlink(dirnode_t* ref, char* path, char* target, mode_t mode){ spinlock_release(&lock); - if(result) return result; - + return result; } +int vfs_link(dirnode_t* ref, vnode_t* link, char* path){ + + 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->link){ + spinlock_release(&lock); + return ENOSYS; + } + + if(link->fs != parent->vnode.fs) + return EXDEV; + + result = parent->vnode.fs->calls->link(parent, link, name); + + spinlock_release(&lock); + + return result; + + +} + + int vfs_mkdir(dirnode_t* ref, char* path, mode_t mode){ dirnode_t* parent = NULL; @@ -365,9 +400,7 @@ int vfs_mkdir(dirnode_t* ref, char* path, mode_t mode){ spinlock_release(&lock); - if(result) return result; - - return 0; + return result; } int vfs_mount(dirnode_t* ref, char* device, char* mountpoint, char* fs, int mountflags, void* fsinfo){ diff --git a/src/include/kernel/vfs.h b/src/include/kernel/vfs.h index 04474aee..42d8cad1 100644 --- a/src/include/kernel/vfs.h +++ b/src/include/kernel/vfs.h @@ -70,6 +70,8 @@ typedef struct _fscalls_t { 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); + // creates a hard link + int (*link)(dirnode_t* parent, vnode_t* link, char* name); } fscalls_t; int vfs_mksocket(dirnode_t* ref, char* path, mode_t mode); @@ -87,6 +89,7 @@ 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); +int vfs_link(dirnode_t* ref, vnode_t* link, char* path); void vfs_init(); dirnode_t* vfs_root();