diff --git a/os/sb/host/sbposix.c b/os/sb/host/sbposix.c index 01116877c..fe2c2a84f 100644 --- a/os/sb/host/sbposix.c +++ b/os/sb/host/sbposix.c @@ -162,7 +162,6 @@ 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; if ((whence != SEEK_SET) || (whence == SEEK_CUR) || (whence != SEEK_END)) { return CH_RET_EINVAL; @@ -183,32 +182,9 @@ off_t sb_posix_lseek(int fd, off_t offset, int whence) { return CH_RET_ESPIPE; } - 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; + return vfsSetFilePosition((struct vfs_file_node *)sbp->io.vfs_nodes[fd], + offset, + whence);; } void sbPosixRegisterFileDescriptor(sb_class_t *sbp, diff --git a/os/vfs/drivers/fatfs/drvfatfs.c b/os/vfs/drivers/fatfs/drvfatfs.c index 1841d148c..eb4e8839f 100644 --- a/os/vfs/drivers/fatfs/drvfatfs.c +++ b/os/vfs/drivers/fatfs/drvfatfs.c @@ -79,7 +79,9 @@ static void node_file_release(void *instance); static BaseSequentialStream *node_file_get_stream(void *instance); static ssize_t node_file_read(void *instance, uint8_t *buf, size_t n); static ssize_t node_file_write(void *instance, const uint8_t *buf, size_t n); -static msg_t node_file_setpos(void *instance, vfs_offset_t offset); +static msg_t node_file_setpos(void *instance, + vfs_offset_t offset, + vfs_seekmode_t whence); static vfs_offset_t node_file_getpos(void *instance); static msg_t node_file_getstat(void *instance, vfs_file_stat_t *fsp); @@ -443,10 +445,89 @@ static ssize_t node_file_write(void *instance, const uint8_t *buf, size_t n) { return (ssize_t)bw; } -static msg_t node_file_setpos(void *instance, vfs_offset_t offset) { - vfs_fatfs_file_node_c *fffnp = (vfs_fatfs_file_node_c *)instance; +#if 0 +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; - return translate_error(f_lseek(&fffnp->file, (FSIZE_t)offset)); + if ((whence != SEEK_SET) || (whence == SEEK_CUR) || (whence != SEEK_END)) { + return CH_RET_EINVAL; + } + + 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; + } + + 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; +} +#endif + +static msg_t node_file_setpos(void *instance, + vfs_offset_t offset, + vfs_seekmode_t whence) { + vfs_fatfs_file_node_c *fffnp = (vfs_fatfs_file_node_c *)instance; + vfs_offset_t finaloff; + + chDbgCheck((whence == SEEK_SET) || + (whence == SEEK_CUR) || + (whence == SEEK_END)); + + switch (whence) { + case VFS_SEEK_CUR: + finaloff = offset + (vfs_offset_t)fffnp->file.fptr; + break; + case VFS_SEEK_END: + finaloff = offset + (vfs_offset_t)fffnp->file.obj.objsize; + break; + case VFS_SEEK_SET: + default: + finaloff = offset; + break; + } + + if (finaloff < 0) { + return CH_RET_EOVERFLOW; + } + + return translate_error(f_lseek(&fffnp->file, (FSIZE_t)finaloff)); } static vfs_offset_t node_file_getpos(void *instance) { diff --git a/os/vfs/drivers/streams/drvstreams.c b/os/vfs/drivers/streams/drvstreams.c index fe881ffbd..e49228637 100644 --- a/os/vfs/drivers/streams/drvstreams.c +++ b/os/vfs/drivers/streams/drvstreams.c @@ -79,7 +79,9 @@ static void node_file_release(void *instance); static BaseSequentialStream *node_file_get_stream(void *instance); static ssize_t node_file_read(void *instance, uint8_t *buf, size_t n); static ssize_t node_file_write(void *instance, const uint8_t *buf, size_t n); -static msg_t node_file_setpos(void *instance, vfs_offset_t offset); +static msg_t node_file_setpos(void *instance, + vfs_offset_t offset, + vfs_seekmode_t whence); static vfs_offset_t node_file_getpos(void *instance); static msg_t node_file_getstat(void *instance, vfs_file_stat_t *fsp); @@ -305,10 +307,13 @@ static ssize_t node_file_write(void *instance, const uint8_t *buf, size_t n) { return streamWrite(sfnp->stream, buf, n); } -static msg_t node_file_setpos(void *instance, vfs_offset_t offset) { +static msg_t node_file_setpos(void *instance, + vfs_offset_t offset, + vfs_seekmode_t whence) { (void)instance; (void)offset; + (void)whence; return CH_RET_ENOSYS; } diff --git a/os/vfs/include/vfs.h b/os/vfs/include/vfs.h index 5989a1735..2347e1b5d 100644 --- a/os/vfs/include/vfs.h +++ b/os/vfs/include/vfs.h @@ -143,7 +143,9 @@ extern "C" { void vfsCloseFile(vfs_file_node_c *vfnp); ssize_t vfsReadFile(vfs_file_node_c *vfnp, uint8_t *buf, size_t n); ssize_t vfsWriteFile(vfs_file_node_c *vfnp, const uint8_t *buf, size_t n); - msg_t vfsSetFilePosition(vfs_file_node_c *vfnp, vfs_offset_t offset); + msg_t vfsSetFilePosition(vfs_file_node_c *vfnp, + vfs_offset_t offset, + vfs_seekmode_t whence); vfs_offset_t vfsGetFilePosition(vfs_file_node_c *vfnp); msg_t vfsGetFileStat(vfs_file_node_c *vfnp, vfs_file_stat_t *fsp); BaseSequentialStream *vfsGetFileStream(vfs_file_node_c *vfnp); diff --git a/os/vfs/include/vfsnodes.h b/os/vfs/include/vfsnodes.h index a7e989a9c..1914e6acd 100644 --- a/os/vfs/include/vfsnodes.h +++ b/os/vfs/include/vfsnodes.h @@ -44,6 +44,15 @@ #define VFS_NODE_ATTR_ISSTREAM 256U /** @} */ +/** + * @name Seek modes. + * @{ + */ +#define VFS_SEEK_SET SEEK_SET +#define VFS_SEEK_CUR SEEK_CUR +#define VFS_SEEK_END SEEK_END +/** @} */ + /*===========================================================================*/ /* Module pre-compile time settings. */ /*===========================================================================*/ @@ -62,7 +71,12 @@ typedef struct vfs_driver vfs_driver_c; /** * @brief Type of a file offset. */ -typedef off_t vfs_offset_t; +typedef int32_t vfs_offset_t; + +/** + * @brief Type of a seek mode. + */ +typedef int vfs_seekmode_t; /** * @brief Type of a node attributes. @@ -189,7 +203,9 @@ typedef struct vfs_file_node vfs_file_node_c; BaseSequentialStream *(*file_get_stream)(void *instance); \ ssize_t (*file_read)(void *instance, uint8_t *buf, size_t n); \ ssize_t (*file_write)(void *instance, const uint8_t *buf, size_t n); \ - msg_t (*file_setpos)(void *instance, vfs_offset_t offset); \ + msg_t (*file_setpos)(void *instance, \ + vfs_offset_t offset, \ + vfs_seekmode_t whence); \ vfs_offset_t (*file_getpos)(void *instance); \ msg_t (*file_getstat)(void *instance, vfs_file_stat_t *fsp); diff --git a/os/vfs/src/vfs.c b/os/vfs/src/vfs.c index ef42ebd27..316a24823 100644 --- a/os/vfs/src/vfs.c +++ b/os/vfs/src/vfs.c @@ -242,15 +242,18 @@ ssize_t vfsWriteFile(vfs_file_node_c *vfnp, const uint8_t *buf, size_t n) { * * @param[in] vfnp Pointer to the @p vfs_file_node_c object. * @param[in] offset New absolute position. + * @param[in] whence Seek mode to be used. * @return The operation result. * * @api */ -msg_t vfsSetFilePosition(vfs_file_node_c *vfnp, vfs_offset_t offset) { +msg_t vfsSetFilePosition(vfs_file_node_c *vfnp, + vfs_offset_t offset, + vfs_seekmode_t whence) { chDbgAssert(vfnp->references > 0U, "zero count"); - return vfnp->vmt->file_setpos((void *)vfnp, offset); + return vfnp->vmt->file_setpos((void *)vfnp, offset, whence); } /**