[Yaffs] [PATCH 10/20] Changed seek mechanic.

Top Page
Attachments:
Message as email
+ (text/plain)
Delete this message
Reply to this message
Author: Xiangfu Liu
Date:  
To: yaffs
CC: sebastien
Old-Topics: [Yaffs] [PATCH 09/20] Check the device read-only property during mount.
New-Topics: [Yaffs] [PATCH 11/20] Use UNIX time instead of seconds since boot.
Subject: [Yaffs] [PATCH 10/20] Changed seek mechanic.
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