diff --git a/src/arch/x86_64/syscall.asm b/src/arch/x86_64/syscall.asm index f18d27ff..12bba1cc 100644 --- a/src/arch/x86_64/syscall.asm +++ b/src/arch/x86_64/syscall.asm @@ -6,7 +6,8 @@ extern syscall_mmap extern syscall_arch_ctl extern syscall_gettid extern syscall_open -func_count equ 5 +extern syscall_read +func_count equ 6 func_table: @@ -15,6 +16,7 @@ func_table: dq syscall_arch_ctl dq syscall_gettid dq syscall_open + dq syscall_read section .text global asm_syscall_entry diff --git a/src/sys/syscalls/read.c b/src/sys/syscalls/read.c new file mode 100644 index 00000000..15600d67 --- /dev/null +++ b/src/sys/syscalls/read.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +syscallret syscall_read(int ifd, void* buff, size_t count){ + + syscallret retv; + retv.ret = -1; + + if(buff > USER_SPACE_END){ + retv.errno = EFAULT; + return retv; + } + + proc_t* proc = arch_getcls()->thread->proc; + + fd_t* fd = proc->fds + ifd; + + spinlock_acquire(&proc->fdlock); + + if(proc->fdcount <= ifd || fd->node == NULL || (fd->flags & FD_FLAGS_READ) == 0){ + spinlock_release(&proc->fdlock); + retv.errno = EBADF; + return retv; + } + + spinlock_acquire(&fd->lock); + spinlock_release(&proc->fdlock); + + void* kbuff = alloc(count); + + if(!kbuff){ + spinlock_release(&fd->lock); + retv.errno = ENOMEM; + return retv; + } + + int err; + size_t readc = vfs_read(&err, fd->node, kbuff, count, fd->offset); + + spinlock_release(&fd->lock); + + + if(err){ + free(kbuff); + retv.errno = err; + return retv; + } + + memcpy(buff, kbuff, count); // XXX user version for safety + + + retv.errno = 0; + retv.ret = readc; + + return retv; +}