diff --git a/os/common/utils/include/errcodes.h b/os/common/utils/include/errcodes.h index 8a55244dc..adcff33b1 100644 --- a/os/common/utils/include/errcodes.h +++ b/os/common/utils/include/errcodes.h @@ -66,6 +66,7 @@ #define CH_RET_ERANGE CH_ENCODE_ERROR(ERANGE) /* Result too large */ #define CH_RET_ENAMETOOLONG CH_ENCODE_ERROR(ENAMETOOLONG)/* File or path name too long */ #define CH_RET_ENOSYS CH_ENCODE_ERROR(ENOSYS) /* Syscall not implemented */ +#define CH_RET_EOVERFLOW CH_ENCODE_ERROR(EOVERFLOW) /* File offset overflow */ /** @} */ /*===========================================================================*/ diff --git a/os/sb/host/sbposix.c b/os/sb/host/sbposix.c index c296b417e..01116877c 100644 --- a/os/sb/host/sbposix.c +++ b/os/sb/host/sbposix.c @@ -159,16 +159,56 @@ ssize_t sb_posix_write(int fd, const void *buf, size_t count) { } off_t sb_posix_lseek(int fd, off_t offset, int whence) { + sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; + msg_t ret; + vfs_file_stat_t stat; + off_t finaloff; - (void)offset; - (void)whence; + if ((whence != SEEK_SET) || (whence == SEEK_CUR) || (whence != SEEK_END)) { + return CH_RET_EINVAL; + } - if ((fd == 0U) || (fd == 1U) || (fd == 2U)) { + if (!is_valid_descriptor(&sbp->io, fd)) { + return CH_RET_EBADF; + } + if (sbp->io.attributes[fd] != 0) { + return CH_RET_EISDIR; + } + + ret = vfsGetFileStat((struct vfs_file_node *)sbp->io.vfs_nodes[fd], &stat); + CH_RETURN_ON_ERROR(ret); + + if ((stat.attr & VFS_NODE_ATTR_ISSTREAM) != 0U) { return CH_RET_ESPIPE; } - return CH_RET_EBADF; + switch (whence) { + case SEEK_SET: + finaloff = offset; + break; + case SEEK_CUR: + { + off_t oldoff = vfsGetFilePosition((struct vfs_file_node *)sbp->io.vfs_nodes[fd]); + CH_RETURN_ON_ERROR(oldoff); + + finaloff = oldoff + offset; + } + break; + case SEEK_END: + finaloff = stat.size + offset; + break; + } + + if (finaloff < 0) { + return CH_RET_EOVERFLOW; + } + + ret = vfsSetFilePosition((struct vfs_file_node *)sbp->io.vfs_nodes[fd], + finaloff); + CH_RETURN_ON_ERROR(ret); + + return finaloff; } void sbPosixRegisterFileDescriptor(sb_class_t *sbp,