summaryrefslogtreecommitdiffstats
path: root/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c')
-rw-r--r--cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c b/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c
new file mode 100644
index 0000000000..2f2df428dd
--- /dev/null
+++ b/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c
@@ -0,0 +1,354 @@
+/*
+ * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
+ *
+ * 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.
+ *
+ * $Id$
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems-rfs
+ *
+ * RTEMS RFS File Handlers
+ *
+ * This file contains the set of handlers used to process operations on
+ * RFS file nodes.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+
+#include <rtems/rfs/rtems-rfs-file.h>
+#include "rtems-rfs-rtems.h"
+
+/**
+ * This routine processes the open() system call. Note that there is nothing
+ * special to be done at open() time.
+ *
+ * @param iop
+ * @param pathname
+ * @param flag
+ * @param mode
+ * @return int
+ */
+
+static int
+rtems_rfs_rtems_file_open (rtems_libio_t* iop,
+ const char* pathname,
+ uint32_t flag,
+ uint32_t mode)
+{
+ rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo);
+ rtems_rfs_ino ino;
+ rtems_rfs_file_handle* file;
+ uint32_t flags;
+ int rc;
+
+ flags = 0;
+
+ if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN))
+ printf("rtems-rfs: file-open: path:%s ino:%" PRId32 " flags:%04" PRIx32 " mode:%04" PRIx32 "\n",
+ pathname, ino, flags, mode);
+
+ rtems_rfs_rtems_lock (fs);
+
+ ino = rtems_rfs_rtems_get_iop_ino (iop);
+
+ rc = rtems_rfs_file_open (fs, ino, flags, &file);
+ if (rc > 0)
+ {
+ rtems_rfs_rtems_unlock (fs);
+ return rtems_rfs_rtems_error ("file-open: open", rc);
+ }
+
+ 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);
+ return 0;
+}
+
+/**
+ * This routine processes the close() system call. Note that there is nothing
+ * to flush at this point.
+ *
+ * @param iop
+ * @return int
+ */
+static int
+rtems_rfs_rtems_file_close (rtems_libio_t* iop)
+{
+ rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
+ rtems_rfs_file_system* fs = rtems_rfs_file_fs (file);
+ int rc;
+
+ if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_CLOSE))
+ printf("rtems-rfs: file-close: handle:%p\n", file);
+
+ rtems_rfs_rtems_lock (fs);
+
+ rc = rtems_rfs_file_close (fs, file);
+ if (rc > 0)
+ rc = rtems_rfs_rtems_error ("file-close: file close", rc);
+
+ rtems_rfs_rtems_unlock (fs);
+ return rc;
+}
+
+/**
+ * This routine processes the read() system call.
+ *
+ * @param iop
+ * @param buffer
+ * @param count
+ * @return int
+ */
+static ssize_t
+rtems_rfs_rtems_file_read (rtems_libio_t* iop,
+ void* buffer,
+ size_t count)
+{
+ rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
+ rtems_rfs_pos pos;
+ uint8_t* data = buffer;
+ ssize_t read = 0;
+ int rc;
+
+ if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_READ))
+ printf("rtems-rfs: file-read: handle:%p count:%zd\n", file, count);
+
+ rtems_rfs_rtems_lock (rtems_rfs_file_fs (file));
+
+ pos = iop->offset;
+
+ if (pos < rtems_rfs_file_size (file))
+ {
+ while (count)
+ {
+ size_t size;
+
+ rc = rtems_rfs_file_io_start (file, &size, true);
+ if (rc > 0)
+ {
+ read = rtems_rfs_rtems_error ("file-read: read: io-start", rc);
+ break;
+ }
+
+ if (size == 0)
+ break;
+
+ if (size > count)
+ size = count;
+
+ memcpy (data, rtems_rfs_file_data (file), size);
+
+ data += size;
+ count -= size;
+ read += size;
+
+ rc = rtems_rfs_file_io_end (file, size, true);
+ if (rc > 0)
+ {
+ read = rtems_rfs_rtems_error ("file-read: read: io-end", rc);
+ break;
+ }
+ }
+ }
+
+ rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
+
+ return read;
+}
+
+/**
+ * This routine processes the write() system call.
+ *
+ * @param iop
+ * @param buffer
+ * @param count
+ * @return ssize_t
+ */
+static ssize_t
+rtems_rfs_rtems_file_write (rtems_libio_t* iop,
+ const void* buffer,
+ size_t count)
+{
+ rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
+ rtems_rfs_pos pos;
+ const uint8_t* data = buffer;
+ ssize_t write = 0;
+ int rc;
+
+ if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_WRITE))
+ printf("rtems-rfs: file-write: handle:%p count:%zd\n", file, count);
+
+ 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))
+ {
+ rc = rtems_rfs_file_set_size (file, pos + 1);
+ 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);
+
+ while (count)
+ {
+ size_t size = count;
+
+ rc = rtems_rfs_file_io_start (file, &size, false);
+ if (rc)
+ {
+ write = rtems_rfs_rtems_error ("file-write: write open", rc);
+ break;
+ }
+
+ if (size > count)
+ size = count;
+
+ memcpy (rtems_rfs_file_data (file), data, size);
+
+ data += size;
+ count -= size;
+ write += size;
+
+ rc = rtems_rfs_file_io_end (file, size, false);
+ if (rc)
+ {
+ write = rtems_rfs_rtems_error ("file-write: write close", rc);
+ break;
+ }
+ }
+
+ iop->size = rtems_rfs_file_size (file);
+
+ rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
+
+ return write;
+}
+
+/**
+ * This routine processes the ioctl() system call.
+ *
+ * @note No ioctl()'s are currently supported for RFS files.
+ *
+ * @param iop
+ * @param command
+ * @param buffer
+ */
+
+static int
+rtems_rfs_rtems_file_ioctl (rtems_libio_t* iop, uint32_t command, void* buffer)
+{
+ return 0;
+}
+
+/**
+ * This routine processes the lseek() system call.
+ *
+ * @param iop
+ * @param offset
+ * @param whence
+ * @return rtems_off64_t
+ */
+static rtems_off64_t
+rtems_rfs_rtems_file_lseek (rtems_libio_t* iop,
+ rtems_off64_t offset,
+ int whence)
+{
+ rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
+ rtems_rfs_pos pos;
+ int rc;
+
+ if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_LSEEK))
+ printf("rtems-rfs: file-lseek: handle:%p offset:%Ld\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)
+ {
+ rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
+ return rtems_rfs_rtems_error ("file_lseek: lseek", rc);
+ }
+
+ rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
+
+ return iop->offset;
+}
+
+/**
+ * This routine processes the ftruncate() system call.
+ *
+ * @param iop
+ * @param length
+ * @return int
+ */
+static int
+rtems_rfs_rtems_file_ftruncate (rtems_libio_t* iop,
+ rtems_off64_t length)
+{
+ rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
+ int rc;
+
+ if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_FTRUNC))
+ printf("rtems-rfs: file-ftrunc: handle:%p length:%Ld\n", file, length);
+
+ rtems_rfs_rtems_lock (rtems_rfs_file_fs (file));
+
+ rc = rtems_rfs_file_set_size (file, length);
+ 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;
+}
+
+/*
+ * Set of operations handlers for operations on RFS files.
+ */
+
+const rtems_filesystem_file_handlers_r rtems_rfs_rtems_file_handlers = {
+ .open_h = rtems_rfs_rtems_file_open,
+ .close_h = rtems_rfs_rtems_file_close,
+ .read_h = rtems_rfs_rtems_file_read,
+ .write_h = rtems_rfs_rtems_file_write,
+ .ioctl_h = rtems_rfs_rtems_file_ioctl,
+ .lseek_h = rtems_rfs_rtems_file_lseek,
+ .fstat_h = rtems_rfs_rtems_fstat,
+ .fchmod_h = rtems_rfs_rtems_fchmod,
+ .ftruncate_h = rtems_rfs_rtems_file_ftruncate,
+ .fpathconf_h = rtems_filesystem_default_fpathconf,
+ .fsync_h = rtems_rfs_rtems_fdatasync,
+ .fdatasync_h = rtems_rfs_rtems_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl,
+ .rmnod_h = rtems_rfs_rtems_rmnod
+};