diff options
Diffstat (limited to 'cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c')
-rw-r--r-- | cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c | 354 |
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 +}; |