diff --git a/src/arch/x86_64/syscall.asm b/src/arch/x86_64/syscall.asm index d55be20e..ac3edeb8 100644 --- a/src/arch/x86_64/syscall.asm +++ b/src/arch/x86_64/syscall.asm @@ -21,7 +21,8 @@ extern syscall_dup extern syscall_dup2 extern syscall_fcntl extern syscall_getpid -func_count equ 20 +extern syscall_getdirent +func_count equ 21 func_table: @@ -45,6 +46,7 @@ func_table: dq syscall_dup2 dq syscall_fcntl dq syscall_getpid + dq syscall_getdirent section .text global asm_syscall_entry diff --git a/src/sys/syscalls/getdirent.c b/src/sys/syscalls/getdirent.c new file mode 100644 index 00000000..9477b398 --- /dev/null +++ b/src/sys/syscalls/getdirent.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include + +syscallret syscall_getdirent(int ifd, void* buff, size_t max_size){ + syscallret retv; + retv.ret = -1; + + if(buff > USER_SPACE_END){ + retv.errno = EFAULT; + return retv; + } + + size_t readc = max_size / sizeof(dent_t); + + if(readc == 0){ + retv.errno = EINVAL; + return retv; + } + + fd_t* fd; + + retv.errno = fd_access(&arch_getcls()->thread->proc->fdtable, &fd, ifd); + + if(retv.errno) + return retv; + + if(GETTYPE(fd->node->st.st_mode) != TYPE_DIR){ + retv.errno = ENOTDIR; + fd_release(fd); + return retv; + } + + dent_t kbuff[readc]; + + retv.errno = vfs_getdirent(fd->node, kbuff, readc, fd->offset, &retv.ret); + + + fd->offset += retv.ret; + + retv.ret *= sizeof(dent_t); + + memcpy(buff, kbuff, retv.ret); // XXX use user memcpy + + fd_release(fd); + + return retv; + +}