Major structure of file system functions to better support asynchronous I/O. Respository should not be trusted until I have a chance to verify everything

This commit is contained in:
Gregory Nutt
2014-10-06 10:53:25 -06:00
parent 1d45f80a9b
commit d914f3ceec
33 changed files with 731 additions and 341 deletions
+4 -4
View File
@@ -69,10 +69,10 @@ else
# Common file/socket descriptor support
CSRCS += fs_close.c fs_dup.c fs_dup2.c fs_fcntl.c fs_filedup.c fs_filedup2.c
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
CSRCS += fs_close.c fs_dup.c fs_dup2.c fs_fcntl.c fs_dupfd.c fs_dupfd2.c
CSRCS += fs_fsync.c fs_getfilep.c fs_ioctl.c fs_lseek.c fs_mkdir.c fs_open.c
CSRCS += fs_poll.c fs_read.c fs_rename.c fs_rmdir.c fs_stat.c fs_statfs.c
CSRCS += fs_select.c fs_unlink.c fs_write.c
# Support for positional file access
+4 -4
View File
@@ -68,7 +68,7 @@
int dup(int fd)
{
int ret = OK;
int ret = OK;
/* Check the range of the descriptor to see if we got a file or a socket
* descriptor. */
@@ -79,19 +79,19 @@ int dup(int fd)
/* Its a valid file descriptor.. dup the file descriptor using any
* other file descriptor*/
ret = file_dup(fd, 0);
ret = fs_dupfd(fd, 0);
}
else
#endif
{
/* Not a vailid file descriptor. Did we get a valid socket descriptor? */
/* Not a valid file descriptor. Did we get a valid socket descriptor? */
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
{
/* Yes.. dup the socket descriptor */
ret = net_dup(fd, CONFIG_NFILE_DESCRIPTORS);
ret = net_dupsd(fd, CONFIG_NFILE_DESCRIPTORS);
}
else
#endif
+2 -2
View File
@@ -87,7 +87,7 @@ int dup2(int fd1, int fd2)
{
/* Yes.. dup the socket descriptor */
return net_dup2(fd1, fd2);
return net_dupsd2(fd1, fd2);
}
else
{
@@ -101,7 +101,7 @@ int dup2(int fd1, int fd2)
{
/* Its a valid file descriptor.. dup the file descriptor */
return file_dup2(fd1, fd2);
return fs_dupfd2(fd1, fd2);
}
}
+53 -35
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_filedup.c
* fs/vfs/fs_dupfd.c
*
* Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -53,20 +53,57 @@
* Pre-processor Definitions
****************************************************************************/
#define DUP_ISOPEN(fd, list) \
((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS && \
list->fl_files[fd].f_inode != NULL)
#define DUP_ISOPEN(filep) (filep->f_inode != NULL)
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Global Functions
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_dup OR dup
* Name: file_dup
*
* Description:
* Equivalent to the non-standard fs_dupfd() function except that it
* accepts a struct file instance instead of a file descriptor. Currently
* used only by file_vfcntl();
*
****************************************************************************/
int file_dup(FAR struct file *filep, int minfd)
{
int fd2;
/* Verify that fd is a valid, open file descriptor */
if (!DUP_ISOPEN(filep))
{
set_errno(EBADF);
return ERROR;
}
/* Increment the reference count on the contained inode */
inode_addref(filep->f_inode);
/* Then allocate a new file descriptor for the inode */
fd2 = files_allocate(filep->f_inode, filep->f_oflags, filep->f_pos, minfd);
if (fd2 < 0)
{
set_errno(EMFILE);
inode_release(filep->f_inode);
return ERROR;
}
return fd2;
}
/****************************************************************************
* Name: fs_dupfd OR dup
*
* Description:
* Clone a file descriptor 'fd' to an arbitray descriptor number (any value
@@ -77,42 +114,23 @@
*
****************************************************************************/
int file_dup(int fd, int minfd)
int fs_dupfd(int fd, int minfd)
{
FAR struct filelist *list;
int fd2;
FAR struct file *filep;
/* Get the thread-specific file list */
/* Get the file structure corresponding to the file descriptor. */
list = sched_getfiles();
DEBUGASSERT(list);
/* Verify that fd is a valid, open file descriptor */
if (!DUP_ISOPEN(fd, list))
filep = fs_getfilep(fd);
if (!filep)
{
set_errno(EBADF);
/* The errno value has already been set */
return ERROR;
}
/* Increment the reference count on the contained inode */
/* Let file_dup() do the real work */
inode_addref(list->fl_files[fd].f_inode);
/* Then allocate a new file descriptor for the inode */
fd2 = files_allocate(list->fl_files[fd].f_inode,
list->fl_files[fd].f_oflags,
list->fl_files[fd].f_pos,
minfd);
if (fd2 < 0)
{
set_errno(EMFILE);
inode_release(list->fl_files[fd].f_inode);
return ERROR;
}
return fd2;
return file_dup(filep, minfd);
}
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
+18 -22
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_filedup2.c
* fs/vfs/fs_dupfd2.c
*
* Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -51,9 +51,7 @@
* Pre-processor Definitions
****************************************************************************/
#define DUP_ISOPEN(fd, list) \
((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS && \
list->fl_files[fd].f_inode != NULL)
#define DUP_ISOPEN(filep) (filep->f_inode != NULL)
/****************************************************************************
* Private Functions
@@ -64,7 +62,7 @@
****************************************************************************/
/****************************************************************************
* Name: file_dup2 OR dup2
* Name: fs_dupfd2 OR dup2
*
* Description:
* Clone a file descriptor to a specific descriptor number. If socket
@@ -75,25 +73,29 @@
****************************************************************************/
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
int file_dup2(int fd1, int fd2)
int fs_dupfd2(int fd1, int fd2)
#else
int dup2(int fd1, int fd2)
#endif
{
FAR struct filelist *list;
FAR struct file *filep1;
FAR struct file *filep2;
/* Get the thread-specific file list */
/* Get the file structures corresponding to the file descriptors. */
list = sched_getfiles();
if (!list)
filep1 = fs_getfilep(fd1);
filep2 = fs_getfilep(fd2);
if (!filep1 || !filep2)
{
set_errno(EMFILE);
/* The errno value has already been set */
return ERROR;
}
/* Verify that fd is a valid, open file descriptor */
/* Verify that fd1 is a valid, open file descriptor */
if (!DUP_ISOPEN(fd1, list))
if (!DUP_ISOPEN(filep1))
{
set_errno(EBADF);
return ERROR;
@@ -106,15 +108,9 @@ int dup2(int fd1, int fd2)
return fd1;
}
/* Verify fd2 */
/* Perform the dup2 operation */
if ((unsigned int)fd2 >= CONFIG_NFILE_DESCRIPTORS)
{
set_errno(EBADF);
return ERROR;
}
return files_dup(&list->fl_files[fd1], &list->fl_files[fd2]);
return file_dup2(filep1, filep2);
}
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
+26 -18
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_fcntl.c
*
* Copyright (C) 2009, 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2009, 2012-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -58,26 +58,28 @@
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_vfcntl
*
* Description:
* Similar to the standard vfcntl function except that is accepts a struct
* struct file instance instead of a file descriptor. Currently used
* only by aio_fcntl();
*
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
static inline int file_vfcntl(int fd, int cmd, va_list ap)
int file_vfcntl(FAR struct file *filep, int cmd, va_list ap)
{
FAR struct filelist *list;
FAR struct file *filep;
int err = 0;
int ret = OK;
/* Get the thread-specific file list */
list = sched_getfiles();
DEBUGASSERT(list);
/* Was this file opened ? */
filep = &list->fl_files[fd];
if (!filep->f_inode)
{
err = EBADF;
@@ -98,7 +100,7 @@ static inline int file_vfcntl(int fd, int cmd, va_list ap)
*/
{
ret = file_dup(fd, va_arg(ap, int));
ret = file_dup(filep, va_arg(ap, int));
}
break;
@@ -216,16 +218,13 @@ errout:
}
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: fcntl
****************************************************************************/
int fcntl(int fd, int cmd, ...)
{
FAR struct file *filep;
va_list ap;
int ret;
@@ -238,9 +237,19 @@ int fcntl(int fd, int cmd, ...)
#if CONFIG_NFILE_DESCRIPTORS > 0
if ((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS)
{
/* Yes.. defer file operations to file_vfcntl() */
/* Get the file structure corresponding to the file descriptor. */
ret = file_vfcntl(fd, cmd, ap);
filep = fs_getfilep(fd);
if (!filep)
{
/* The errno value has already been set */
return ERROR;
}
/* Let file_vfcntl() do the real work */
ret = file_vfcntl(filep, cmd, ap);
}
else
#endif
@@ -266,4 +275,3 @@ int fcntl(int fd, int cmd, ...)
va_end(ap);
return ret;
}
+12 -6
View File
@@ -65,22 +65,28 @@
#if CONFIG_NFILE_DESCRIPTORS > 0
static inline int fs_checkfd(FAR struct tcb_s *tcb, int fd, int oflags)
{
FAR struct filelist *flist;
FAR struct inode *inode;
FAR struct file *filep;
FAR struct inode *inode;
DEBUGASSERT(tcb && tcb->group);
/* Get the file list from the task group */
/* Get the file structure corresponding to the file descriptor. */
flist = &tcb->group->tg_filelist;
filep = fs_getfilep(fd);
if (!filep)
{
/* The errno value has already been set */
return ERROR;
}
/* Get the inode associated with the file descriptor. This should
* normally be the case if fd >= 0. But not in the case where the
* called attempts to explictly stdin with fdopen(0) but stdin has
* called attempts to explicitly stdin with fdopen(0) but stdin has
* been closed.
*/
inode = flist->fl_files[fd].f_inode;
inode = filep->f_inode;
if (!inode)
{
/* No inode -- descriptor does not correspond to an open file */
+34 -22
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_fsync.c
*
* Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -70,36 +70,22 @@
****************************************************************************/
/****************************************************************************
* Name: fsync
* Name: file_fsync
*
* Description:
* This func simply binds inode sync methods to the sync system call.
* Equivalent to the standard fsync() function except that is accepts a
* struct file instance instead of a file descriptor. Currently used
* only by aio_fsync();
*
****************************************************************************/
int fsync(int fd)
int file_fsync(FAR struct file *filep)
{
FAR struct filelist *list;
FAR struct file *filep;
struct inode *inode;
int ret;
/* Get the thread-specific file list */
list = sched_getfiles();
DEBUGASSERT(list);
/* Did we get a valid file descriptor? */
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
{
ret = EBADF;
goto errout;
}
struct inode *inode;
int ret;
/* Was this file opened for write access? */
filep = &list->fl_files[fd];
if ((filep->f_oflags & O_WROK) == 0)
{
ret = EBADF;
@@ -134,3 +120,29 @@ errout:
return ERROR;
}
/****************************************************************************
* Name: fsync
*
* Description:
* This func simply binds inode sync methods to the sync system call.
*
****************************************************************************/
int fsync(int fd)
{
FAR struct file *filep;
/* Get the file structure corresponding to the file descriptor. */
filep = fs_getfilep(fd);
if (!filep)
{
/* The errno value has already been set */
return ERROR;
}
/* Perform the fsync operation */
return file_fsync(filep);
}
+112
View File
@@ -0,0 +1,112 @@
/****************************************************************************
* fs/vfs/fs_getfilep.c
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <sched.h>
#include <errno.h>
#include "inode/inode.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: fs_getfilep
*
* Description:
* Given a file descriptor, return the corresponding instance of struct
* file. NOTE that this function will currently fail if it is provided
* with a socket descriptor.
*
* Parameters:
* fd - The file descriptor
*
* Return:
* A point to the corresponding struct file instance is returned on
* success. On failure, NULL is returned and the errno value is
* set appropriately (EBADF).
*
****************************************************************************/
FAR struct file *fs_getfilep(int fd)
{
FAR struct filelist *list;
int errcode;
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
{
errcode = EBADF;
goto errout;
}
/* The descriptor is in a valid range to file descriptor... Get the
* thread-specific file list.
*/
list = sched_getfiles();
/* The file list can be NULL under one obscure cornercase: When memory
* management debug output is enabled. Then there may be attempts to
* write to stdout from malloc before the group data has been allocated.
*/
if (!list)
{
errcode = EAGAIN;
goto errout;
}
/* And return the file pointer from the list */
return &list->fl_files[fd];
errout:
set_errno(errcode);
return NULL;
}
+9 -7
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_ioctl.c
*
* Copyright (C) 2007-2010, 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2010, 2012-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -89,7 +89,6 @@ int ioctl(int fd, int req, unsigned long arg)
{
int err;
#if CONFIG_NFILE_DESCRIPTORS > 0
FAR struct filelist *list;
FAR struct file *filep;
FAR struct inode *inode;
int ret = OK;
@@ -115,16 +114,19 @@ int ioctl(int fd, int req, unsigned long arg)
}
#if CONFIG_NFILE_DESCRIPTORS > 0
/* Get the thread-specific file list */
/* Get the file structure corresponding to the file descriptor. */
list = sched_getfiles();
DEBUGASSERT(list);
filep = fs_getfilep(fd);
if (!filep)
{
/* The errno value has already been set */
return ERROR;
}
/* Is a driver registered? Does it support the ioctl method? */
filep = &list->fl_files[fd];
inode = filep->f_inode;
if (inode && inode->u.i_ops && inode->u.i_ops->ioctl)
{
/* Yes, then let it perform the ioctl */
+9 -17
View File
@@ -50,7 +50,7 @@
#if CONFIG_NFILE_DESCRIPTORS > 0
/****************************************************************************
* Global Functions
* Public Functions
****************************************************************************/
/****************************************************************************
@@ -71,9 +71,6 @@
*
****************************************************************************/
#ifndef CONFIG_NET_SENDFILE
static inline
#endif
off_t file_seek(FAR struct file *filep, off_t offset, int whence)
{
FAR struct inode *inode;
@@ -172,26 +169,21 @@ errout:
off_t lseek(int fd, off_t offset, int whence)
{
FAR struct filelist *list;
FAR struct file *filep;
/* Did we get a valid file descriptor? */
/* Get the file structure corresponding to the file descriptor. */
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
filep = fs_getfilep(fd);
if (!filep)
{
set_errno(EBADF);
/* The errno value has already been set */
return (off_t)ERROR;
}
else
{
/* Get the thread-specific file list */
list = sched_getfiles();
DEBUGASSERT(list);
/* Then let file_seek do the real work */
/* Then let file_seek do the real work */
return file_seek(&list->fl_files[fd], offset, whence);
}
return file_seek(filep, offset, whence);
}
#endif
+18 -14
View File
@@ -91,19 +91,14 @@ int inode_checkflags(FAR struct inode *inode, int oflags)
int open(const char *path, int oflags, ...)
{
FAR struct filelist *list;
FAR struct inode *inode;
FAR const char *relpath = NULL;
FAR struct file *filep;
FAR struct inode *inode;
FAR const char *relpath = NULL;
#if defined(CONFIG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT)
mode_t mode = 0666;
mode_t mode = 0666;
#endif
int ret;
int fd;
/* Get the thread-specific file list */
list = sched_getfiles();
DEBUGASSERT(list);
int ret;
int fd;
#ifdef CONFIG_FILE_MODE
# ifdef CONFIG_CPP_HAVE_WARNING
@@ -168,6 +163,16 @@ int open(const char *path, int oflags, ...)
goto errout_with_inode;
}
/* Get the file structure corresponding to the file descriptor. */
filep = fs_getfilep(fd);
if (!filep)
{
/* The errno value has already been set */
return ERROR;
}
/* Perform the driver open operation. NOTE that the open method may be
* called many times. The driver/mountpoint logic should handled this
* because it may also be closed that many times.
@@ -179,13 +184,12 @@ int open(const char *path, int oflags, ...)
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_MOUNTPT(inode))
{
ret = inode->u.i_mops->open((FAR struct file*)&list->fl_files[fd],
relpath, oflags, mode);
ret = inode->u.i_mops->open(filep, relpath, oflags, mode);
}
else
#endif
{
ret = inode->u.i_ops->open((FAR struct file*)&list->fl_files[fd]);
ret = inode->u.i_ops->open(filep);
}
}
+11 -9
View File
@@ -97,10 +97,9 @@ static void poll_semtake(FAR sem_t *sem)
#if CONFIG_NFILE_DESCRIPTORS > 0
static int poll_fdsetup(int fd, FAR struct pollfd *fds, bool setup)
{
FAR struct filelist *list;
FAR struct file *filep;
FAR struct inode *inode;
int ret = -ENOSYS;
FAR struct file *filep;
FAR struct inode *inode;
int ret = -ENOSYS;
/* Check for a valid file descriptor */
@@ -120,18 +119,21 @@ static int poll_fdsetup(int fd, FAR struct pollfd *fds, bool setup)
}
}
/* Get the thread-specific file list */
/* Get the file pointer corresponding to this file descriptor */
list = sched_getfiles();
DEBUGASSERT(list);
filep = fs_getfilep(fd);
if (!filep)
{
/* The errno value has already been set */
return ERROR;
}
/* Is a driver registered? Does it support the poll method?
* If not, return -ENOSYS
*/
filep = &list->fl_files[fd];
inode = filep->f_inode;
if (inode && inode->u.i_ops && inode->u.i_ops->poll)
{
/* Yes, then setup the poll */
+69 -37
View File
@@ -43,6 +43,8 @@
#include <unistd.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -51,6 +53,65 @@
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_pread
*
* Description:
* Equivalent to the standard pread function except that is accepts a
* struct file instance instead of a file descriptor. Currently used
* only by aio_read();
*
****************************************************************************/
ssize_t file_pread(FAR struct file *filep, FAR void *buf, size_t nbytes,
off_t offset)
{
off_t savepos;
off_t pos;
ssize_t ret;
int errcode;
/* Perform the seek to the current position. This will not move the
* file pointer, but will return its current setting
*/
savepos = file_seek(filep, 0, SEEK_CUR);
if (savepos == (off_t)-1)
{
/* file_seek might fail if this if the media is not seekable */
return ERROR;
}
/* Then seek to the correct position in the file */
pos = file_seek(filep, offset, SEEK_SET);
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 = file_read(filep, buf, nbytes);
errcode = get_errno();
/* Restore the file position */
pos = file_seek(filep, savepos, SEEK_SET);
if (pos == (off_t)-1 && ret >= 0)
{
/* This really should not fail */
return ERROR;
}
set_errno(errcode);
return ret;
}
/****************************************************************************
* Name: pread
*
@@ -82,48 +143,19 @@
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;
FAR struct file *filep;
/* Perform the lseek to the current position. This will not move the
* file pointer, but will return its current setting
*/
/* Get the file structure corresponding to the file descriptor. */
savepos = lseek(fd, 0, SEEK_CUR);
if (savepos == (off_t)-1)
filep = fs_getfilep(fd);
if (!filep)
{
/* lseek might fail if this if the media is not seekable */
/* The errno value has already been set */
return ERROR;
return (ssize_t)ERROR;
}
/* Then seek to the correct position in the file */
/* Let file_pread do the real work */
pos = lseek(fd, offset, SEEK_SET);
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_SET);
if (pos == (off_t)-1 && ret >= 0)
{
/* This really should not fail */
return ERROR;
}
set_errno(errcode);
return ret;
return file_pread(filep, buf, nbytes, offset);
}
+69 -37
View File
@@ -43,6 +43,8 @@
#include <unistd.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -51,6 +53,65 @@
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_pwrite
*
* Description:
* Equivalent to the standard pwrite function except that is accepts a
* struct file instance instead of a file descriptor. Currently used
* only by aio_write();
*
****************************************************************************/
ssize_t file_pwrite(FAR struct file *filep, FAR const void *buf,
size_t nbytes, off_t offset)
{
off_t savepos;
off_t pos;
ssize_t ret;
int errcode;
/* Perform the seek to the current position. This will not move the
* file pointer, but will return its current setting
*/
savepos = file_seek(filep, 0, SEEK_CUR);
if (savepos == (off_t)-1)
{
/* file_seek might fail if this if the media is not seekable */
return ERROR;
}
/* Then seek to the correct position in the file */
pos = file_seek(filep, offset, SEEK_SET);
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 = file_write(filep, buf, nbytes);
errcode = get_errno();
/* Restore the file position */
pos = file_seek(filep, savepos, SEEK_SET);
if (pos == (off_t)-1 && ret >= 0)
{
/* This really should not fail */
return ERROR;
}
set_errno(errcode);
return ret;
}
/****************************************************************************
* Name: pwrite
*
@@ -80,48 +141,19 @@
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;
FAR struct file *filep;
/* Perform the lseek to the current position. This will not move the
* file pointer, but will return its current setting
*/
/* Get the file structure corresponding to the file descriptor. */
savepos = lseek(fd, 0, SEEK_CUR);
if (savepos == (off_t)-1)
filep = fs_getfilep(fd);
if (!filep)
{
/* lseek might fail if this if the media is not seekable */
/* The errno value has already been set */
return ERROR;
return (ssize_t)ERROR;
}
/* Then seek to the correct position in the file */
/* Let file_pread do the real work */
pos = lseek(fd, offset, SEEK_SET);
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_SET);
if (pos == (off_t)-1 && ret >= 0)
{
/* This really should not fail */
return ERROR;
}
set_errno(errcode);
return ret;
return file_pwrite(filep, buf, nbytes, offset);
}
+13 -15
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_read.c
*
* Copyright (C) 2007-2009, 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2012-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -73,10 +73,6 @@
*
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
#ifndef CONFIG_NET_SENDFILE
static inline
#endif
ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
{
FAR struct inode *inode;
@@ -120,7 +116,6 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
return ret;
}
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
/****************************************************************************
* Name: read
@@ -141,10 +136,6 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
ssize_t read(int fd, FAR void *buf, size_t nbytes)
{
#if CONFIG_NFILE_DESCRIPTORS > 0
FAR struct filelist *list;
#endif
/* Did we get a valid file descriptor? */
#if CONFIG_NFILE_DESCRIPTORS > 0
@@ -168,16 +159,23 @@ ssize_t read(int fd, FAR void *buf, size_t nbytes)
#if CONFIG_NFILE_DESCRIPTORS > 0
else
{
/* Thee descriptor is in a valid range to file descriptor... do the
* read. Get the thread-specific file list.
FAR struct file *filep;
/* The descriptor is in a valid range to file descriptor... do the
* read. First, get the file structure.
*/
list = sched_getfiles();
DEBUGASSERT(list);
filep = fs_getfilep(fd);
if (!filep)
{
/* The errno value has already been set */
return ERROR;
}
/* Then let file_read do all of the work */
return file_read(&list->fl_files[fd], buf, nbytes);
return file_read(filep, buf, nbytes);
}
#endif
}
+11 -6
View File
@@ -127,18 +127,23 @@ ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count)
if ((unsigned int)outfd >= CONFIG_NFILE_DESCRIPTORS &&
(unsigned int)infd < CONFIG_NFILE_DESCRIPTORS)
{
FAR struct filelist *list;
FAR struct file *filep;
/* This appears to be a file-to-socket transfer. Get the thread-
* specific file list.
/* This appears to be a file-to-socket transfer. Get the file
* structure.
*/
list = sched_getfiles();
DEBUGASSERT(list);
filep = fs_getfilep(fd);
if (!filep)
{
/* The errno value has already been set */
return ERROR;
}
/* Then let net_sendfile do the work. */
return net_sendfile(outfd, &list->fl_files[infd], offset, count);
return net_sendfile(outfd, filep, offset, count);
}
else
#endif
+35 -30
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/vfs/fs_write.c
*
* Copyright (C) 2007-2009, 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2012-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -55,33 +55,28 @@
* Private Functions
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
static inline ssize_t file_write(int fd, FAR const void *buf, size_t nbytes)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_write
*
* Description:
* Equivalent to the standard write() function except that is accepts a
* struct file instance instead of a file descriptor. Currently used
* only by aio_write();
*
****************************************************************************/
ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes)
{
FAR struct filelist *list;
FAR struct file *filep;
FAR struct inode *inode;
int ret;
int err;
/* Get the thread-specific file list */
list = sched_getfiles();
/* The file list can be NULL under one obscure cornercase: When memory
* management debug output is enabled. Then there may be attempts to
* write to stdout from malloc before the group data has been allocated.
*/
if (!list)
{
err = EAGAIN;
goto errout;
}
/* Was this file opened for write access? */
filep = &list->fl_files[fd];
if ((filep->f_oflags & O_WROK) == 0)
{
err = EBADF;
@@ -112,11 +107,6 @@ errout:
set_errno(err);
return ERROR;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/***************************************************************************
* Name: write
@@ -170,6 +160,10 @@ errout:
ssize_t write(int fd, FAR const void *buf, size_t nbytes)
{
#if CONFIG_NFILE_DESCRIPTORS > 0
FAR struct file *filep;
#endif
/* Did we get a valid file descriptor? */
#if CONFIG_NFILE_DESCRIPTORS > 0
@@ -186,10 +180,21 @@ ssize_t write(int fd, FAR const void *buf, size_t nbytes)
#endif
}
/* The descriptor is in the right range to be a file descriptor... write to the file */
#if CONFIG_NFILE_DESCRIPTORS > 0
return file_write(fd, buf, nbytes);
/* The descriptor is in the right range to be a file descriptor... write
* to the file.
*/
filep = fs_getfilep(fd);
if (!filep)
{
/* The errno value has already been set */
return ERROR;
}
/* Perform the write operation using the file descriptor as an index */
return file_write(filep, buf, nbytes);
#endif
}