From 948be542a1e70985c082ee4e3d743cc44d5ebb82 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 4 Oct 2014 07:31:13 -0600 Subject: [PATCH] Add pread() and pwrite() --- fs/vfs/Make.defs | 8 +++ fs/vfs/fs_pread.c | 129 +++++++++++++++++++++++++++++++++++++++++++++ fs/vfs/fs_pwrite.c | 127 ++++++++++++++++++++++++++++++++++++++++++++ fs/vfs/fs_read.c | 6 +-- include/unistd.h | 2 + 5 files changed, 269 insertions(+), 3 deletions(-) create mode 100644 fs/vfs/fs_pread.c create mode 100644 fs/vfs/fs_pwrite.c diff --git a/fs/vfs/Make.defs b/fs/vfs/Make.defs index 2919b40b5b7..583aaf070e1 100644 --- a/fs/vfs/Make.defs +++ b/fs/vfs/Make.defs @@ -43,6 +43,10 @@ ifneq ($(CONFIG_NSOCKET_DESCRIPTORS),0) CSRCS += fs_close.c fs_read.c fs_write.c fs_ioctl.c fs_poll.c fs_select.c +# Support for positional file access + +CSRCS += fs_pread.c fs_pwrite.c + # Support for network access using streams ifneq ($(CONFIG_NFILE_STREAMS),0) @@ -70,6 +74,10 @@ CSRCS += fs_fsync.c fs_ioctl.c fs_lseek.c fs_mkdir.c fs_open.c fs_poll.c CSRCS += fs_read.c fs_rename.c fs_rmdir.c fs_stat.c fs_statfs.c fs_select.c CSRCS += fs_unlink.c fs_write.c +# Support for positional file access + +CSRCS += fs_pread.c fs_pwrite.c + # Stream support ifneq ($(CONFIG_NFILE_STREAMS),0) diff --git a/fs/vfs/fs_pread.c b/fs/vfs/fs_pread.c new file mode 100644 index 00000000000..621ffa7ff3c --- /dev/null +++ b/fs/vfs/fs_pread.c @@ -0,0 +1,129 @@ +/**************************************************************************** + * fs/vfs/fs_pread.c + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pread + * + * Description: + * The pread() function performs the same action as read(), except that it + * reads from a given position in the file without changing the file + * pointer. The first three arguments to pread() are the same as read() + * with the addition of a fourth argument offset for the desired position + * inside the file. An attempt to perform a pread() on a file that is + * incapable of seeking results in an error. + * + * NOTE: This function could have been wholly implemented within libc but + * it is not. Why? Because if pread were implemented in libc, it would + * require four system calls. If it is implemented within the kernel, + * only three. + * + * Parameters: + * file File structure instance + * buf User-provided to save the data + * nbytes The maximum size of the user-provided buffer + * offset The file offset + * + * Return: + * The positive non-zero number of bytes read on success, 0 on if an + * end-of-file condition, or -1 on failure with errno set appropriately. + * See read() return values + * + ****************************************************************************/ + +ssize_t pread(int fd, FAR void *buf, size_t nbytes, off_t offset) +{ + off_t savepos; + off_t pos; + ssize_t ret; + int errcode; + + /* Perform the lseek to the current position. This will not move the + * file pointer, but will return its current setting + */ + + savepos = lseek(fd, 0, SEEK_CUR); + if (savepos == (off_t)-1) + { + /* lseek might fail if this if the media is not seekable */ + + return ERROR; + } + + /* Then seek to the correct position in the file */ + + pos = lseek(fd, offset, SEEK_CUR); + if (pos == (off_t)-1) + { + /* This might fail is the offset is beyond the end of file */ + + return ERROR; + } + + /* Then perform the read operation */ + + ret = read(fd, buf, nbytes); + errcode = get_errno(); + + /* Restore the file position */ + + pos = lseek(fd, savepos, SEEK_CUR); + if (pos == (off_t)-1 && ret >= 0) + { + /* This really should not fail */ + + return ERROR; + } + + set_errno(errcode); + return ret; +} diff --git a/fs/vfs/fs_pwrite.c b/fs/vfs/fs_pwrite.c new file mode 100644 index 00000000000..a1e6a05d407 --- /dev/null +++ b/fs/vfs/fs_pwrite.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * fs/vfs/fs_pwrite.c + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pwrite + * + * Description: + * The pwrite() function performs the same action as write(), except that + * it writes into a given position without changing the file pointer. The + * first three arguments to pwrite() are the same as write() with the + * addition of a fourth argument offset for the desired position inside + * the file. + * + * NOTE: This function could have been wholly implemented within libc but + * it is not. Why? Because if pwrite were implemented in libc, it would + * require four system calls. If it is implemented within the kernel, + * only three. + * + * Parameters: + * fd file descriptor (or socket descriptor) to write to + * buf Data to write + * nbytes Length of data to write + * + * Return: + * The positive non-zero number of bytes read on success, 0 on if an + * end-of-file condition, or -1 on failure with errno set appropriately. + * See write() return values + * + ****************************************************************************/ + +ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset) +{ + off_t savepos; + off_t pos; + ssize_t ret; + int errcode; + + /* Perform the lseek to the current position. This will not move the + * file pointer, but will return its current setting + */ + + savepos = lseek(fd, 0, SEEK_CUR); + if (savepos == (off_t)-1) + { + /* lseek might fail if this if the media is not seekable */ + + return ERROR; + } + + /* Then seek to the correct position in the file */ + + pos = lseek(fd, offset, SEEK_CUR); + if (pos == (off_t)-1) + { + /* This might fail is the offset is beyond the end of file */ + + return ERROR; + } + + /* Then perform the write operation */ + + ret = write(fd, buf, nbytes); + errcode = get_errno(); + + /* Restore the file position */ + + pos = lseek(fd, savepos, SEEK_CUR); + if (pos == (off_t)-1 && ret >= 0) + { + /* This really should not fail */ + + return ERROR; + } + + set_errno(errcode); + return ret; +} diff --git a/fs/vfs/fs_read.c b/fs/vfs/fs_read.c index 5b0e09db0b4..d9b7ed23a15 100644 --- a/fs/vfs/fs_read.c +++ b/fs/vfs/fs_read.c @@ -69,7 +69,7 @@ * * Return: * The positive non-zero number of bytes read on success, 0 on if an - * end-of-file condition, or -1 on failure withi errno set appropriately. + * end-of-file condition, or -1 on failure with errno set appropriately. * ****************************************************************************/ @@ -101,7 +101,7 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes) else if (inode && inode->u.i_ops && inode->u.i_ops->read) { /* Yes.. then let it perform the read. NOTE that for the case of the - * mountpoint, we depend on the read methods bing identical in + * mountpoint, we depend on the read methods being identical in * signature and position in the operations vtable. */ @@ -135,7 +135,7 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes) * * Return: * The positive non-zero number of bytes read on success, 0 on if an - * end-of-file condition, or -1 on failure withi errno set appropriately. + * end-of-file condition, or -1 on failure with errno set appropriately. * ****************************************************************************/ diff --git a/include/unistd.h b/include/unistd.h index abaf7230c48..5108faa5173 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -146,6 +146,8 @@ int fsync(int fd); off_t lseek(int fd, off_t offset, int whence); ssize_t read(int fd, FAR void *buf, size_t nbytes); ssize_t write(int fd, FAR const void *buf, size_t nbytes); +ssize_t pread(int fd, FAR void *buf, size_t nbytes, off_t offset); +ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset); /* Memory management */