[rtems commit] Filesystem: PR1398: Fix lseek() mechanic

Sebastian Huber sebh at rtems.org
Fri May 11 11:57:21 UTC 2012


Module:    rtems
Branch:    master
Commit:    30d412469c930fe4150ad2b9a321eea2747ec6f4
Changeset: http://git.rtems.org/rtems/commit/?id=30d412469c930fe4150ad2b9a321eea2747ec6f4

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon May  7 16:30:37 2012 +0200

Filesystem: PR1398: Fix lseek() mechanic

According to POSIX the lseek() function shall not, by itself, extend the
size of a file.

Remove the size field of rtems_libio_t.  A file has only one size but
may have multiple open file descriptors.  Thus a file size field in the
file descriptor may lead to inconsistencies.

New default handlers rtems_filesystem_default_lseek_file() and
rtems_filesystem_default_lseek_directory().

---

 cpukit/libblock/src/blkdev-imfs.c                  |    2 +-
 cpukit/libcsupport/include/rtems/libio.h           |   50 +++++++++++++--
 cpukit/libcsupport/src/lseek.c                     |   54 +---------------
 cpukit/libfs/Makefile.am                           |    3 +-
 ...t_lseek_success.c => default_lseek_directory.c} |   14 +++-
 cpukit/libfs/src/defaults/default_lseek_file.c     |   70 ++++++++++++++++++++
 cpukit/libfs/src/devfs/devfs_init.c                |    2 +-
 cpukit/libfs/src/dosfs/msdos.h                     |   12 ----
 cpukit/libfs/src/dosfs/msdos_dir.c                 |   32 ---------
 cpukit/libfs/src/dosfs/msdos_file.c                |   54 +---------------
 cpukit/libfs/src/dosfs/msdos_handlers_dir.c        |    2 +-
 cpukit/libfs/src/dosfs/msdos_handlers_file.c       |    2 +-
 cpukit/libfs/src/imfs/deviceio.c                   |   17 -----
 cpukit/libfs/src/imfs/imfs.h                       |   18 -----
 cpukit/libfs/src/imfs/imfs_directory.c             |   38 -----------
 cpukit/libfs/src/imfs/imfs_handlers_device.c       |    2 +-
 cpukit/libfs/src/imfs/imfs_handlers_directory.c    |    2 +-
 cpukit/libfs/src/imfs/imfs_handlers_memfile.c      |    2 +-
 cpukit/libfs/src/imfs/memfile.c                    |   35 +---------
 cpukit/libfs/src/nfsclient/src/nfs.c               |   58 +++-------------
 cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c         |   20 +-----
 cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c         |   39 +-----------
 cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c        |   29 ++++----
 testsuites/fstests/fsrdwr/init.c                   |    2 +-
 testsuites/psxtests/psximfs01/init.c               |   63 ++++++++---------
 25 files changed, 197 insertions(+), 425 deletions(-)

diff --git a/cpukit/libblock/src/blkdev-imfs.c b/cpukit/libblock/src/blkdev-imfs.c
index fe7a80c..8645593 100644
--- a/cpukit/libblock/src/blkdev-imfs.c
+++ b/cpukit/libblock/src/blkdev-imfs.c
@@ -206,7 +206,7 @@ static const rtems_filesystem_file_handlers_r rtems_blkdev_imfs_node = {
   .read_h = rtems_blkdev_imfs_read,
   .write_h = rtems_blkdev_imfs_write,
   .ioctl_h = rtems_blkdev_imfs_ioctl,
-  .lseek_h = rtems_filesystem_default_lseek_success,
+  .lseek_h = rtems_filesystem_default_lseek_file,
   .fstat_h = rtems_blkdev_imfs_fstat,
   .ftruncate_h = rtems_filesystem_default_ftruncate,
   .fsync_h = rtems_blkdev_imfs_fsync_or_fdatasync,
diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h
index 04ca52c..a740a40 100644
--- a/cpukit/libcsupport/include/rtems/libio.h
+++ b/cpukit/libcsupport/include/rtems/libio.h
@@ -849,8 +849,9 @@ typedef int (*rtems_filesystem_ioctl_t)(
  * @retval non-negative The new offset from the beginning of the file.
  * @retval -1 An error occured.  The errno is set to indicate the error.
  *
- * @see rtems_filesystem_default_lseek() and
- * rtems_filesystem_default_lseek_success().
+ * @see rtems_filesystem_default_lseek(),
+ * rtems_filesystem_default_lseek_file(), and
+ * rtems_filesystem_default_lseek_directory().
  */
 typedef off_t (*rtems_filesystem_lseek_t)(
   rtems_libio_t *iop,
@@ -1026,11 +1027,51 @@ off_t rtems_filesystem_default_lseek(
 );
 
 /**
+ * @brief An offset 0 with a whence of SEEK_SET will perform a directory rewind
+ * operation.
+ *
+ * This function has no protection against concurrent access.
+ *
+ * @retval -1 The offset is not zero or the whence is not SEEK_SET.
+ * @retval 0 Successful rewind operation.
+ *
+ * @see rtems_filesystem_lseek_t.
+ */
+off_t rtems_filesystem_default_lseek_directory(
+  rtems_libio_t *iop,
+  off_t offset,
+  int whence
+);
+
+/**
+ * @brief Default lseek() handler for files.
+ *
+ * The fstat() handler will be used to obtain the file size in case whence is
+ * SEEK_END.
+ *
+ * This function has no protection against concurrent access.
+ *
+ * @retval -1 An error occured.  In case an integer overflow occured, then the
+ * errno will be set to EOVERFLOW.  In case the new offset is negative, then
+ * the errno will be set to EINVAL.  In case the whence is SEEK_END and the
+ * fstat() handler to obtain the current file size returned an error status,
+ * then the errno will be set by the fstat() handler.
+ * @retval offset The new offset.
+ *
+ * @see rtems_filesystem_lseek_t.
+ */
+off_t rtems_filesystem_default_lseek_file(
+  rtems_libio_t *iop,
+  off_t offset,
+  int whence
+);
+
+/**
  * @retval 0 Always.
  *
  * @see rtems_filesystem_lseek_t.
  */
-off_t rtems_filesystem_default_lseek_success(
+off_t rtems_filesystem_default_lseek_file(
   rtems_libio_t *iop,
   off_t          offset,
   int            whence
@@ -1157,11 +1198,10 @@ extern const rtems_filesystem_limits_and_options_t
  * It will be indexed by 'fd'.
  *
  * @todo Should really have a separate per/file data structure that this points
- * to (eg: size, offset, driver, pathname should be in that)
+ * to (eg: offset, driver, pathname should be in that)
  */
 struct rtems_libio_tt {
   rtems_driver_name_t                    *driver;
-  off_t                                   size;      /* size of file */
   off_t                                   offset;    /* current offset into file */
   uint32_t                                flags;
   rtems_filesystem_location_info_t        pathinfo;
diff --git a/cpukit/libcsupport/src/lseek.c b/cpukit/libcsupport/src/lseek.c
index 7c1f76b..fa18db3 100644
--- a/cpukit/libcsupport/src/lseek.c
+++ b/cpukit/libcsupport/src/lseek.c
@@ -21,65 +21,13 @@
 
 off_t lseek( int fd, off_t offset, int whence )
 {
-  off_t rv = 0;
   rtems_libio_t *iop;
-  off_t reference_offset;
-  off_t old_offset;
-  off_t new_offset;
 
   rtems_libio_check_fd( fd );
   iop = rtems_libio_iop( fd );
   rtems_libio_check_is_open(iop);
 
-  old_offset = iop->offset;
-  switch ( whence ) {
-    case SEEK_SET:
-      reference_offset = 0;
-      break;
-    case SEEK_CUR:
-      reference_offset = old_offset;
-      break;
-    case SEEK_END:
-      reference_offset = iop->size;
-      break;
-    default:
-      errno = EINVAL;
-      rv = (off_t) -1;
-      break;
-  }
-  new_offset = reference_offset + offset;
-
-  if ( rv == 0 ) {
-    if (
-      (reference_offset >= 0 && new_offset >= offset)
-        || (reference_offset < 0 && new_offset <= offset)
-    ) {
-      switch ( rtems_filesystem_node_type( &iop->pathinfo ) ) {
-        case RTEMS_FILESYSTEM_DIRECTORY:
-        case RTEMS_FILESYSTEM_MEMORY_FILE:
-          if ( new_offset < 0 ) {
-            errno = EINVAL;
-            rv = (off_t) -1;
-          }
-          break;
-        default:
-          break;
-      }
-
-      if ( rv == 0 ) {
-        iop->offset = new_offset;
-        rv = (*iop->pathinfo.handlers->lseek_h)( iop, offset, whence );
-        if ( rv == (off_t) -1 ) {
-          iop->offset = old_offset;
-        }
-      }
-    } else {
-      errno = EOVERFLOW;
-      rv = (off_t) -1;
-    }
-  }
-
-  return rv;
+  return (*iop->pathinfo.handlers->lseek_h)( iop, offset, whence );
 }
 
 /*
diff --git a/cpukit/libfs/Makefile.am b/cpukit/libfs/Makefile.am
index c629bc9..f236704 100644
--- a/cpukit/libfs/Makefile.am
+++ b/cpukit/libfs/Makefile.am
@@ -23,7 +23,8 @@ libdefaultfs_a_SOURCES = \
     src/defaults/default_chown.c \
     src/defaults/default_fcntl.c src/defaults/default_fsmount.c \
     src/defaults/default_ftruncate.c src/defaults/default_lseek.c \
-    src/defaults/default_lseek_success.c \
+    src/defaults/default_lseek_file.c \
+    src/defaults/default_lseek_directory.c \
     src/defaults/default_readlink.c src/defaults/default_statvfs.c \
     src/defaults/default_utime.c \
     src/defaults/default_fstat.c \
diff --git a/cpukit/libfs/src/defaults/default_lseek_success.c b/cpukit/libfs/src/defaults/default_lseek_directory.c
similarity index 71%
rename from cpukit/libfs/src/defaults/default_lseek_success.c
rename to cpukit/libfs/src/defaults/default_lseek_directory.c
index d6a1cb4..e50eefd 100644
--- a/cpukit/libfs/src/defaults/default_lseek_success.c
+++ b/cpukit/libfs/src/defaults/default_lseek_directory.c
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
  *
@@ -19,11 +18,20 @@
 
 #include <rtems/libio_.h>
 
-off_t rtems_filesystem_default_lseek_success(
+off_t rtems_filesystem_default_lseek_directory(
   rtems_libio_t *iop,
   off_t offset,
   int whence
 )
 {
-  return 0;
+  off_t rv = 0;
+
+  if ( offset == 0 && whence == SEEK_SET ) {
+    iop->offset = 0;
+  } else {
+    errno = EINVAL;
+    rv = -1;
+  }
+
+  return rv;
 }
diff --git a/cpukit/libfs/src/defaults/default_lseek_file.c b/cpukit/libfs/src/defaults/default_lseek_file.c
new file mode 100644
index 0000000..9d80b2a
--- /dev/null
+++ b/cpukit/libfs/src/defaults/default_lseek_file.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+
+off_t rtems_filesystem_default_lseek_file(
+  rtems_libio_t *iop,
+  off_t offset,
+  int whence
+)
+{
+  off_t rv = 0;
+  off_t reference_offset;
+  off_t new_offset;
+  struct stat st;
+
+  switch ( whence ) {
+    case SEEK_SET:
+      reference_offset = 0;
+      break;
+    case SEEK_CUR:
+      reference_offset = iop->offset;
+      break;
+    case SEEK_END:
+      st.st_size = 0;
+      rv = (*iop->pathinfo.handlers->fstat_h)( &iop->pathinfo, &st );
+      reference_offset = st.st_size;
+      break;
+    default:
+      errno = EINVAL;
+      rv = -1;
+      break;
+  }
+  new_offset = reference_offset + offset;
+
+  if ( rv == 0 ) {
+    if (
+      (offset >= 0 && new_offset >= reference_offset)
+        || (offset < 0 && new_offset < reference_offset)
+    ) {
+      if ( new_offset >= 0 ) {
+        iop->offset = new_offset;
+        rv = new_offset;
+      } else {
+        errno = EINVAL;
+        rv = -1;
+      }
+    } else {
+      errno = EOVERFLOW;
+      rv = -1;
+    }
+  }
+
+  return rv;
+}
diff --git a/cpukit/libfs/src/devfs/devfs_init.c b/cpukit/libfs/src/devfs/devfs_init.c
index db856d2..154f1b9 100644
--- a/cpukit/libfs/src/devfs/devfs_init.c
+++ b/cpukit/libfs/src/devfs/devfs_init.c
@@ -42,7 +42,7 @@ const rtems_filesystem_file_handlers_r devFS_file_handlers = {
   .read_h = devFS_read,
   .write_h = devFS_write,
   .ioctl_h = devFS_ioctl,
-  .lseek_h = rtems_filesystem_default_lseek,
+  .lseek_h = rtems_filesystem_default_lseek_file,
   .fstat_h = devFS_stat,
   .ftruncate_h = rtems_filesystem_default_ftruncate,
   .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
diff --git a/cpukit/libfs/src/dosfs/msdos.h b/cpukit/libfs/src/dosfs/msdos.h
index 9bdfd88..a7aff1d 100644
--- a/cpukit/libfs/src/dosfs/msdos.h
+++ b/cpukit/libfs/src/dosfs/msdos.h
@@ -286,12 +286,6 @@ ssize_t msdos_file_write(
   size_t         count            /* IN  */
 );
 
-off_t msdos_file_lseek(
-  rtems_libio_t        *iop,              /* IN  */
-  off_t                 offset,           /* IN  */
-  int                   whence            /* IN  */
-);
-
 int msdos_file_stat(
   const rtems_filesystem_location_info_t *loc,
   struct stat *buf
@@ -322,12 +316,6 @@ ssize_t msdos_dir_read(
   size_t         count             /* IN  */
 );
 
-off_t msdos_dir_lseek(
-  rtems_libio_t        *iop,              /* IN  */
-  off_t                 offset,           /* IN  */
-  int                   whence            /* IN  */
-);
-
 int msdos_dir_sync(rtems_libio_t *iop);
 
 int msdos_dir_stat(
diff --git a/cpukit/libfs/src/dosfs/msdos_dir.c b/cpukit/libfs/src/dosfs/msdos_dir.c
index 67a0bda..be6b5a9 100644
--- a/cpukit/libfs/src/dosfs/msdos_dir.c
+++ b/cpukit/libfs/src/dosfs/msdos_dir.c
@@ -465,38 +465,6 @@ msdos_dir_read(rtems_libio_t *iop, void *buffer, size_t count)
  *     no write for directory
  */
 
-/* msdos_dir_lseek --
- *
- *  This routine will behave in one of three ways based on the state of
- *  argument whence. Based on the state of its value the offset argument will
- *  be interpreted using one of the following methods:
- *
- *     SEEK_SET - offset is the absolute byte offset from the start of the
- *                logical start of the dirent sequence that represents the
- *                directory
- *     SEEK_CUR - offset is used as the relative byte offset from the current
- *                directory position index held in the iop structure
- *     SEEK_END - N/A --> This will cause an assert.
- *
- * PARAMETERS:
- *     iop    - file control block
- *     offset - offset
- *     whence - predefine directive
- *
- * RETURNS:
- *     RC_OK on success, or -1 if error occured (errno
- *     set apropriately).
- */
-off_t
-msdos_dir_lseek(rtems_libio_t *iop, off_t offset, int whence)
-{
-    if (iop->offset >= 0 && iop->offset <= iop->size) {
-        return 0;
-    } else {
-        rtems_set_errno_and_return_minus_one(EINVAL);
-    }
-}
-
 /* msdos_dir_stat --
  *
  * This routine will obtain the following information concerning the current
diff --git a/cpukit/libfs/src/dosfs/msdos_file.c b/cpukit/libfs/src/dosfs/msdos_file.c
index 7cd55b0..c2db196 100644
--- a/cpukit/libfs/src/dosfs/msdos_file.c
+++ b/cpukit/libfs/src/dosfs/msdos_file.c
@@ -64,8 +64,6 @@ msdos_file_open(rtems_libio_t *iop, const char *pathname, int oflag,
     if (iop->flags & LIBIO_FLAGS_APPEND)
         iop->offset = fat_fd->fat_file_size;
 
-    iop->size = fat_fd->fat_file_size;
-
     rtems_semaphore_release(fs_info->vol_sema);
     return RC_OK;
 }
@@ -203,60 +201,10 @@ msdos_file_write(rtems_libio_t *iop,const void *buffer, size_t count)
     if (iop->offset + ret > fat_fd->fat_file_size)
         fat_fd->fat_file_size = iop->offset + ret;
 
-    iop->size = fat_fd->fat_file_size;
-
     rtems_semaphore_release(fs_info->vol_sema);
     return ret;
 }
 
-/* msdos_file_lseek --
- *     Process lseek call to the file: extend file if lseek is up to the end
- *     of the file.
- *
- * PARAMETERS:
- *     iop    - file control block
- *     offset - new offset
- *     whence - predefine directive
- *
- * RETURNS:
- *     new offset on success, or -1 if error occured (errno set
- *     appropriately).
- */
-off_t
-msdos_file_lseek(rtems_libio_t *iop, off_t offset, int whence)
-{
-    int                rc = RC_OK;
-    rtems_status_code  sc = RTEMS_SUCCESSFUL;
-    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
-    fat_file_fd_t     *fat_fd = iop->pathinfo.node_access;
-    uint32_t           real_size = 0;
-
-    if (iop->offset < 0 || iop->offset > UINT32_MAX) {
-        rtems_set_errno_and_return_minus_one(EINVAL);
-    }
-
-    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
-                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
-    if (sc != RTEMS_SUCCESSFUL)
-        rtems_set_errno_and_return_minus_one(EIO);
-
-    rc = fat_file_extend(iop->pathinfo.mt_entry, fat_fd, iop->offset,
-                         &real_size);
-    if (rc != RC_OK)
-    {
-        rtems_semaphore_release(fs_info->vol_sema);
-        return rc;
-    }
-
-    if (real_size > fat_fd->fat_file_size)
-        fat_fd->fat_file_size = iop->offset = real_size;
-
-    iop->size = fat_fd->fat_file_size;
-
-    rtems_semaphore_release(fs_info->vol_sema);
-    return iop->offset;
-}
-
 /* msdos_file_stat --
  *
  * PARAMETERS:
@@ -332,7 +280,7 @@ msdos_file_ftruncate(rtems_libio_t *iop, off_t length)
      * file size only if length < fat-file size
      */
     if (length < fat_fd->fat_file_size)
-        iop->size = fat_fd->fat_file_size = length;
+        fat_fd->fat_file_size = length;
 
     rtems_semaphore_release(fs_info->vol_sema);
     return RC_OK;
diff --git a/cpukit/libfs/src/dosfs/msdos_handlers_dir.c b/cpukit/libfs/src/dosfs/msdos_handlers_dir.c
index 193d796..eeaa77d 100644
--- a/cpukit/libfs/src/dosfs/msdos_handlers_dir.c
+++ b/cpukit/libfs/src/dosfs/msdos_handlers_dir.c
@@ -24,7 +24,7 @@ const rtems_filesystem_file_handlers_r msdos_dir_handlers = {
     msdos_dir_read,
     rtems_filesystem_default_write,
     rtems_filesystem_default_ioctl,
-    msdos_dir_lseek,
+    rtems_filesystem_default_lseek_directory,
     msdos_dir_stat,
     rtems_filesystem_default_ftruncate_directory,
     msdos_dir_sync,
diff --git a/cpukit/libfs/src/dosfs/msdos_handlers_file.c b/cpukit/libfs/src/dosfs/msdos_handlers_file.c
index fefb679..e68a09f 100644
--- a/cpukit/libfs/src/dosfs/msdos_handlers_file.c
+++ b/cpukit/libfs/src/dosfs/msdos_handlers_file.c
@@ -24,7 +24,7 @@ const rtems_filesystem_file_handlers_r msdos_file_handlers = {
     msdos_file_read,
     msdos_file_write,
     rtems_filesystem_default_ioctl,
-    msdos_file_lseek,
+    rtems_filesystem_default_lseek_file,
     msdos_file_stat,
     msdos_file_ftruncate,
     msdos_file_sync,
diff --git a/cpukit/libfs/src/imfs/deviceio.c b/cpukit/libfs/src/imfs/deviceio.c
index c4e7a92..f18c9e7 100644
--- a/cpukit/libfs/src/imfs/deviceio.c
+++ b/cpukit/libfs/src/imfs/deviceio.c
@@ -192,23 +192,6 @@ int device_ioctl(
 }
 
 /*
- *  device_lseek
- *
- *  This handler eats all lseek() operations and does not create
- *  an error. It assumes all devices can handle the seek. The
- *  writes fail.
- */
-
-off_t device_lseek(
-  rtems_libio_t *iop,
-  off_t          offset,
-  int            whence
-)
-{
-  return offset;
-}
-
-/*
  *  device_stat
  *
  *  The IMFS_stat() is used.
diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h
index dd7c158..daad052 100644
--- a/cpukit/libfs/src/imfs/imfs.h
+++ b/cpukit/libfs/src/imfs/imfs.h
@@ -418,12 +418,6 @@ extern ssize_t imfs_dir_read(
   size_t         count             /* IN  */
 );
 
-extern off_t imfs_dir_lseek(
-  rtems_libio_t        *iop,              /* IN  */
-  off_t                 offset,           /* IN  */
-  int                   whence            /* IN  */
-);
-
 extern int memfile_open(
   rtems_libio_t *iop,             /* IN  */
   const char    *pathname,        /* IN  */
@@ -449,12 +443,6 @@ extern int memfile_ioctl(
   void          *buffer           /* IN  */
 );
 
-extern off_t memfile_lseek(
-  rtems_libio_t        *iop,        /* IN  */
-  off_t                 offset,     /* IN  */
-  int                   whence      /* IN  */
-);
-
 extern int device_open(
   rtems_libio_t *iop,            /* IN  */
   const char    *pathname,       /* IN  */
@@ -484,12 +472,6 @@ extern int device_ioctl(
   void          *buffer             /* IN  */
 );
 
-extern off_t device_lseek(
-  rtems_libio_t *iop,               /* IN  */
-  off_t          offset,            /* IN  */
-  int            whence             /* IN  */
-);
-
 extern int device_ftruncate(
   rtems_libio_t *iop,               /* IN  */
   off_t          length             /* IN  */
diff --git a/cpukit/libfs/src/imfs/imfs_directory.c b/cpukit/libfs/src/imfs/imfs_directory.c
index c6be71f..f77b68b 100644
--- a/cpukit/libfs/src/imfs/imfs_directory.c
+++ b/cpukit/libfs/src/imfs/imfs_directory.c
@@ -99,41 +99,3 @@ ssize_t imfs_dir_read(
 
    return bytes_transferred;
 }
-
-/*
- *  imfs_dir_lseek
- *
- *  This routine will behave in one of three ways based on the state of
- *  argument whence. Based on the state of its value the offset argument will
- *  be interpreted using one of the following methods:
- *
- *     SEEK_SET - offset is the absolute byte offset from the start of the
- *                logical start of the dirent sequence that represents the
- *                directory
- *     SEEK_CUR - offset is used as the relative byte offset from the current
- *                directory position index held in the iop structure
- *     SEEK_END - N/A --> This will cause an EINVAL to be returned.
- */
-
-off_t imfs_dir_lseek(
-  rtems_libio_t  *iop,
-  off_t           offset,
-  int             whence
-)
-{
-  switch( whence ) {
-     case SEEK_SET:   /* absolute move from the start of the file */
-     case SEEK_CUR:   /* relative move */
-        iop->offset = (iop->offset/sizeof(struct dirent)) *
-              sizeof(struct dirent);
-        break;
-
-     case SEEK_END:   /* Movement past the end of the directory via lseek */
-                      /* is not a permitted operation                     */
-      default:
-        rtems_set_errno_and_return_minus_one( EINVAL );
-        break;
-  }
-
-  return 0;
-}
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_device.c b/cpukit/libfs/src/imfs/imfs_handlers_device.c
index dfbd894..fe3973d 100644
--- a/cpukit/libfs/src/imfs/imfs_handlers_device.c
+++ b/cpukit/libfs/src/imfs/imfs_handlers_device.c
@@ -36,7 +36,7 @@ static const rtems_filesystem_file_handlers_r IMFS_device_handlers = {
   device_read,
   device_write,
   device_ioctl,
-  device_lseek,
+  rtems_filesystem_default_lseek_file,
   IMFS_stat_device,
   device_ftruncate,
   rtems_filesystem_default_fsync_or_fdatasync,
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_directory.c b/cpukit/libfs/src/imfs/imfs_handlers_directory.c
index 9c3f774..579fdec 100644
--- a/cpukit/libfs/src/imfs/imfs_handlers_directory.c
+++ b/cpukit/libfs/src/imfs/imfs_handlers_directory.c
@@ -52,7 +52,7 @@ static const rtems_filesystem_file_handlers_r IMFS_directory_handlers = {
   imfs_dir_read,
   rtems_filesystem_default_write,
   rtems_filesystem_default_ioctl,
-  imfs_dir_lseek,
+  rtems_filesystem_default_lseek_directory,
   IMFS_stat_directory,
   rtems_filesystem_default_ftruncate_directory,
   rtems_filesystem_default_fsync_or_fdatasync_success,
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c
index 57d488a..262b93a 100644
--- a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c
+++ b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c
@@ -36,7 +36,7 @@ static const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = {
   memfile_read,
   memfile_write,
   memfile_ioctl,
-  memfile_lseek,
+  rtems_filesystem_default_lseek_file,
   IMFS_stat_file,
   memfile_ftruncate,
   rtems_filesystem_default_fsync_or_fdatasync_success,
diff --git a/cpukit/libfs/src/imfs/memfile.c b/cpukit/libfs/src/imfs/memfile.c
index d2cff01..64679df 100644
--- a/cpukit/libfs/src/imfs/memfile.c
+++ b/cpukit/libfs/src/imfs/memfile.c
@@ -109,7 +109,6 @@ int memfile_open(
   if (iop->flags & LIBIO_FLAGS_APPEND)
     iop->offset = the_jnode->info.file.size;
 
-  iop->size = the_jnode->info.file.size;
   return 0;
 }
 
@@ -148,7 +147,6 @@ ssize_t memfile_write(
   the_jnode = iop->pathinfo.node_access;
 
   status = IMFS_memfile_write( the_jnode, iop->offset, buffer, count );
-  iop->size = the_jnode->info.file.size;
 
   return status;
 }
@@ -170,34 +168,6 @@ int memfile_ioctl(
 }
 
 /*
- *  memfile_lseek
- *
- *  This routine processes the lseek() system call.
- */
-off_t memfile_lseek(
-  rtems_libio_t   *iop,
-  off_t            offset,
-  int              whence
-)
-{
-  IMFS_jnode_t   *the_jnode;
-
-  the_jnode = iop->pathinfo.node_access;
-
-  if (IMFS_type( the_jnode ) == IMFS_LINEAR_FILE) {
-    if (iop->offset > the_jnode->info.linearfile.size)
-      iop->offset = the_jnode->info.linearfile.size;
-  }
-  else {  /* Must be a block file (IMFS_MEMORY_FILE). */
-    if (IMFS_memfile_extend( the_jnode, iop->offset ))
-      rtems_set_errno_and_return_minus_one( ENOSPC );
-
-    iop->size = the_jnode->info.file.size;
-  }
-  return iop->offset;
-}
-
-/*
  *  memfile_stat
  *
  *  This IMFS_stat() can be used.
@@ -232,7 +202,6 @@ int memfile_ftruncate(
    *  future use and just set the length.
    */
   the_jnode->info.file.size = length;
-  iop->size = the_jnode->info.file.size;
 
   IMFS_update_atime( the_jnode );
 
@@ -265,7 +234,7 @@ MEMFILE_STATIC int IMFS_memfile_extend(
    *  Verify new file size is supported
    */
   if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
-    rtems_set_errno_and_return_minus_one( EINVAL );
+    rtems_set_errno_and_return_minus_one( EFBIG );
 
   /*
    *  Verify new file size is actually larger than current size
@@ -654,7 +623,7 @@ MEMFILE_STATIC ssize_t IMFS_memfile_write(
   if ( last_byte > the_jnode->info.file.size ) {
     status = IMFS_memfile_extend( the_jnode, last_byte );
     if ( status )
-      rtems_set_errno_and_return_minus_one( ENOSPC );
+      return status;
   }
 
   copied = 0;
diff --git a/cpukit/libfs/src/nfsclient/src/nfs.c b/cpukit/libfs/src/nfsclient/src/nfs.c
index 15b6def..09a9278 100644
--- a/cpukit/libfs/src/nfsclient/src/nfs.c
+++ b/cpukit/libfs/src/nfsclient/src/nfs.c
@@ -2424,63 +2424,25 @@ int			e;
 	return count;
 }
 
-static off_t nfs_file_lseek(
-	rtems_libio_t *iop,
-	off_t          length,
-	int            whence
-)
-{
-#if DEBUG & DEBUG_SYSCALLS
-	fprintf(stderr,
-			"lseek to %i (length %i, whence %i)\n",
-			iop->offset,
-			length,
-			whence);
-#endif
-	if ( SEEK_END == whence ) {
-		/* rtems (4.6.2) libcsupport code 'lseek' uses iop->size to
-		 * compute the offset. We don't want to track the file size
-	 	 * by updating 'iop->size' constantly.
-		 * Since lseek is the only place using iop->size, we work
-		 * around this by tweaking the offset here...
-		 */
-		NfsNode	node = iop->pathinfo.node_access;
-		fattr	*fa  = &SERP_ATTR(node);
-
-		if (updateAttr(node, 0 /* only if old */)) {
-			return -1;
-		}
-		iop->offset = fa->size;
-	}
-
-	/* this is particularly easy :-) */
-	return iop->offset;
-}
-
 static off_t nfs_dir_lseek(
 	rtems_libio_t *iop,
 	off_t          length,
 	int            whence
 )
 {
-DirInfo di = iop->pathinfo.node_access_2;
+	off_t rv = rtems_filesystem_default_lseek_directory(iop, length, whence);
 
-	/* we don't support anything other than
-	 * rewinding
-	 */
-	if (SEEK_SET != whence || 0 != length) {
-		errno = ENOTSUP;
-		return -1;
-	}
+	if (rv == 0) {
+		DirInfo di = iop->pathinfo.node_access_2;
+		nfscookie *cookie = &di->readdirargs.cookie;
 
-	/* rewind cookie */
-	memset( &di->readdirargs.cookie,
-	        0,
-	        sizeof(di->readdirargs.cookie) );
+		di->eofreached = FALSE;
 
-	di->eofreached = FALSE;
+		/* rewind cookie */
+		memset(cookie, 0, sizeof(*cookie));
+	}
 
-	return iop->offset;
+	return rv;
 }
 
 #if 0	/* structure types for reference */
@@ -2703,7 +2665,7 @@ struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers = {
 	.read_h      = nfs_file_read,
 	.write_h     = nfs_file_write,
 	.ioctl_h     = rtems_filesystem_default_ioctl,
-	.lseek_h     = nfs_file_lseek,
+	.lseek_h     = rtems_filesystem_default_lseek_file,
 	.fstat_h     = nfs_fstat,
 	.ftruncate_h = nfs_file_ftruncate,
 	.fsync_h     = rtems_filesystem_default_fsync_or_fdatasync,
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c
index d66e429..0325885 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dev.c
@@ -214,24 +214,6 @@ rtems_rfs_rtems_device_ioctl (rtems_libio_t* iop,
 }
 
 /**
- * This handler eats all lseek() operations and does not create an error. It
- * assumes all devices can handle the seek. The writes fail.
- *
- * @param iop
- * @param offset
- * @param whence
- * @return off_t
- */
-
-static off_t
-rtems_rfs_rtems_device_lseek (rtems_libio_t* iop,
-                              off_t          offset,
-                              int            whence)
-{
-  return offset;
-}
-
-/**
  * The consumes the truncate call. You cannot truncate device files.
  *
  * @param iop
@@ -255,7 +237,7 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_device_handlers = {
   .read_h      = rtems_rfs_rtems_device_read,
   .write_h     = rtems_rfs_rtems_device_write,
   .ioctl_h     = rtems_rfs_rtems_device_ioctl,
-  .lseek_h     = rtems_rfs_rtems_device_lseek,
+  .lseek_h     = rtems_filesystem_default_lseek_file,
   .fstat_h     = rtems_rfs_rtems_fstat,
   .ftruncate_h = rtems_rfs_rtems_device_ftruncate,
   .fsync_h     = rtems_filesystem_default_fsync_or_fdatasync,
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c
index 550973d..88f71e5 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c
@@ -150,43 +150,6 @@ rtems_rfs_rtems_dir_read (rtems_libio_t* iop,
   return bytes_transferred;
 }
 
-/**
- * This routine will behave in one of three ways based on the state of argument
- * whence. Based on the state of its value the offset argument will be
- * interpreted using one of the following methods:
- *
- *   SEEK_SET - offset is the absolute byte offset from the start of the
- *              logical start of the dirent sequence that represents the
- *              directory
- *   SEEK_CUR - offset is used as the relative byte offset from the current
- *              directory position index held in the iop structure
- *   SEEK_END - N/A --> This will cause an assert.
- *
- * @param iop
- * @param offset
- * @param whence
- * return off_t
- */
-static off_t
-rtems_rfs_rtems_dir_lseek (rtems_libio_t* iop,
-                           off_t          offset,
-                           int            whence)
-{
-  switch (whence)
-  {
-    case SEEK_SET:   /* absolute move from the start of the file */
-    case SEEK_CUR:   /* relative move */
-      break;
-
-     case SEEK_END:   /* Movement past the end of the directory via lseek */
-                      /* is not a permitted operation                     */
-    default:
-      return rtems_rfs_rtems_error ("dir_lseek: bad whence", EINVAL);
-      break;
-  }
-  return 0;
-}
-
 /*
  *  Set of operations handlers for operations on directories.
  */
@@ -197,7 +160,7 @@ const rtems_filesystem_file_handlers_r rtems_rfs_rtems_dir_handlers = {
   .read_h      = rtems_rfs_rtems_dir_read,
   .write_h     = rtems_filesystem_default_write,
   .ioctl_h     = rtems_filesystem_default_ioctl,
-  .lseek_h     = rtems_rfs_rtems_dir_lseek,
+  .lseek_h     = rtems_filesystem_default_lseek_directory,
   .fstat_h     = rtems_rfs_rtems_fstat,
   .ftruncate_h = rtems_filesystem_default_ftruncate_directory,
   .fsync_h     = rtems_filesystem_default_fsync_or_fdatasync,
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c
index 0a15652..b2ff45d 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c
@@ -72,7 +72,6 @@ rtems_rfs_rtems_file_open (rtems_libio_t* iop,
   if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN))
     printf("rtems-rfs: file-open: handle:%p\n", file);
 
-  iop->size = rtems_rfs_file_size (file);
   rtems_rfs_rtems_set_iop_file_handle (iop, file);
 
   rtems_rfs_rtems_unlock (fs);
@@ -245,8 +244,6 @@ rtems_rfs_rtems_file_write (rtems_libio_t* iop,
     }
   }
 
-  iop->size = rtems_rfs_file_size (file);
-
   rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
 
   return write;
@@ -282,26 +279,32 @@ rtems_rfs_rtems_file_lseek (rtems_libio_t* iop,
                             int            whence)
 {
   rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
-  rtems_rfs_pos          pos;
-  int                    rc;
+  off_t                  old_offset;
+  off_t                  new_offset;
 
   if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_LSEEK))
     printf("rtems-rfs: file-lseek: handle:%p offset:%" PRIdoff_t "\n", file, offset);
 
   rtems_rfs_rtems_lock (rtems_rfs_file_fs (file));
 
-  pos = iop->offset;
-
-  rc = rtems_rfs_file_seek (file, pos, &pos);
-  if (rc)
+  old_offset = iop->offset;
+  new_offset = rtems_filesystem_default_lseek_file (iop, offset, whence);
+  if (new_offset != -1)
   {
-    rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
-    return rtems_rfs_rtems_error ("file_lseek: lseek", rc);
+    rtems_rfs_pos pos = iop->offset;
+    int           rc = rtems_rfs_file_seek (file, pos, &pos);
+
+    if (rc)
+    {
+      rtems_rfs_rtems_error ("file_lseek: lseek", rc);
+      iop->offset = old_offset;
+      new_offset = -1;
+    }
   }
 
   rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
 
-  return iop->offset;
+  return new_offset;
 }
 
 /**
@@ -327,8 +330,6 @@ rtems_rfs_rtems_file_ftruncate (rtems_libio_t* iop,
   if (rc)
     rc = rtems_rfs_rtems_error ("file_ftruncate: set size", rc);
 
-  iop->size = rtems_rfs_file_size (file);
-
   rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
 
   return rc;
diff --git a/testsuites/fstests/fsrdwr/init.c b/testsuites/fstests/fsrdwr/init.c
index ef2b02a..8b40f07 100644
--- a/testsuites/fstests/fsrdwr/init.c
+++ b/testsuites/fstests/fsrdwr/init.c
@@ -371,7 +371,7 @@ lseek_test (void)
    */
   status = fstat (fd, &statbuf);
   rtems_test_assert (status == 0);
-  rtems_test_assert (statbuf.st_size == total_written + 1);
+  rtems_test_assert (statbuf.st_size == total_written);
 
   status = ftruncate (fd, total_written);
   rtems_test_assert (status == 0);
diff --git a/testsuites/psxtests/psximfs01/init.c b/testsuites/psxtests/psximfs01/init.c
index c567eee..88796ba 100644
--- a/testsuites/psxtests/psximfs01/init.c
+++ b/testsuites/psxtests/psximfs01/init.c
@@ -56,7 +56,7 @@ void write_helper(void)
   do {
     written = write( TestFd, Buffer, sizeof(Buffer) );
     if ( written == -1 ) {
-      if ( errno == ENOSPC ) {
+      if ( errno == EFBIG ) {
         printf( "Total written = %zd\n", TotalWritten );
         return;
       }
@@ -93,22 +93,21 @@ void read_helper(void)
         rtems_test_exit(0);
       }
       i++;
-      continue;
-    }
-    /* Unsure if ENOSPC is the write error to be returned */
-    if ( errno == ENOSPC && i == TotalWritten ) {
-      puts( "File correctly read until ENOSPC returned\n" );
-      return;
+    } else if ( sc != 0 ) {
+      fprintf(
+        stderr,
+        "ERROR - at offset %d - returned %zd and error=%s\n",
+        i,
+        sc,
+        strerror( errno )
+      );
+      rtems_test_exit(0);
     }
-    fprintf(
-      stderr,
-      "ERROR - at offset %d - returned %zd and error=%s\n",
-      i,
-      sc,
-      strerror( errno )
-    );
-    rtems_test_exit(0);
-  } while (1);
+  } while ( sc > 0 );
+
+  if ( i == TotalWritten ) {
+    puts( "File correctly read until EOF returned\n" );
+  }
 }
 
 void truncate_helper(void)
@@ -143,7 +142,7 @@ void truncate_helper(void)
   } while (new > 0);
 }
 
-void extend_helper(void)
+void extend_helper(int eno)
 {
   off_t position;
   off_t new;
@@ -164,18 +163,11 @@ void extend_helper(void)
   new = position;
   do {
     sc = lseek( TestFd, new, SEEK_SET );
-    if( sc == -1 ) {
-      if( errno == ENOSPC ) {
-	break;
-      }
-      else {
-	rtems_test_assert( 0 );
-      }
-    }
+    rtems_test_assert( sc == new );
 
     rc = ftruncate( TestFd, new );
     if ( rc != 0 ) {
-      if( errno != ENOSPC ) {
+      if( errno != eno ) {
 	fprintf(
 	  stderr,
 	  "ERROR - at offset %d - returned %d and error=%s\n",
@@ -218,8 +210,10 @@ rtems_task Init(
 {
   int i;
   void *alloc_ptr = (void *)0;
-  int position = 0;
-  int status = 0;
+  off_t position;
+  off_t new_position;
+  char buf [1];
+  ssize_t n;
 
   puts( "\n\n*** TEST IMFS 01 ***" );
 
@@ -244,18 +238,21 @@ rtems_task Init(
    */
   alloc_ptr = malloc( malloc_free_space() - 4 );
 
-  extend_helper();
+  extend_helper(ENOSPC);
 
   /* 
    * free the allocated heap memory
    */
   free(alloc_ptr);
 
-  extend_helper();
+  extend_helper(EFBIG);
   position = lseek( TestFd , 0, SEEK_END );
-  status = lseek( TestFd, position+2, SEEK_SET );
-  rtems_test_assert( status == -1 );
-  rtems_test_assert( errno == ENOSPC );
+  new_position = lseek( TestFd, position + 2, SEEK_SET );
+  rtems_test_assert( new_position == position + 2 );
+
+  n = write( TestFd, buf, sizeof(buf) );
+  rtems_test_assert( n == -1 );
+  rtems_test_assert( errno == EFBIG );
 
   close_it();
   unlink_it();




More information about the vc mailing list