From: Sebastian Huber The seek mechanic is now more in line with other file systems on RTEMS. Concurrent write access may lead to confusion if a seek at the file end will be performed. --- rtems/rtems_yaffs.c | 98 +++++++++++++++++++++++++++++--------------------- 1 files changed, 57 insertions(+), 41 deletions(-) diff --git a/rtems/rtems_yaffs.c b/rtems/rtems_yaffs.c index f6869cd..92fb171 100644 --- a/rtems/rtems_yaffs.c +++ b/rtems/rtems_yaffs.c @@ -36,6 +36,8 @@ #include "rtems_yaffs.h" +#define MAX_SIZE 0x7fffffff + /* locking */ static void ylock(struct yaffs_dev *dev) @@ -58,6 +60,11 @@ static void rtems_yaffs_os_unmount(struct yaffs_dev *dev) /* Helper functions */ +static int is_valid_offset(rtems_off64_t offset) +{ + return (0 <= offset && offset <= MAX_SIZE); +} + static int is_path_divider(YCHAR ch) { const YCHAR *str = YAFFS_PATH_DIVIDERS; @@ -547,11 +554,12 @@ static ssize_t ycb_dir_read(rtems_libio_t *iop, void *buffer, size_t count) static rtems_off64_t ycb_dir_lseek(rtems_libio_t *iop, rtems_off64_t length, int whence) { - /* we don't support anything else than rewinding */ - if((whence != SEEK_SET) || (length != 0)) - rtems_set_errno_and_return_minus_one(ENOTSUP); - iop->offset = 0; - return 0; + /* We support only rewinding */ + if (whence == SEEK_SET && length == 0) { + return 0; + } else { + rtems_set_errno_and_return_minus_one(EINVAL); + } } static int ycb_fstat(rtems_filesystem_location_info_t *loc, struct stat *buf) @@ -676,7 +684,19 @@ static int ycb_dir_rmnod(rtems_filesystem_location_info_t *parent_loc, rtems_fil static int ycb_file_open(rtems_libio_t *iop, const char *pathname, uint32_t flag, uint32_t mode) { - /* nothing to do */ + const rtems_filesystem_location_info_t *pathinfo = &iop->pathinfo; + struct yaffs_obj *obj = pathinfo->node_access; + struct yaffs_dev *dev = obj->my_dev; + int length = 0; + + ylock(dev); + length = yaffs_get_obj_length(obj); + iop->size = length; + if ((iop->flags & LIBIO_FLAGS_APPEND) != 0) { + iop->offset = length; + } + yunlock(dev); + return 0; } @@ -720,50 +740,46 @@ static ssize_t ycb_file_read(rtems_libio_t *iop, void *buffer, size_t count) static ssize_t ycb_file_write(rtems_libio_t *iop, const void *buffer, size_t count) { - struct yaffs_obj *obj; - struct yaffs_dev *dev; - ssize_t nw; + const rtems_filesystem_location_info_t *pathinfo = &iop->pathinfo; + struct yaffs_obj *obj = pathinfo->node_access; + struct yaffs_dev *dev = obj->my_dev; + rtems_off64_t offset = 0; + rtems_off64_t new_offset = 0; + ssize_t rv = -1; - obj = iop->pathinfo.node_access; - if(obj->my_dev->read_only) { - errno = EROFS; - return -1; + if (count == 0) { + return 0; } - dev = obj->my_dev; + ylock(dev); - nw = yaffs_wr_file(obj, buffer, iop->offset, (int)count, 0); - yunlock(dev); - if(nw < 0) { - errno = ENOSPC; - return -1; + offset = iop->offset; + new_offset = offset + count; + if (is_valid_offset(new_offset)) { + rv = yaffs_wr_file(obj, buffer, offset, (int) count, 0); + if (rv > 0) { + new_offset = offset + rv; + iop->offset = new_offset; + if (iop->size < new_offset) { + iop->size = new_offset; + } + } else { + errno = ENOSPC; + } + } else { + errno = EINVAL; } - return nw; + yunlock(dev); + + return rv; } static rtems_off64_t ycb_file_lseek(rtems_libio_t *iop, rtems_off64_t length, int whence) { - struct yaffs_obj *obj; - struct yaffs_dev *dev; - - obj = iop->pathinfo.node_access; - switch(whence) { - case SEEK_SET: - iop->offset = length; - break; - case SEEK_CUR: - iop->offset += length; - break; - case SEEK_END: - dev = obj->my_dev; - ylock(dev); - iop->offset = yaffs_get_obj_length(obj) + length; - yunlock(dev); - break; - default: - errno = EINVAL; - return -1; + if (is_valid_offset(iop->offset)) { + return 0; + } else { + rtems_set_errno_and_return_minus_one(EINVAL); } - return iop->offset; } int ycb_file_ftruncate(rtems_libio_t *iop, rtems_off64_t length) -- 1.7.4.1