diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_filedesc.c | 59 | ||||
-rw-r--r-- | sys/kern/kern_syscall.c | 1 |
2 files changed, 60 insertions, 0 deletions
diff --git a/sys/kern/kern_filedesc.c b/sys/kern/kern_filedesc.c index 63ffa98..6cdc1ee 100644 --- a/sys/kern/kern_filedesc.c +++ b/sys/kern/kern_filedesc.c @@ -339,6 +339,54 @@ read(int fd, void *buf, size_t count) } /* + * Reposition the file offset + * + * @fd: File descriptor. + * @offset: Offset for the reposition + * @whence: SEEK_SET, SEEK_CUR, or SEEK_END + * + * TODO: Implement SEEK_END + */ +off_t +lseek(int fd, off_t offset, int whence) +{ + struct filedesc *fd_desc; + struct vattr vattr; + + fd_desc = fd_from_fdnum(this_td(), fd); + + if (fd_desc == NULL) { + return -EBADF; + } + + if (vfs_getattr(fd_desc->vnode, &vattr) != 0) { + return -1; + } + + switch (whence) { + case SEEK_SET: + if (offset > vattr.size) + return -ESPIPE; + + fd_desc->offset = offset; + break; + case SEEK_CUR: + if ((fd_desc->offset + offset) > vattr.size) + return -ESPIPE; + + fd_desc->offset += offset; + break; + case SEEK_END: + /* TODO */ + break; + default: + return -EINVAL; + } + + return fd_desc->offset; +} + +/* * arg0: int fd * arg1: const void *buf * arg2: count @@ -418,3 +466,14 @@ sys_read(struct syscall_args *args) } return bytes_read; } + +/* + * arg0: fd + * arg1: offset: + * arg2: whence + */ +uint64_t +sys_lseek(struct syscall_args *args) +{ + return lseek(args->arg0, args->arg1, args->arg2); +} diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c index 0f45469..a630195 100644 --- a/sys/kern/kern_syscall.c +++ b/sys/kern/kern_syscall.c @@ -46,4 +46,5 @@ uint64_t(*g_syscall_table[__MAX_SYSCALLS])(struct syscall_args *args) = { sys_open, sys_close, sys_read, + sys_lseek, }; |