diff options
-rw-r--r-- | sys/include/sys/filedesc.h | 7 | ||||
-rw-r--r-- | sys/include/sys/syscall.h | 1 | ||||
-rw-r--r-- | sys/kern/kern_filedesc.c | 59 | ||||
-rw-r--r-- | sys/kern/kern_syscall.c | 1 |
4 files changed, 67 insertions, 1 deletions
diff --git a/sys/include/sys/filedesc.h b/sys/include/sys/filedesc.h index 70b297d..83c32ee 100644 --- a/sys/include/sys/filedesc.h +++ b/sys/include/sys/filedesc.h @@ -39,6 +39,10 @@ #define O_WRONLY 0x00001 #define O_RDWR 0x00002 +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + struct proc; struct filedesc { @@ -56,11 +60,12 @@ void fd_close_fdnum(struct proc *td, int fdno); ssize_t write(int fd, const void *buf, size_t count); int open(const char *pathname, int oflag); int read(int fd, void *buf, size_t count); +off_t lseek(int fd, off_t offset, int whence); uint64_t sys_write(struct syscall_args *args); uint64_t sys_open(struct syscall_args *args); uint64_t sys_close(struct syscall_args *args); uint64_t sys_read(struct syscall_args *args); +uint64_t sys_lseek(struct syscall_args *args); #endif - #endif diff --git a/sys/include/sys/syscall.h b/sys/include/sys/syscall.h index ae2438f..8ebc2da 100644 --- a/sys/include/sys/syscall.h +++ b/sys/include/sys/syscall.h @@ -42,6 +42,7 @@ enum { SYS_open, SYS_close, SYS_read, + SYS_lseek, __MAX_SYSCALLS }; 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, }; |