summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2011-09-07 16:22:28 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2011-09-07 16:22:28 +0200
commit6c4875892e2710a9ff106136d469850cd0ced8ca (patch)
treea0c5358e62cc43a77099eb4bab5467cad722143f
parent2def83667b99c3f196a030687e69ea6470400ec4 (diff)
Changed seek mechanic.
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.
-rw-r--r--rtems/rtems_yaffs.c98
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)