[rtems commit] Filesystem: PR1871: Fix O_APPEND

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


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

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

Filesystem: PR1871: Fix O_APPEND

---

 cpukit/libfs/src/dosfs/msdos.h               |   16 ------
 cpukit/libfs/src/dosfs/msdos_dir.c           |   64 --------------------------
 cpukit/libfs/src/dosfs/msdos_file.c          |   46 +-----------------
 cpukit/libfs/src/dosfs/msdos_handlers_dir.c  |    4 +-
 cpukit/libfs/src/dosfs/msdos_handlers_file.c |    2 +-
 cpukit/libfs/src/imfs/memfile.c              |    7 ++-
 cpukit/libfs/src/rfs/rtems-rfs-file.c        |    2 +-
 cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c  |   35 +++++++++-----
 testsuites/fstests/fsrdwr/init.c             |   10 ++++-
 9 files changed, 42 insertions(+), 144 deletions(-)

diff --git a/cpukit/libfs/src/dosfs/msdos.h b/cpukit/libfs/src/dosfs/msdos.h
index a7aff1d..0696b8f 100644
--- a/cpukit/libfs/src/dosfs/msdos.h
+++ b/cpukit/libfs/src/dosfs/msdos.h
@@ -265,13 +265,6 @@ int msdos_initialize_support(
   const rtems_filesystem_file_handlers_r  *directory_handlers
 );
 
-int msdos_file_open(
-  rtems_libio_t *iop,             /* IN  */
-  const char    *pathname,        /* IN  */
-  int            oflag,           /* IN  */
-  mode_t         mode             /* IN  */
-);
-
 int msdos_file_close(rtems_libio_t *iop /* IN  */);
 
 ssize_t msdos_file_read(
@@ -301,15 +294,6 @@ int msdos_file_sync(rtems_libio_t *iop);
 
 int msdos_file_datasync(rtems_libio_t *iop);
 
-int msdos_dir_open(
-  rtems_libio_t *iop,             /* IN  */
-  const char    *pathname,        /* IN  */
-  int            oflag,           /* IN  */
-  mode_t         mode             /* IN  */
-);
-
-int msdos_dir_close(rtems_libio_t *iop /* IN  */);
-
 ssize_t msdos_dir_read(
   rtems_libio_t *iop,              /* IN  */
   void          *buffer,           /* IN  */
diff --git a/cpukit/libfs/src/dosfs/msdos_dir.c b/cpukit/libfs/src/dosfs/msdos_dir.c
index be6b5a9..38ea667 100644
--- a/cpukit/libfs/src/dosfs/msdos_dir.c
+++ b/cpukit/libfs/src/dosfs/msdos_dir.c
@@ -30,70 +30,6 @@
 
 #include "msdos.h"
 
-/* msdos_dir_open --
- *     Open fat-file which correspondes to the directory being opened and
- *     set offset field of file control block to zero.
- */
-int
-msdos_dir_open(rtems_libio_t *iop, const char *pathname, int oflag,
-               mode_t mode)
-{
-    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;
-
-    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_reopen(fat_fd);
-    if (rc != RC_OK)
-    {
-        rtems_semaphore_release(fs_info->vol_sema);
-        return rc;
-    }
-
-    iop->offset = 0;
-    rtems_semaphore_release(fs_info->vol_sema);
-    return RC_OK;
-}
-
-/* msdos_dir_close --
- *     Close  fat-file which correspondes to the directory being closed
- *
- * PARAMETERS:
- *     iop - file control block
- *
- * RETURNS:
- *     RC_OK, if directory closed successfully, or -1 if error occured (errno
- *     set apropriately.
- */
-int
-msdos_dir_close(rtems_libio_t *iop)
-{
-    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;
-
-    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_close(iop->pathinfo.mt_entry, fat_fd);
-    if (rc != RC_OK)
-    {
-        rtems_semaphore_release(fs_info->vol_sema);
-        return rc;
-    }
-
-    rtems_semaphore_release(fs_info->vol_sema);
-    return RC_OK;
-}
-
 /*  msdos_format_dirent_with_dot --
  *      This routine convert a (short) MSDOS filename as present on disk
  *      (fixed 8+3 characters, filled with blanks, without separator dot)
diff --git a/cpukit/libfs/src/dosfs/msdos_file.c b/cpukit/libfs/src/dosfs/msdos_file.c
index c2db196..6eb9b79 100644
--- a/cpukit/libfs/src/dosfs/msdos_file.c
+++ b/cpukit/libfs/src/dosfs/msdos_file.c
@@ -27,47 +27,6 @@
 
 #include "msdos.h"
 
-/* msdos_file_open --
- *     Open fat-file which correspondes to the file
- *
- * PARAMETERS:
- *     iop        - file control block
- *     pathname   - name
- *     flag       - flags
- *     mode       - mode
- *
- * RETURNS:
- *     RC_OK, if file opened successfully, or -1 if error occured
- *     and errno set appropriately
- */
-int
-msdos_file_open(rtems_libio_t *iop, const char *pathname, int oflag,
-                mode_t mode)
-{
-    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;
-
-    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_reopen(fat_fd);
-    if (rc != RC_OK)
-    {
-        rtems_semaphore_release(fs_info->vol_sema);
-        return rc;
-    }
-
-    if (iop->flags & LIBIO_FLAGS_APPEND)
-        iop->offset = fat_fd->fat_file_size;
-
-    rtems_semaphore_release(fs_info->vol_sema);
-    return RC_OK;
-}
-
 /* msdos_file_close --
  *     Close fat-file which correspondes to the file. If fat-file descriptor
  *     which correspondes to the file is not marked "removed", synchronize
@@ -121,8 +80,6 @@ msdos_file_close(rtems_libio_t *iop)
         }
     }
 
-    rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd);
-
     rtems_semaphore_release(fs_info->vol_sema);
     return rc;
 }
@@ -186,6 +143,9 @@ msdos_file_write(rtems_libio_t *iop,const void *buffer, size_t count)
     if (sc != RTEMS_SUCCESSFUL)
         rtems_set_errno_and_return_minus_one(EIO);
 
+    if ((iop->flags & LIBIO_FLAGS_APPEND) != 0)
+        iop->offset = fat_fd->fat_file_size;
+
     ret = fat_file_write(iop->pathinfo.mt_entry, fat_fd, iop->offset, count,
                          buffer);
     if (ret < 0)
diff --git a/cpukit/libfs/src/dosfs/msdos_handlers_dir.c b/cpukit/libfs/src/dosfs/msdos_handlers_dir.c
index eeaa77d..8c7dcdc 100644
--- a/cpukit/libfs/src/dosfs/msdos_handlers_dir.c
+++ b/cpukit/libfs/src/dosfs/msdos_handlers_dir.c
@@ -19,8 +19,8 @@
 #include "msdos.h"
 
 const rtems_filesystem_file_handlers_r msdos_dir_handlers = {
-    msdos_dir_open,
-    msdos_dir_close,
+    rtems_filesystem_default_open,
+    rtems_filesystem_default_close,
     msdos_dir_read,
     rtems_filesystem_default_write,
     rtems_filesystem_default_ioctl,
diff --git a/cpukit/libfs/src/dosfs/msdos_handlers_file.c b/cpukit/libfs/src/dosfs/msdos_handlers_file.c
index e68a09f..12cdaa0 100644
--- a/cpukit/libfs/src/dosfs/msdos_handlers_file.c
+++ b/cpukit/libfs/src/dosfs/msdos_handlers_file.c
@@ -19,7 +19,7 @@
 #include "msdos.h"
 
 const rtems_filesystem_file_handlers_r msdos_file_handlers = {
-    msdos_file_open,
+    rtems_filesystem_default_open,
     msdos_file_close,
     msdos_file_read,
     msdos_file_write,
diff --git a/cpukit/libfs/src/imfs/memfile.c b/cpukit/libfs/src/imfs/memfile.c
index 64679df..d836172 100644
--- a/cpukit/libfs/src/imfs/memfile.c
+++ b/cpukit/libfs/src/imfs/memfile.c
@@ -92,7 +92,7 @@ int memfile_open(
   /*
    * Perform 'copy on write' for linear files
    */
-  if ((iop->flags & (LIBIO_FLAGS_WRITE | LIBIO_FLAGS_APPEND))
+  if ((iop->flags & LIBIO_FLAGS_WRITE)
    && (IMFS_type( the_jnode ) == IMFS_LINEAR_FILE)) {
     uint32_t   count = the_jnode->info.linearfile.size;
     const unsigned char *buffer = the_jnode->info.linearfile.direct;
@@ -106,8 +106,6 @@ int memfile_open(
      && (IMFS_memfile_write(the_jnode, 0, buffer, count) == -1))
         return -1;
   }
-  if (iop->flags & LIBIO_FLAGS_APPEND)
-    iop->offset = the_jnode->info.file.size;
 
   return 0;
 }
@@ -146,6 +144,9 @@ ssize_t memfile_write(
 
   the_jnode = iop->pathinfo.node_access;
 
+  if ((iop->flags & LIBIO_FLAGS_APPEND) != 0)
+    iop->offset = the_jnode->info.file.size;
+
   status = IMFS_memfile_write( the_jnode, iop->offset, buffer, count );
 
   return status;
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-file.c b/cpukit/libfs/src/rfs/rtems-rfs-file.c
index abd123d..ab195fa 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-file.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-file.c
@@ -422,7 +422,7 @@ rtems_rfs_file_seek (rtems_rfs_file_handle* handle,
    * This means the file needs to set the file size to the pos only when a
    * write occurs.
    */
-  if (pos < rtems_rfs_file_shared_get_size (rtems_rfs_file_fs (handle),
+  if (pos <= rtems_rfs_file_shared_get_size (rtems_rfs_file_fs (handle),
                                             handle->shared))
   {
     rtems_rfs_file_set_bpos (handle, pos);
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c
index b2ff45d..1b8b0d4 100644
--- a/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c
+++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c
@@ -185,6 +185,7 @@ rtems_rfs_rtems_file_write (rtems_libio_t* iop,
 {
   rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
   rtems_rfs_pos          pos;
+  rtems_rfs_pos          file_size;
   const uint8_t*         data = buffer;
   ssize_t                write = 0;
   int                    rc;
@@ -195,26 +196,34 @@ rtems_rfs_rtems_file_write (rtems_libio_t* iop,
   rtems_rfs_rtems_lock (rtems_rfs_file_fs (file));
 
   pos = iop->offset;
-
-  /*
-   * If the iop position is past the physical end of the file we need to set
-   * the file size to the new length before writing. If the position equals the
-   * size of file we are still past the end of the file as positions number
-   * from 0. For a specific position we need a file that has a length of one
-   * more.
-   */
-
-  if (pos >= rtems_rfs_file_size (file))
+  file_size = rtems_rfs_file_size (file);
+  if (pos > file_size)
   {
-    rc = rtems_rfs_file_set_size (file, pos + 1);
+    /*
+     * If the iop position is past the physical end of the file we need to set
+     * the file size to the new length before writing.  The
+     * rtems_rfs_file_io_end() will grow the file subsequently.
+     */
+    rc = rtems_rfs_file_set_size (file, pos);
     if (rc)
     {
       rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
       return rtems_rfs_rtems_error ("file-write: write extend", rc);
     }
-  }
 
-  rtems_rfs_file_set_bpos (file, pos);
+    rtems_rfs_file_set_bpos (file, pos);
+  }
+  else if (pos < file_size && (iop->flags & LIBIO_FLAGS_APPEND) != 0)
+  {
+    pos = file_size;
+    rc = rtems_rfs_file_seek (file, pos, &pos);
+    if (rc)
+    {
+      rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
+      return rtems_rfs_rtems_error ("file-write: write append seek", rc);
+    }
+    iop->offset = pos;
+  }
 
   while (count)
   {
diff --git a/testsuites/fstests/fsrdwr/init.c b/testsuites/fstests/fsrdwr/init.c
index 8b40f07..bfaa8ab 100644
--- a/testsuites/fstests/fsrdwr/init.c
+++ b/testsuites/fstests/fsrdwr/init.c
@@ -112,6 +112,12 @@ read_write_test (void)
   rtems_test_assert (n == len);
   pos = lseek (fd, 0, SEEK_CUR);
   rtems_test_assert (pos == 2 * len);
+  pos = lseek (fd, 0, SEEK_SET);
+  rtems_test_assert (pos == 0);
+  n = write (fd, databuf, len);
+  rtems_test_assert (n == len);
+  pos = lseek (fd, 0, SEEK_CUR);
+  rtems_test_assert (pos == 3 * len);
   status = close (fd);
   rtems_test_assert (status == 0);
 
@@ -123,7 +129,9 @@ read_write_test (void)
   n = read (fd, readbuf, len);
   rtems_test_assert (n == len);
   rtems_test_assert (!strncmp (databuf, readbuf, len));
-
+  n = read (fd, readbuf, len);
+  rtems_test_assert (n == len);
+  rtems_test_assert (!strncmp (databuf, readbuf, len));
   n = read (fd, readbuf, len);
   rtems_test_assert (n == len);
   rtems_test_assert (!strncmp (databuf, readbuf, len));




More information about the vc mailing list