Move renaming files in fs/. to fs/vfs/. (Don't all belong there)

This commit is contained in:
Gregory Nutt
2014-09-28 11:46:11 -06:00
parent 1426e424ff
commit ff73be870e
24 changed files with 115 additions and 60 deletions
+91
View File
@@ -0,0 +1,91 @@
############################################################################
# fs/vfs/Make.defs
#
# 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.
#
############################################################################
# If there are no file descriptors configured, then a small part of the
# logic in this directory may still apply to socket descriptors
ifeq ($(CONFIG_NFILE_DESCRIPTORS),0)
ifneq ($(CONFIG_NSOCKET_DESCRIPTORS),0)
# Socket descriptor support
CSRCS += fs_close.c fs_read.c fs_write.c fs_ioctl.c fs_poll.c fs_select.c
# Support for network access using streams
ifneq ($(CONFIG_NFILE_STREAMS),0)
CSRCS += fs_fdopen.c
endif
# Support for sendfile()
ifeq ($(CONFIG_NET_SENDFILE),y)
CSRCS += fs_sendfile.c
endif
# Include vfs build support
DEPPATH += --dep-path vfs
VPATH += :vfs
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)vfs}
endif
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_ioctl.c fs_lseek.c fs_mkdir.c fs_open.c fs_poll.c fs_read.c
CSRCS += fs_rename.c fs_rmdir.c fs_stat.c fs_statfs.c fs_select.c
CSRCS += fs_unlink.c fs_write.c
# Stream support
ifneq ($(CONFIG_NFILE_STREAMS),0)
CSRCS += fs_fdopen.c
endif
# Support for sendfile()
ifeq ($(CONFIG_NET_SENDFILE),y)
CSRCS += fs_sendfile.c
endif
# Include vfs build support
DEPPATH += --dep-path vfs
VPATH += :vfs
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)fs$(DELIM)vfs}
endif
+133
View File
@@ -0,0 +1,133 @@
/****************************************************************************
* fs/vfs/fs_close.c
*
* Copyright (C) 2007-2009, 2012 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 <unistd.h>
#include <sched.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
# include <nuttx/net/net.h>
#endif
#include "fs.h"
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: close
*
* Description:
* close() closes a file descriptor, so that it no longer refers to any
* file and may be reused. Any record locks (see fcntl(2)) held on the file
* it was associated with, and owned by the process, are removed (regardless
* of the file descriptor that was used to obtain the lock).
*
* If fd is the last copy of a particular file descriptor the resources
* associated with it are freed; if the descriptor was the last reference
* to a file which has been removed using unlink(2) the file is deleted.
*
* Parameters:
* fd file descriptor to close
*
* Returned Value:
* 0 on success; -1 on error with errno set appropriately.
*
* Assumptions:
*
****************************************************************************/
int close(int fd)
{
int err;
#if CONFIG_NFILE_DESCRIPTORS > 0
int ret;
/* Did we get a valid file descriptor? */
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
{
/* Close a socket descriptor */
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
{
return net_close(fd);
}
else
#endif
{
err = EBADF;
goto errout;
}
}
#if CONFIG_NFILE_DESCRIPTORS > 0
/* Close the driver or mountpoint. NOTES: (1) there is no
* exclusion mechanism here , the driver or mountpoint must be
* able to handle concurrent operations internally, (2) The driver
* may have been opened numerous times (for different file
* descriptors) and must also handle being closed numerous times.
* (3) for the case of the mountpoint, we depend on the close
* methods bing identical in signature and position in the operations
* vtable.
*/
ret = files_close(fd);
if (ret < 0)
{
/* An error occurred while closing the driver */
err = -ret;
goto errout;
}
return OK;
#endif
errout:
set_errno(err);
return ERROR;
}
+107
View File
@@ -0,0 +1,107 @@
/****************************************************************************
* fs/vfs/fs_dup.c
*
* Copyright (C) 2007-2009 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 <unistd.h>
#include <sched.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include "fs.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: dup
*
* Description:
* Clone a file or socket descriptor to an arbitray descriptor number
*
****************************************************************************/
int dup(int fd)
{
int ret = OK;
/* Check the range of the descriptor to see if we got a file or a socket
* descriptor. */
#if CONFIG_NFILE_DESCRIPTORS > 0
if ((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS)
{
/* Its a valid file descriptor.. dup the file descriptor using any
* other file descriptor*/
ret = file_dup(fd, 0);
}
else
#endif
{
/* Not a vailid 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);
}
else
#endif
{
/* No.. then it is a bad descriptor number */
set_errno(EBADF);
ret = ERROR;
}
}
return ret;
}
+109
View File
@@ -0,0 +1,109 @@
/****************************************************************************
* fs/vfs/fs_dup2.c
*
* Copyright (C) 2007-2009, 2011, 2013 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 <unistd.h>
#include <sched.h>
#include <errno.h>
#include "fs.h"
/* This logic in this applies only when both socket and file descriptors are
* in that case, this function descriminates which type of dup2 is being
* performed.
*/
#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: dup2
*
* Description:
* Clone a file descriptor or socket descriptor to a specific descriptor
* number
*
****************************************************************************/
int dup2(int fd1, int fd2)
{
/* Check the range of the descriptor to see if we got a file or a socket
* descriptor.
*/
if ((unsigned int)fd1 >= CONFIG_NFILE_DESCRIPTORS)
{
/* Not a valid file descriptor. Did we get a valid socket descriptor? */
if ((unsigned int)fd1 < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
{
/* Yes.. dup the socket descriptor */
return net_dup2(fd1, fd2);
}
else
{
/* No.. then it is a bad descriptor number */
set_errno(EBADF);
return ERROR;
}
}
else
{
/* Its a valid file descriptor.. dup the file descriptor */
return file_dup2(fd1, fd2);
}
}
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 ... */
+269
View File
@@ -0,0 +1,269 @@
/****************************************************************************
* fs/vfs/fs_fcntl.c
*
* Copyright (C) 2009, 2012-2013 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 <stdarg.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <nuttx/fs/fs.h>
#include <nuttx/net/net.h>
#include <nuttx/sched.h>
#include "fs.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: file_vfcntl
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
static inline int file_vfcntl(int fd, 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;
goto errout;
}
switch (cmd)
{
case F_DUPFD:
/* Return a new file descriptor which shall be the lowest numbered
* available (that is, not already open) file descriptor greater than
* or equal to the third argument, arg, taken as an integer of type
* int. The new file descriptor shall refer to the same open file
* description as the original file descriptor, and shall share any
* locks. The FD_CLOEXEC flag associated with the new file descriptor
* shall be cleared to keep the file open across calls to one of the
* exec functions.
*/
{
ret = file_dup(fd, va_arg(ap, int));
}
break;
case F_GETFD:
/* Get the file descriptor flags defined in <fcntl.h> that are associated
* with the file descriptor fd. File descriptor flags are associated
* with a single file descriptor and do not affect other file descriptors
* that refer to the same file.
*/
case F_SETFD:
/* Set the file descriptor flags defined in <fcntl.h>, that are associated
* with fd, to the third argument, arg, taken as type int. If the
* FD_CLOEXEC flag in the third argument is 0, the file shall remain open
* across the exec functions; otherwise, the file shall be closed upon
* successful execution of one of the exec functions.
*/
err = ENOSYS;
break;
case F_GETFL:
/* Get the file status flags and file access modes, defined in <fcntl.h>,
* for the file description associated with fd. The file access modes
* can be extracted from the return value using the mask O_ACCMODE, which is
* defined in <fcntl.h>. File status flags and file access modes are associated
* with the file description and do not affect other file descriptors that
* refer to the same file with different open file descriptions.
*/
{
ret = filep->f_oflags;
}
break;
case F_SETFL:
/* Set the file status flags, defined in <fcntl.h>, for the file description
* associated with fd from the corresponding bits in the third argument,
* arg, taken as type int. Bits corresponding to the file access mode and
* the file creation flags, as defined in <fcntl.h>, that are set in arg shall
* be ignored. If any bits in arg other than those mentioned here are changed
* by the application, the result is unspecified.
*/
{
int oflags = va_arg(ap, int);
oflags &= FFCNTL;
filep->f_oflags &= ~FFCNTL;
filep->f_oflags |= oflags;
}
break;
case F_GETOWN:
/* If fd refers to a socket, get the process or process group ID specified
* to receive SIGURG signals when out-of-band data is available. Positive values
* indicate a process ID; negative values, other than -1, indicate a process group
* ID. If fd does not refer to a socket, the results are unspecified.
*/
case F_SETOWN:
/* If fd refers to a socket, set the process or process group ID specified
* to receive SIGURG signals when out-of-band data is available, using the value
* of the third argument, arg, taken as type int. Positive values indicate a
* process ID; negative values, other than -1, indicate a process group ID. If
* fd does not refer to a socket, the results are unspecified.
*/
err = EBADF; /* Only valid on socket descriptors */
break;
case F_GETLK:
/* Get the first lock which blocks the lock description pointed to by the third
* argument, arg, taken as a pointer to type struct flock, defined in <fcntl.h>.
* The information retrieved shall overwrite the information passed to fcntl() in
* the structure flock. If no lock is found that would prevent this lock from being
* created, then the structure shall be left unchanged except for the lock type
* which shall be set to F_UNLCK.
*/
case F_SETLK:
/* Set or clear a file segment lock according to the lock description pointed to
* by the third argument, arg, taken as a pointer to type struct flock, defined in
* <fcntl.h>. F_SETLK can establish shared (or read) locks (F_RDLCK) or exclusive
* (or write) locks (F_WRLCK), as well as to remove either type of lock (F_UNLCK).
* F_RDLCK, F_WRLCK, and F_UNLCK are defined in <fcntl.h>. If a shared or exclusive
* lock cannot be set, fcntl() shall return immediately with a return value of -1.
*/
case F_SETLKW:
/* This command shall be equivalent to F_SETLK except that if a shared or exclusive
* lock is blocked by other locks, the thread shall wait until the request can be
* satisfied. If a signal that is to be caught is received while fcntl() is waiting
* for a region, fcntl() shall be interrupted. Upon return from the signal handler,
* fcntl() shall return -1 with errno set to [EINTR], and the lock operation shall
* not be done.
*/
err = ENOSYS; /* Not implemented */
break;
default:
err = EINVAL;
break;
}
errout:
if (err != 0)
{
set_errno(err);
return ERROR;
}
return ret;
}
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: fcntl
****************************************************************************/
int fcntl(int fd, int cmd, ...)
{
va_list ap;
int ret;
/* Setup to access the variable argument list */
va_start(ap, cmd);
/* Did we get a valid file descriptor? */
#if CONFIG_NFILE_DESCRIPTORS > 0
if ((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS)
{
/* Yes.. defer file operations to file_vfcntl() */
ret = file_vfcntl(fd, cmd, ap);
}
else
#endif
{
/* No... check for operations on a socket descriptor */
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
{
/* Yes.. defer socket descriptor operations to net_vfcntl() */
ret = net_vfcntl(fd, cmd, ap);
}
else
#endif
{
/* No.. this descriptor number is out of range */
ret = EBADF;
}
}
va_end(ap);
return ret;
}
+274
View File
@@ -0,0 +1,274 @@
/****************************************************************************
* fs/vfs/fs_fdopen.c
*
* Copyright (C) 2007-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 <stdio.h>
#include <string.h>
#include <semaphore.h>
#include <fcntl.h>
#include <errno.h>
#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include <nuttx/net/net.h>
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: fs_checkfd
*
* Description:
* Check if the file descriptor is valid for the provided TCB and if it
* supports the requested access.
*
****************************************************************************/
#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;
DEBUGASSERT(tcb && tcb->group);
/* Get the file list from the task group */
flist = &tcb->group->tg_filelist;
/* 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
* been closed.
*/
inode = flist->fl_files[fd].f_inode;
if (!inode)
{
/* No inode -- descriptor does not correspond to an open file */
return -ENOENT;
}
/* Make sure that the inode supports the requested access. In
* the case of fdopen, we are not actually creating the file -- in
* particular w and w+ do not truncate the file and any files have
* already been created.
*/
if (inode_checkflags(inode, oflags) != OK)
{
/* Cannot support the requested access */
return -EACCES;
}
/* Looks good to me */
return OK;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: fs_fdopen
*
* Description:
* This function does the core operations for fopen and fdopen.
*
****************************************************************************/
FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb)
{
FAR struct streamlist *slist;
FAR FILE *stream;
int err = OK;
int ret;
int i;
/* Check input parameters */
if (fd < 0)
{
err = EBADF;
goto errout;
}
/* A NULL TCB pointer means to use this threads TCB. This is a little
* hack the let's this function be called from user-space (via a syscall)
* without having access to the TCB.
*/
if (!tcb)
{
tcb = sched_self();
}
DEBUGASSERT(tcb && tcb->group);
/* Verify that this is a valid file/socket descriptor and that the
* requested access can be support.
*
* Is this fd in the range of valid file descriptors? Socket descriptors
* lie in a different range.
*/
#if CONFIG_NFILE_DESCRIPTORS > 0
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
{
/* No.. If networking is enabled then this might be a socket
* descriptor.
*/
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
ret = net_checksd(fd, oflags);
#else
/* No networking... it is just a bad descriptor */
err = EBADF;
goto errout;
#endif
}
/* The descriptor is in a valid range to file descriptor... perform some more checks */
#if CONFIG_NFILE_DESCRIPTORS > 0
else
{
ret = fs_checkfd(tcb, fd, oflags);
}
#endif
/* Do we have a good descriptor of some sort? */
if (ret < 0)
{
/* No... return the reported error */
err = -ret;
goto errout;
}
/* Get the stream list from the TCB */
#if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \
defined(CONFIG_MM_KERNEL_HEAP)
slist = tcb->group->tg_streamlist;
#else
slist = &tcb->group->tg_streamlist;
#endif
/* Find an unallocated FILE structure in the stream list */
ret = sem_wait(&slist->sl_sem);
if (ret != OK)
{
goto errout_with_errno;
}
for (i = 0 ; i < CONFIG_NFILE_STREAMS; i++)
{
stream = &slist->sl_streams[i];
if (stream->fs_fd < 0)
{
/* Zero the structure */
#if CONFIG_STDIO_BUFFER_SIZE > 0
memset(stream, 0, sizeof(FILE));
#elif CONFIG_NUNGET_CHARS > 0
stream->fs_nungotten = 0;
#endif
#if CONFIG_STDIO_BUFFER_SIZE > 0
/* Initialize the semaphore the manages access to the buffer */
(void)sem_init(&stream->fs_sem, 0, 1);
/* Allocate the IO buffer at the appropriate privilege level for
* the group.
*/
stream->fs_bufstart =
group_malloc(tcb->group, CONFIG_STDIO_BUFFER_SIZE);
if (!stream->fs_bufstart)
{
err = ENOMEM;
goto errout_with_sem;
}
/* Set up pointers */
stream->fs_bufend = &stream->fs_bufstart[CONFIG_STDIO_BUFFER_SIZE];
stream->fs_bufpos = stream->fs_bufstart;
stream->fs_bufpos = stream->fs_bufstart;
stream->fs_bufread = stream->fs_bufstart;
#endif
/* Save the file description and open flags. Setting the
* file descriptor locks this stream.
*/
stream->fs_fd = fd;
stream->fs_oflags = (uint16_t)oflags;
sem_post(&slist->sl_sem);
return stream;
}
}
/* No free stream available.. report ENFILE */
err = ENFILE;
#if CONFIG_STDIO_BUFFER_SIZE > 0
errout_with_sem:
#endif
sem_post(&slist->sl_sem);
errout:
set_errno(err);
errout_with_errno:
return NULL;
}
+119
View File
@@ -0,0 +1,119 @@
/****************************************************************************
* fs/vfs/fs_filedup.c
*
* Copyright (C) 2007-2009, 2011-2013 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 <sched.h>
#include <errno.h>
#include <assert.h>
#include <nuttx/fs/fs.h>
#include "fs.h"
#if CONFIG_NFILE_DESCRIPTORS > 0
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define DUP_ISOPEN(fd, list) \
((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS && \
list->fl_files[fd].f_inode != NULL)
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: file_dup OR dup
*
* Description:
* Clone a file descriptor 'fd' to an arbitray descriptor number (any value
* greater than or equal to 'minfd'). If socket descriptors are
* implemented, then this is called by dup() for the case of file
* descriptors. If socket descriptors are not implemented, then this
* function IS dup().
*
****************************************************************************/
int file_dup(int fd, int minfd)
{
FAR struct filelist *list;
int fd2;
/* Get the thread-specific file list */
list = sched_getfiles();
DEBUGASSERT(list);
/* Verify that fd is a valid, open file descriptor */
if (!DUP_ISOPEN(fd, list))
{
set_errno(EBADF);
return ERROR;
}
/* Increment the reference count on the contained inode */
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;
}
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
+121
View File
@@ -0,0 +1,121 @@
/****************************************************************************
* fs/vfs/fs_filedup2.c
*
* Copyright (C) 2007-2009, 2011-2013 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 <unistd.h>
#include <sched.h>
#include <errno.h>
#include "fs.h"
#if CONFIG_NFILE_DESCRIPTORS > 0
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define DUP_ISOPEN(fd, list) \
((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS && \
list->fl_files[fd].f_inode != NULL)
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: file_dup2 OR dup2
*
* Description:
* Clone a file descriptor to a specific descriptor number. If socket
* descriptors are implemented, then this is called by dup2() for the
* case of file descriptors. If socket descriptors are not implemented,
* then this function IS dup2().
*
****************************************************************************/
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
int file_dup2(int fd1, int fd2)
#else
int dup2(int fd1, int fd2)
#endif
{
FAR struct filelist *list;
/* Get the thread-specific file list */
list = sched_getfiles();
if (!list)
{
set_errno(EMFILE);
return ERROR;
}
/* Verify that fd is a valid, open file descriptor */
if (!DUP_ISOPEN(fd1, list))
{
set_errno(EBADF);
return ERROR;
}
/* Handle a special case */
if (fd1 == fd2)
{
return fd1;
}
/* Verify fd2 */
if ((unsigned int)fd2 >= CONFIG_NFILE_DESCRIPTORS)
{
set_errno(EBADF);
return ERROR;
}
return files_dup(&list->fl_files[fd1], &list->fl_files[fd2]);
}
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
+136
View File
@@ -0,0 +1,136 @@
/****************************************************************************
* fs/vfs/fs_fsync.c
*
* Copyright (C) 2007-2009, 2013 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 <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <nuttx/fs/fs.h>
#include <nuttx/sched.h>
#include "fs.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Public Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: fsync
*
* Description:
* This func simply binds inode sync methods to the sync system call.
*
****************************************************************************/
int fsync(int fd)
{
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;
}
/* Was this file opened for write access? */
filep = &list->fl_files[fd];
if ((filep->f_oflags & O_WROK) == 0)
{
ret = EBADF;
goto errout;
}
/* Is this inode a registered mountpoint? Does it support the
* sync operations may be relevant to device drivers but only
* the mountpoint operations vtable contains a sync method.
*/
inode = filep->f_inode;
if (!inode || !INODE_IS_MOUNTPT(inode) ||
!inode->u.i_mops || !inode->u.i_mops->sync)
{
ret = EINVAL;
goto errout;
}
/* Yes, then tell the mountpoint to sync this file */
ret = inode->u.i_mops->sync(filep);
if (ret >= 0)
{
return OK;
}
ret = -ret;
errout:
set_errno(ret);
return ERROR;
}
+147
View File
@@ -0,0 +1,147 @@
/****************************************************************************
* fs/vfs/fs_ioctl.c
*
* Copyright (C) 2007-2010, 2012-2013 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/ioctl.h>
#include <sched.h>
#include <errno.h>
#include <assert.h>
#include <net/if.h>
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
# include <nuttx/net/net.h>
#endif
#include "fs.h"
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: ioctl
*
* Description:
* Perform device specific operations.
*
* Parameters:
* fd File/socket descriptor of device
* req The ioctl command
* arg The argument of the ioctl cmd
*
* Return:
* >=0 on success (positive non-zero values are cmd-specific)
* -1 on failure withi errno set properly:
*
* EBADF
* 'fd' is not a valid descriptor.
* EFAULT
* 'arg' references an inaccessible memory area.
* EINVAL
* 'cmd' or 'arg' is not valid.
* ENOTTY
* 'fd' is not associated with a character special device.
* ENOTTY
* The specified request does not apply to the kind of object that the
* descriptor 'fd' references.
*
****************************************************************************/
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;
/* Did we get a valid file descriptor? */
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
{
/* Perform the socket ioctl */
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
{
return netdev_ioctl(fd, req, arg);
}
else
#endif
{
err = EBADF;
goto errout;
}
}
#if CONFIG_NFILE_DESCRIPTORS > 0
/* Get the thread-specific file list */
list = sched_getfiles();
DEBUGASSERT(list);
/* 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 */
ret = (int)inode->u.i_ops->ioctl(filep, req, arg);
if (ret < 0)
{
err = -ret;
goto errout;
}
}
return ret;
#endif
errout:
set_errno(err);
return ERROR;
}
+197
View File
@@ -0,0 +1,197 @@
/****************************************************************************
* fs/vfs/fs_lseek.c
*
* Copyright (C) 2008 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 <unistd.h>
#include <sched.h>
#include <errno.h>
#include <assert.h>
#include "fs.h"
#if CONFIG_NFILE_DESCRIPTORS > 0
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: file_seek
*
* Description:
* This is the internal implementation of lseek. See the comments in
* lseek() for further information.
*
* Parameters:
* file File structure instance
* offset Defines the offset to position to
* whence Defines how to use offset
*
* Return:
* The resulting offset on success. -1 on failure withi errno set
* properly (see lseek comments).
*
****************************************************************************/
#ifndef CONFIG_NET_SENDFILE
static inline
#endif
off_t file_seek(FAR struct file *filep, off_t offset, int whence)
{
FAR struct inode *inode;
int ret;
int err = OK;
DEBUGASSERT(filep);
inode = filep->f_inode;
/* Invoke the file seek method if available */
if (inode && inode->u.i_ops && inode->u.i_ops->seek)
{
ret = (int)inode->u.i_ops->seek(filep, offset, whence);
if (ret < 0)
{
err = -ret;
goto errout;
}
}
else
{
/* No... Just set the common file position value */
switch (whence)
{
case SEEK_CUR:
offset += filep->f_pos;
case SEEK_SET:
if (offset >= 0)
{
filep->f_pos = offset; /* Might be beyond the end-of-file */
break;
}
else
{
err = EINVAL;
goto errout;
}
break;
case SEEK_END:
err = ENOSYS;
goto errout;
default:
err = EINVAL;
goto errout;
}
}
return filep->f_pos;
errout:
set_errno(err);
return (off_t)ERROR;
}
/****************************************************************************
* Name: lseek
*
* Description:
* The lseek() function repositions the offset of the open file associated
* with the file descriptor fd to the argument 'offset' according to the
* directive 'whence' as follows:
*
* SEEK_SET
* The offset is set to offset bytes.
* SEEK_CUR
* The offset is set to its current location plus offset bytes.
* SEEK_END
* The offset is set to the size of the file plus offset bytes.
*
* The lseek() function allows the file offset to be set beyond the end of the
* file (but this does not change the size of the file). If data is later written
* at this point, subsequent reads of the data in the gap (a "hole") return null
* bytes ('\0') until data is actually written into the gap.
*
* Parameters:
* fd File descriptor of device
* offset Defines the offset to position to
* whence Defines how to use offset
*
* Return:
* The resulting offset on success. -1 on failure withi errno set properly:
*
* EBADF fd is not an open file descriptor.
* EINVAL whence is not one of SEEK_SET, SEEK_CUR, SEEK_END; or the
* resulting file offset would be negative, or beyond the end of a
* seekable device.
* EOVERFLOW The resulting file offset cannot be represented in an off_t.
* ESPIPE fd is associated with a pipe, socket, or FIFO.
*
****************************************************************************/
off_t lseek(int fd, off_t offset, int whence)
{
FAR struct filelist *list;
/* Did we get a valid file descriptor? */
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
{
set_errno(EBADF);
return (off_t)ERROR;
}
else
{
/* Get the thread-specific file list */
list = sched_getfiles();
DEBUGASSERT(list);
/* Then let file_seek do the real work */
return file_seek(&list->fl_files[fd], offset, whence);
}
}
#endif
+188
View File
@@ -0,0 +1,188 @@
/****************************************************************************
* fs/vfs/fs_mkdir.c
*
* Copyright (C) 2007, 2008, 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/stat.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include "fs.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#undef FS_HAVE_WRITABLE_MOUNTPOINT
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_WRITABLE_MOUNTPOINT 1
#endif
#undef FS_HAVE_PSEUDOFS_OPERATIONS
#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_PSEUDOFS_OPERATIONS 1
#endif
#undef FS_HAVE_MKDIR
#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
# define FS_HAVE_MKDIR 1
#endif
#ifdef FS_HAVE_MKDIR
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Public Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mkdir
*
* Description: Create a directory
*
****************************************************************************/
int mkdir(const char *pathname, mode_t mode)
{
FAR struct inode *inode;
const char *relpath = NULL;
int errcode;
int ret;
/* Find the inode that includes this path */
inode = inode_find(pathname, &relpath);
if (inode)
{
/* An inode was found that includes this path and possibly refers to a
* mountpoint.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
/* Check if the inode is a valid mountpoint. */
if (!INODE_IS_MOUNTPT(inode) || !inode->u.i_mops)
{
/* The inode is not a mountpoint */
errcode = ENXIO;
goto errout_with_inode;
}
/* Perform the mkdir operation using the relative path
* at the mountpoint.
*/
if (inode->u.i_mops->mkdir)
{
ret = inode->u.i_mops->mkdir(inode, relpath, mode);
if (ret < 0)
{
errcode = -ret;
goto errout_with_inode;
}
}
else
{
errcode = ENOSYS;
goto errout_with_inode;
}
/* Release our reference on the inode */
inode_release(inode);
#else
/* But mountpoints are not supported in this configuration */
errcode = EEXIST;
goto errout_with_inode;
#endif
}
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
/* No inode exists that contains this path. Create a new inode in the
* pseudo-filesystem at this location.
*/
else
{
/* Create an inode in the pseudo-filesystem at this path */
inode_semtake();
ret = inode_reserve(pathname, &inode);
inode_semgive();
if (ret < 0)
{
errcode = -ret;
goto errout;
}
}
#else
else
{
errcode = ENXIO;
goto errout;
}
#endif
/* Directory successfully created */
return OK;
errout_with_inode:
inode_release(inode);
errout:
set_errno(errcode);
return ERROR;
}
#endif /* FS_HAVE_MKDIR */
+206
View File
@@ -0,0 +1,206 @@
/****************************************************************************
* fs/vfs/fs_open.c
*
* Copyright (C) 2007-2009, 2011-2012 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 <fcntl.h>
#include <sched.h>
#include <errno.h>
#include <assert.h>
#ifdef CONFIG_FILE_MODE
#include <stdarg.h>
#endif
#include <nuttx/fs/fs.h>
#include "fs.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: inode_checkflags
*
* Description:
* Check if the access described by 'oflags' is supported on 'inode'
*
****************************************************************************/
int inode_checkflags(FAR struct inode *inode, int oflags)
{
if (((oflags & O_RDOK) != 0 && !inode->u.i_ops->read) ||
((oflags & O_WROK) != 0 && !inode->u.i_ops->write))
{
return -EACCES;
}
else
{
return OK;
}
}
/****************************************************************************
* Name: open
*
* Description:
* Standard 'open' interface
*
****************************************************************************/
int open(const char *path, int oflags, ...)
{
FAR struct filelist *list;
FAR struct inode *inode;
FAR const char *relpath = NULL;
#if defined(CONFIG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT)
mode_t mode = 0666;
#endif
int ret;
int fd;
/* Get the thread-specific file list */
list = sched_getfiles();
DEBUGASSERT(list);
#ifdef CONFIG_FILE_MODE
# ifdef CONFIG_CPP_HAVE_WARNING
# warning "File creation not implemented"
# endif
/* If the file is opened for creation, then get the mode bits */
if (oflags & (O_WRONLY|O_CREAT) != 0)
{
va_list ap;
va_start(ap, oflags);
mode = va_arg(ap, mode_t);
va_end(ap);
}
#endif
/* Get an inode for this file */
inode = inode_find(path, &relpath);
if (!inode)
{
/* "O_CREAT is not set and the named file does not exist. Or, a
* directory component in pathname does not exist or is a dangling
* symbolic link."
*/
ret = ENOENT;
goto errout;
}
/* Verify that the inode is valid and either a "normal" or a mountpoint. We
* specifically exclude block drivers.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) || !inode->u.i_ops)
#else
if (!INODE_IS_DRIVER(inode) || !inode->u.i_ops)
#endif
{
ret = ENXIO;
goto errout_with_inode;
}
/* Make sure that the inode supports the requested access */
ret = inode_checkflags(inode, oflags);
if (ret < 0)
{
ret = -ret;
goto errout_with_inode;
}
/* Associate the inode with a file structure */
fd = files_allocate(inode, oflags, 0, 0);
if (fd < 0)
{
ret = EMFILE;
goto errout_with_inode;
}
/* 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.
*/
ret = OK;
if (inode->u.i_ops->open)
{
#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);
}
else
#endif
{
ret = inode->u.i_ops->open((FAR struct file*)&list->fl_files[fd]);
}
}
if (ret < 0)
{
ret = -ret;
goto errout_with_fd;
}
return fd;
errout_with_fd:
files_release(fd);
errout_with_inode:
inode_release(inode);
errout:
set_errno(ret);
return ERROR;
}
+357
View File
@@ -0,0 +1,357 @@
/****************************************************************************
* fs/vfs/fs_poll.c
*
* Copyright (C) 2008-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
* 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 <stdint.h>
#include <stdbool.h>
#include <poll.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/sched.h>
#include <nuttx/clock.h>
#include <nuttx/fs/fs.h>
#include <arch/irq.h>
#include "fs.h"
#ifndef CONFIG_DISABLE_POLL
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define poll_semgive(sem) sem_post(sem)
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: poll_semtake
****************************************************************************/
static void poll_semtake(FAR sem_t *sem)
{
/* Take the semaphore (perhaps waiting) */
while (sem_wait(sem) != 0)
{
/* The only case that an error should occur here is if
* the wait was awakened by a signal.
*/
ASSERT(get_errno() == EINTR);
}
}
/****************************************************************************
* Name: poll_fdsetup
*
* Description:
* Configure (or unconfigure) one file/socket descriptor for the poll
* operation. If fds and sem are non-null, then the poll is being setup.
* if fds and sem are NULL, then the poll is being torn down.
*
****************************************************************************/
#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;
/* Check for a valid file descriptor */
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
{
/* Perform the socket ioctl */
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
{
return net_poll(fd, fds, setup);
}
else
#endif
{
return -EBADF;
}
}
/* Get the thread-specific file list */
list = sched_getfiles();
DEBUGASSERT(list);
/* 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 */
ret = (int)inode->u.i_ops->poll(filep, fds, setup);
}
return ret;
}
#endif
/****************************************************************************
* Name: poll_setup
*
* Description:
* Setup the poll operation for each descriptor in the list.
*
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
static inline int poll_setup(FAR struct pollfd *fds, nfds_t nfds, sem_t *sem)
{
unsigned int i;
int ret;
/* Process each descriptor in the list */
for (i = 0; i < nfds; i++)
{
/* Setup the poll descriptor */
fds[i].sem = sem;
fds[i].revents = 0;
fds[i].priv = NULL;
/* Check for invalid descriptors. "If the value of fd is less than 0,
* events shall be ignored, and revents shall be set to 0 in that entry
* on return from poll()."
*
* NOTE: There is a potential problem here. If there is only one fd
* and if it is negative, then poll will hang. From my reading of the
* spec, that appears to be the correct behavior.
*/
if (fds[i].fd >= 0)
{
/* Set up the poll on this valid file descriptor */
ret = poll_fdsetup(fds[i].fd, &fds[i], true);
if (ret < 0)
{
return ret;
}
}
}
return OK;
}
#endif
/****************************************************************************
* Name: poll_teardown
*
* Description:
* Teardown the poll operation for each descriptor in the list and return
* the count of non-zero poll events.
*
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
static inline int poll_teardown(FAR struct pollfd *fds, nfds_t nfds, int *count)
{
unsigned int i;
int status;
int ret = OK;
/* Process each descriptor in the list */
*count = 0;
for (i = 0; i < nfds; i++)
{
/* Ignore negative descriptors */
if (fds[i].fd >= 0)
{
/* Teardown the poll */
status = poll_fdsetup(fds[i].fd, &fds[i], false);
if (status < 0)
{
ret = status;
}
}
/* Check if any events were posted */
if (fds[i].revents != 0)
{
(*count)++;
}
/* Un-initialize the poll structure */
fds[i].sem = NULL;
}
return ret;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: poll
*
* Description:
* poll() waits for one of a set of file descriptors to become ready to
* perform I/O. If none of the events requested (and no error) has
* occurred for any of the file descriptors, then poll() blocks until
* one of the events occurs.
*
* Inputs:
* fds - List of structures describing file descriptors to be monitored
* nfds - The number of entries in the list
* timeout - Specifies an upper limit on the time for which poll() will
* block in milliseconds. A negative value of timeout means an infinite
* timeout.
*
* Return:
* On success, the number of structures that have non-zero revents fields.
* A value of 0 indicates that the call timed out and no file descriptors
* were ready. On error, -1 is returned, and errno is set appropriately:
*
* EBADF - An invalid file descriptor was given in one of the sets.
* EFAULT - The fds address is invalid
* EINTR - A signal occurred before any requested event.
* EINVAL - The nfds value exceeds a system limit.
* ENOMEM - There was no space to allocate internal data structures.
* ENOSYS - One or more of the drivers supporting the file descriptor
* does not support the poll method.
*
****************************************************************************/
int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
{
struct timespec abstime;
irqstate_t flags;
sem_t sem;
int count = 0;
int ret;
sem_init(&sem, 0, 0);
ret = poll_setup(fds, nfds, &sem);
if (ret >= 0)
{
if (timeout == 0)
{
/* Poll returns immediately whether we have a poll event or not. */
}
else if (timeout > 0)
{
time_t sec;
uint32_t nsec;
/* Either wait for either a poll event(s) to occur or for the
* specified timeout to elapse with no event.
*
* NOTE: If a poll event is pending (i.e., the semaphore has already
* been incremented), sem_timedwait() will not wait, but will return
* immediately.
*/
sec = timeout / MSEC_PER_SEC;
nsec = (timeout - MSEC_PER_SEC * sec) * NSEC_PER_MSEC;
/* Make sure that the following are atomic by disabling interrupts.
* Interrupts will be re-enabled while we are waiting.
*/
flags = irqsave();
(void)clock_gettime(CLOCK_REALTIME, &abstime);
abstime.tv_sec += sec;
abstime.tv_nsec += nsec;
if (abstime.tv_nsec > NSEC_PER_SEC)
{
abstime.tv_sec++;
abstime.tv_nsec -= NSEC_PER_SEC;
}
(void)sem_timedwait(&sem, &abstime);
irqrestore(flags);
}
else
{
/* Wait for the poll event with no timeout */
poll_semtake(&sem);
}
/* Teardown the poll operation and get the count of events. Zero will be
* returned in the case of a timeout.
*/
ret = poll_teardown(fds, nfds, &count);
}
sem_destroy(&sem);
/* Check for errors */
if (ret < 0)
{
set_errno(-ret);
return ERROR;
}
return count;
}
#endif /* CONFIG_DISABLE_POLL */
+183
View File
@@ -0,0 +1,183 @@
/****************************************************************************
* fs/vfs/fs_read.c
*
* Copyright (C) 2007-2009, 2012-2013 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 "fs.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_read
*
* Description:
* This is the internal implementation of read().
*
* Parameters:
* file File structure instance
* buf User-provided to save the data
* nbytes The maximum size of the user-provided buffer
*
* 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.
*
****************************************************************************/
#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;
int ret = -EBADF;
DEBUGASSERT(filep);
inode = filep->f_inode;
/* Was this file opened for read access? */
if ((filep->f_oflags & O_RDOK) == 0)
{
/* No.. File is not read-able */
ret = -EACCES;
}
/* Is a driver or mountpoint registered? If so, does it support the read
* method?
*/
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
* signature and position in the operations vtable.
*/
ret = (int)inode->u.i_ops->read(filep, (char*)buf, (size_t)nbytes);
}
/* If an error occurred, set errno and return -1 (ERROR) */
if (ret < 0)
{
set_errno(-ret);
return ERROR;
}
/* Otherwise, return the number of bytes read */
return ret;
}
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
/****************************************************************************
* Name: read
*
* Description:
* The standard, POSIX read interface.
*
* Parameters:
* file File structure instance
* buf User-provided to save the data
* nbytes The maximum size of the user-provided buffer
*
* 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.
*
****************************************************************************/
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
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
{
/* No.. If networking is enabled, read() is the same as recv() with
* the flags parameter set to zero.
*/
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
return recv(fd, buf, nbytes, 0);
#else
/* No networking... it is a bad descriptor in any event */
set_errno(EBADF);
return ERROR;
#endif
}
#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.
*/
list = sched_getfiles();
DEBUGASSERT(list);
/* Then let file_read do all of the work */
return file_read(&list->fl_files[fd], buf, nbytes);
}
#endif
}
+255
View File
@@ -0,0 +1,255 @@
/****************************************************************************
* fs/vfs/fs_rename.c
*
* Copyright (C) 2007-2009, 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 <stdio.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include "fs.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#undef FS_HAVE_WRITABLE_MOUNTPOINT
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_WRITABLE_MOUNTPOINT 1
#endif
#undef FS_HAVE_PSEUDOFS_OPERATIONS
#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_PSEUDOFS_OPERATIONS 1
#endif
#undef FS_HAVE_RENAME
#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
# define FS_HAVE_RENAME 1
#endif
#ifdef FS_HAVE_RENAME
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Public Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: rename
*
* Description: Remove a file managed a mountpoint
*
****************************************************************************/
int rename(FAR const char *oldpath, FAR const char *newpath)
{
FAR struct inode *oldinode;
FAR struct inode *newinode;
const char *oldrelpath = NULL;
#ifndef CONFIG_DISABLE_MOUNTPOINT
const char *newrelpath = NULL;
#endif
int errcode;
int ret;
/* Ignore paths that are interpreted as the root directory which has no name
* and cannot be moved
*/
if (!oldpath || *oldpath == '\0' || oldpath[0] != '/' ||
!newpath || *newpath == '\0' || newpath[0] != '/')
{
return -EINVAL;
}
/* Get an inode that includes the oldpath */
oldinode = inode_find(oldpath, &oldrelpath);
if (!oldinode)
{
/* There is no inode that includes in this path */
errcode = ENOENT;
goto errout;
}
#ifndef CONFIG_DISABLE_MOUNTPOINT
/* Verify that the old inode is a valid mountpoint. */
if (INODE_IS_MOUNTPT(oldinode) && oldinode->u.i_mops)
{
/* Get an inode for the new relpath -- it should like on the same
* mountpoint
*/
newinode = inode_find(newpath, &newrelpath);
if (!newinode)
{
/* There is no mountpoint that includes in this path */
errcode = ENOENT;
goto errout_with_oldinode;
}
/* Verify that the two paths lie on the same mountpoint inode */
if (oldinode != newinode)
{
errcode = EXDEV;
goto errout_with_newinode;
}
/* Perform the rename operation using the relative paths
* at the common mountpoint.
*/
if (oldinode->u.i_mops->rename)
{
ret = oldinode->u.i_mops->rename(oldinode, oldrelpath, newrelpath);
if (ret < 0)
{
errcode = -ret;
goto errout_with_newinode;
}
}
else
{
errcode = ENOSYS;
goto errout_with_newinode;
}
/* Successfully renamed */
inode_release(newinode);
}
else
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
{
/* Create a new, empty inode at the destination location */
inode_semtake();
ret = inode_reserve(newpath, &newinode);
if (ret < 0)
{
/* It is an error if a node at newpath already exists in the tree
* OR if we fail to allocate memory for the new inode (and possibly
* any new intermediate path segments).
*/
inode_semgive();
errcode = EEXIST;
goto errout_with_oldinode;
}
/* Copy the inode state from the old inode to the newly allocated inode */
newinode->i_child = oldinode->i_child; /* Link to lower level inode */
newinode->i_flags = oldinode->i_flags; /* Flags for inode */
newinode->u.i_ops = oldinode->u.i_ops; /* Inode operations */
#ifdef CONFIG_FILE_MODE
newinode->i_mode = oldinode->i_mode; /* Access mode flags */
#endif
newinode->i_private = oldinode->i_private; /* Per inode driver private data */
/* We now have two copies of the inode. One with a reference count of
* zero (the new one), and one that may have multiple references
* including one by this logic (the old one)
*
* Remove the old inode. Because we hold a reference count on the
* inode, it will not be deleted now. It will be deleted when all of
* the references to to the inode have been released (perhaps when
* inode_release() is called below). inode_remove() should return
* -EBUSY to indicate that the inode was not deleted now.
*/
ret = inode_remove(oldpath);
if (ret < 0 && ret != -EBUSY)
{
/* Remove the new node we just recreated */
(void)inode_remove(newpath);
inode_semgive();
errcode = -ret;
goto errout_with_oldinode;
}
/* Remove all of the children from the unlinked inode */
oldinode->i_child = NULL;
inode_semgive();
}
#else
{
errcode = ENXIO;
goto errout;
}
#endif
/* Successfully renamed */
inode_release(oldinode);
return OK;
#ifndef CONFIG_DISABLE_MOUNTPOINT
errout_with_newinode:
inode_release(newinode);
#endif
errout_with_oldinode:
inode_release(oldinode);
errout:
set_errno(errcode);
return ERROR;
}
#endif /* FS_HAVE_RENAME */
+198
View File
@@ -0,0 +1,198 @@
/****************************************************************************
* fs/vfs/fs_rmdir.c
*
* Copyright (C) 2007-2009, 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 <unistd.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include "fs.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#undef FS_HAVE_WRITABLE_MOUNTPOINT
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_WRITABLE_MOUNTPOINT 1
#endif
#undef FS_HAVE_PSEUDOFS_OPERATIONS
#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_PSEUDOFS_OPERATIONS 1
#endif
#undef FS_HAVE_RMDIR
#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
# define FS_HAVE_RMDIR 1
#endif
#ifdef FS_HAVE_RMDIR
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Public Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: rmdir
*
* Description: Remove a file managed a mountpoint
*
****************************************************************************/
int rmdir(FAR const char *pathname)
{
FAR struct inode *inode;
const char *relpath = NULL;
int errcode;
/* Get an inode for this file. inode_find() automatically increments the
* reference count on the inode if one is found.
*/
inode = inode_find(pathname, &relpath);
if (!inode)
{
/* There is no inode that includes in this path */
errcode = ENOENT;
goto errout;
}
#ifndef CONFIG_DISABLE_MOUNTPOINT
/* Check if the inode is a valid mountpoint. */
if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops)
{
/* Perform the rmdir operation using the relative path
* from the mountpoint.
*/
if (inode->u.i_mops->rmdir)
{
int ret = inode->u.i_mops->rmdir(inode, relpath);
if (ret < 0)
{
errcode = -ret;
goto errout_with_inode;
}
}
else
{
errcode = ENOSYS;
goto errout_with_inode;
}
}
else
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
/* If this is a "dangling" pseudo-directory node (i.e., it has no operations)
* then rmdir should remove the node.
*/
if (!inode->u.i_ops)
{
int ret;
/* If the directory inode has children, however, then it cannot be
* removed.
*/
if (inode->i_child)
{
errcode = ENOTEMPTY;
goto errout_with_inode;
}
/* Remove the inode. NOTE: Because we hold a reference count on the
* inode, it will not be deleted now. But probably when inode_release()
* is called below. inode_remove should return -EBUSY to indicate that
* the inode was not deleted now.
*/
inode_semtake();
ret = inode_remove(pathname);
inode_semgive();
if (ret < 0 && ret != -EBUSY)
{
errcode = -ret;
goto errout_with_inode;
}
}
else
{
errcode = ENOTDIR;
goto errout_with_inode;
}
#else
{
errcode = ENXIO;
goto errout_with_inode;
}
#endif
/* Successfully removed the directory */
inode_release(inode);
return OK;
errout_with_inode:
inode_release(inode);
errout:
set_errno(errcode);
return ERROR;
}
#endif /* FS_HAVE_RMDIR */
+270
View File
@@ -0,0 +1,270 @@
/****************************************************************************
* fs/vfs/fs_select.c
*
* Copyright (C) 2008-2009, 2012-2013 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/select.h>
#include <string.h>
#include <poll.h>
#include <time.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include "fs.h"
#ifndef CONFIG_DISABLE_POLL
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: select
*
* Description:
* select() allows a program to monitor multiple file descriptors, waiting
* until one or more of the file descriptors become "ready" for some class
* of I/O operation (e.g., input possible). A file descriptor is
* considered ready if it is possible to perform the corresponding I/O
* operation (e.g., read(2)) without blocking.
*
* NOTE: poll() is the fundamental API for performing such monitoring
* operation under NuttX. select() is provided for compatibility and
* is simply a layer of added logic on top of poll(). As such, select()
* is more wasteful of resources and poll() is the recommended API to be
* used.
*
* Input parameters:
* nfds - the maximum fd number (+1) of any descriptor in any of the
* three sets.
* readfds - the set of descriptions to monitor for read-ready events
* writefds - the set of descriptions to monitor for write-ready events
* exceptfds - the set of descriptions to monitor for error events
* timeout - Return at this time if none of these events of interest
* occur.
*
* Return:
* 0: Timer expired
* >0: The number of bits set in the three sets of descriptors
* -1: An error occurred (errno will be set appropriately)
*
****************************************************************************/
int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds,
FAR fd_set *exceptfds, FAR struct timeval *timeout)
{
struct pollfd *pollset;
int fd;
int npfds;
int msec;
int ndx;
int ret;
/* How many pollfd structures do we need to allocate? */
/* Initialize the descriptor list for poll() */
for (fd = 0, npfds = 0; fd < nfds; fd++)
{
/* Check if any monitor operation is requested on this fd */
if ((readfds && FD_ISSET(fd, readfds)) ||
(writefds && FD_ISSET(fd, writefds)) ||
(exceptfds && FD_ISSET(fd, exceptfds)))
{
/* Yes.. increment the count of pollfds structures needed */
npfds++;
}
}
/* Allocate the descriptor list for poll() */
pollset = (struct pollfd *)kmm_zalloc(npfds * sizeof(struct pollfd));
if (!pollset)
{
set_errno(ENOMEM);
return ERROR;
}
/* Initialize the descriptor list for poll() */
for (fd = 0, ndx = 0; fd < nfds; fd++)
{
int incr = 0;
/* The readfs set holds the set of FDs that the caller can be assured
* of reading from without blocking. Note that POLLHUP is included as
* a read-able condition. POLLHUP will be reported at the end-of-file
* or when a connection is lost. In either case, the read() can then
* be performed without blocking.
*/
if (readfds && FD_ISSET(fd, readfds))
{
pollset[ndx].fd = fd;
pollset[ndx].events |= POLLIN;
incr = 1;
}
/* The writefds set holds the set of FDs that the caller can be assured
* of writing to without blocking.
*/
if (writefds && FD_ISSET(fd, writefds))
{
pollset[ndx].fd = fd;
pollset[ndx].events |= POLLOUT;
incr = 1;
}
/* The exceptfds set holds the set of FDs that are watched for exceptions */
if (exceptfds && FD_ISSET(fd, exceptfds))
{
pollset[ndx].fd = fd;
incr = 1;
}
ndx += incr;
}
DEBUGASSERT(ndx == npfds);
/* Convert the timeout to milliseconds */
if (timeout)
{
/* Calculate the timeout in milliseconds */
msec = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
}
else
{
/* Any negative value of msec means no timeout */
msec = -1;
}
/* Then let poll do all of the real work. */
ret = poll(pollset, npfds, msec);
/* Now set up the return values */
if (readfds)
{
memset(readfds, 0, sizeof(fd_set));
}
if (writefds)
{
memset(writefds, 0, sizeof(fd_set));
}
if (exceptfds)
{
memset(exceptfds, 0, sizeof(fd_set));
}
/* Convert the poll descriptor list back into selects 3 bitsets */
if (ret > 0)
{
ret = 0;
for (ndx = 0; ndx < npfds; ndx++)
{
/* Check for read conditions. Note that POLLHUP is included as a
* read condition. POLLHUP will be reported when no more data will
* be available (such as when a connection is lost). In either
* case, the read() can then be performed without blocking.
*/
if (readfds)
{
if (pollset[ndx].revents & (POLLIN|POLLHUP))
{
FD_SET(pollset[ndx].fd, readfds);
ret++;
}
}
/* Check for write conditions */
if (writefds)
{
if (pollset[ndx].revents & POLLOUT)
{
FD_SET(pollset[ndx].fd, writefds);
ret++;
}
}
/* Check for exceptions */
if (exceptfds)
{
if (pollset[ndx].revents & POLLERR)
{
FD_SET(pollset[ndx].fd, exceptfds);
ret++;
}
}
}
}
kmm_free(pollset);
return ret;
}
#endif /* CONFIG_DISABLE_POLL */
+154
View File
@@ -0,0 +1,154 @@
/************************************************************************
* fs/vfs/fs_sendfile.c
*
* Copyright (C) 2007, 2009, 2011, 2013 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/sendfile.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <nuttx/sched.h>
#include <nuttx/net/net.h>
#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NET_SENDFILE
/************************************************************************
* Private types
************************************************************************/
/************************************************************************
* Private Variables
************************************************************************/
/************************************************************************
* Public Variables
************************************************************************/
/************************************************************************
* Private Functions
************************************************************************/
/************************************************************************
* Public Functions
************************************************************************/
/************************************************************************
* Name: sendfile
*
* Description:
* sendfile() copies data between one file descriptor and another.
* Used with file descriptors it basically just wraps a sequence of
* reads() and writes() to perform a copy.
*
* If the destination descriptor is a socket, it gives a better
* performance than simple reds() and writes(). The data is read directly
* into the net buffer and the whole tcp window is filled if possible.
*
* NOTE: This interface is *not* specified in POSIX.1-2001, or other
* standards. The implementation here is very similar to the Linux
* sendfile interface. Other UNIX systems implement sendfile() with
* different semantics and prototypes. sendfile() should not be used
* in portable programs.
*
* Input Parmeters:
* infd - A file (or socket) descriptor opened for reading
* outfd - A descriptor opened for writing.
* offset - If 'offset' is not NULL, then it points to a variable
* holding the file offset from which sendfile() will start
* reading data from 'infd'. When sendfile() returns, this
* variable will be set to the offset of the byte following
* the last byte that was read. If 'offset' is not NULL,
* then sendfile() does not modify the current file offset of
* 'infd'; otherwise the current file offset is adjusted to
* reflect the number of bytes read from 'infd.'
*
* If 'offset' is NULL, then data will be read from 'infd'
* starting at the current file offset, and the file offset
* will be updated by the call.
* count - The number of bytes to copy between the file descriptors.
*
* Returned Value:
* If the transfer was successful, the number of bytes written to outfd is
* returned. On error, -1 is returned, and errno is set appropriately.
* There error values are those returned by read() or write() plus:
*
* EINVAL - Bad input parameters.
* ENOMEM - Could not allocated an I/O buffer
*
************************************************************************/
ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count)
{
#if defined(CONFIG_NET_TCP) && CONFIG_NSOCKET_DESCRIPTORS > 0
/* Check the destination file descriptor: Is it a (probable) file
* descriptor? Check the source file: Is it a normal file?
*/
if ((unsigned int)outfd >= CONFIG_NFILE_DESCRIPTORS &&
(unsigned int)infd < CONFIG_NFILE_DESCRIPTORS)
{
FAR struct filelist *list;
/* This appears to be a file-to-socket transfer. Get the thread-
* specific file list.
*/
list = sched_getfiles();
DEBUGASSERT(list);
/* Then let net_sendfile do the work. */
return net_sendfile(outfd, &list->fl_files[infd], offset, count);
}
else
#endif
{
/* No... then this is probably a file-to-file transfer. The generic
* lib_sendfile() can handle that case.
*/
return lib_sendfile(outfd, infd, offset, count);
}
}
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NET_SENDFILE */
+224
View File
@@ -0,0 +1,224 @@
/****************************************************************************
* fs/vfs/fs_stat.c
*
* Copyright (C) 2007-2009, 2012 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/stat.h>
#include <string.h>
#include <sched.h>
#include <errno.h>
#include "fs.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: statpseudo
****************************************************************************/
static inline int statpseudo(FAR struct inode *inode, FAR struct stat *buf)
{
/* Most of the stat entries just do not apply */
memset(buf, 0, sizeof(struct stat) );
if (inode->u.i_ops)
{
if (inode->u.i_ops->read)
{
buf->st_mode = S_IROTH|S_IRGRP|S_IRUSR;
}
if (inode->u.i_ops->write)
{
buf->st_mode |= S_IWOTH|S_IWGRP|S_IWUSR;
}
if (INODE_IS_MOUNTPT(inode))
{
buf->st_mode |= S_IFDIR;
}
else if (INODE_IS_BLOCK(inode))
{
/* What is it also has child inodes? */
buf->st_mode |= S_IFBLK;
}
else
{
/* What is it if it also has child inodes? */
buf->st_mode |= S_IFCHR;
}
}
else
{
/* If it has no operations, then it must just be a intermediate
* node in the inode tree. It is something like a directory.
* We'll say that all pseudo-directories are read-able but not
* write-able.
*/
buf->st_mode |= S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR;
}
return OK;
}
/****************************************************************************
* Name: statroot
****************************************************************************/
static inline int statroot(FAR struct stat *buf)
{
/* There is no inode associated with the fake root directory */
memset(buf, 0, sizeof(struct stat) );
buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR;
return OK;
}
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: stat
*
* Returned Value:
* Zero on success; -1 on failure with errno set:
*
* EACCES Search permission is denied for one of the directories in the
* path prefix of path.
* EFAULT Bad address.
* ENOENT A component of the path path does not exist, or the path is an
* empty string.
* ENOMEM Out of memory
* ENOTDIR A component of the path is not a directory.
*
****************************************************************************/
int stat(FAR const char *path, FAR struct stat *buf)
{
FAR struct inode *inode;
const char *relpath = NULL;
int ret = OK;
/* Sanity checks */
if (!path || !buf)
{
ret = EFAULT;
goto errout;
}
if (!path[0])
{
ret = ENOENT;
goto errout;
}
/* Check for the fake root directory (which has no inode) */
if (strcmp(path, "/") == 0)
{
return statroot(buf);
}
/* Get an inode for this file */
inode = inode_find(path, &relpath);
if (!inode)
{
/* This name does not refer to a psudeo-inode and there is no
* mountpoint that includes in this path.
*/
ret = ENOENT;
goto errout;
}
/* The way we handle the stat depends on the type of inode that we
* are dealing with.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_MOUNTPT(inode))
{
/* The node is a file system mointpoint. Verify that the mountpoint
* supports the stat() method
*/
if (inode->u.i_mops && inode->u.i_mops->stat)
{
/* Perform the stat() operation */
ret = inode->u.i_mops->stat(inode, relpath, buf);
}
}
else
#endif
{
/* The node is part of the root pseudo file system */
ret = statpseudo(inode, buf);
}
/* Check if the stat operation was successful */
if (ret < 0)
{
ret = -ret;
goto errout_with_inode;
}
/* Successfully stat'ed the file */
inode_release(inode);
return OK;
/* Failure conditions always set the errno appropriately */
errout_with_inode:
inode_release(inode);
errout:
set_errno(ret);
return ERROR;
}
+165
View File
@@ -0,0 +1,165 @@
/****************************************************************************
* fs/vfs/fs_statfs.c
*
* Copyright (C) 2007-2009, 2012 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/statfs.h>
#include <string.h>
#include <limits.h>
#include <sched.h>
#include <errno.h>
#include "fs.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: statpseudo
****************************************************************************/
static inline int statpseudofs(FAR struct inode *inode, FAR struct statfs *buf)
{
memset(buf, 0, sizeof(struct statfs));
buf->f_type = PROC_SUPER_MAGIC;
buf->f_namelen = NAME_MAX;
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: stat
*
* Return: Zero on success; -1 on failure with errno set:
*
* EACCES Search permission is denied for one of the directories in the
* path prefix of path.
* EFAULT Bad address.
* ENOENT A component of the path path does not exist, or the path is an
* empty string.
* ENOMEM Out of memory
* ENOTDIR A component of the path is not a directory.
* ENOSYS The file system does not support this call.
*
****************************************************************************/
int statfs(FAR const char *path, FAR struct statfs *buf)
{
FAR struct inode *inode;
FAR const char *relpath = NULL;
int ret = OK;
/* Sanity checks */
if (!path || !buf)
{
ret = EFAULT;
goto errout;
}
if (!path[0])
{
ret = ENOENT;
goto errout;
}
/* Get an inode for this file */
inode = inode_find(path, &relpath);
if (!inode)
{
/* This name does not refer to a psudeo-inode and there is no
* mountpoint that includes in this path.
*/
ret = ENOENT;
goto errout;
}
/* The way we handle the statfs depends on the type of inode that we
* are dealing with.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_MOUNTPT(inode))
{
/* The node is a file system mointpoint. Verify that the mountpoint
* supports the statfs() method
*/
if (inode->u.i_mops && inode->u.i_mops->statfs)
{
/* Perform the statfs() operation */
ret = inode->u.i_mops->statfs(inode, buf);
}
}
else
#endif
{
/* The node is part of the root pseudo file system */
ret = statpseudofs(inode, buf);
}
/* Check if the statfs operation was successful */
if (ret < 0)
{
ret = -ret;
goto errout_with_inode;
}
/* Successfully statfs'ed the file */
inode_release(inode);
return OK;
/* Failure conditions always set the errno appropriately */
errout_with_inode:
inode_release(inode);
errout:
set_errno(ret);
return ERROR;
}
+205
View File
@@ -0,0 +1,205 @@
/****************************************************************************
* fs/vfs/fs_unlink.c
*
* Copyright (C) 2007-2009 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 <unistd.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include "fs.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#undef FS_HAVE_WRITABLE_MOUNTPOINT
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_WRITABLE_MOUNTPOINT 1
#endif
#undef FS_HAVE_PSEUDOFS_OPERATIONS
#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
# define FS_HAVE_PSEUDOFS_OPERATIONS 1
#endif
#undef FS_HAVE_UNLINK
#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
# define FS_HAVE_UNLINK 1
#endif
#ifdef FS_HAVE_UNLINK
/****************************************************************************
* Private Variables
****************************************************************************/
/****************************************************************************
* Public Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: unlink
*
* Description: Remove a file managed a mountpoint
*
****************************************************************************/
int unlink(FAR const char *pathname)
{
FAR struct inode *inode;
const char *relpath = NULL;
int errcode;
int ret;
/* Get an inode for this file */
inode = inode_find(pathname, &relpath);
if (!inode)
{
/* There is no inode that includes in this path */
errcode = ENOENT;
goto errout;
}
#ifndef CONFIG_DISABLE_MOUNTPOINT
/* Check if the inode is a valid mountpoint. */
if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops)
{
/* Perform the unlink operation using the relative path at the
* mountpoint.
*/
if (inode->u.i_mops->unlink)
{
ret = inode->u.i_mops->unlink(inode, relpath);
if (ret < 0)
{
errcode = -ret;
goto errout_with_inode;
}
}
else
{
errcode = ENOSYS;
goto errout_with_inode;
}
}
else
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
/* If this is a "dangling" pseudo-file node (i.e., it has operations) then rm
* should remove the node.
*/
if (inode->u.i_ops)
{
/* If this is a pseudo-file node (i.e., it has no operations)
* then rmdir should remove the node.
*/
if (inode->u.i_ops)
{
inode_semtake();
/* Refuse to unlink the inode if it has children. I.e., if it is
* functioning as a directory and the directory is not empty.
*/
if (inode->i_child != NULL)
{
errcode = ENOTEMPTY;
inode_semgive();
goto errout_with_inode;
}
/* Remove the old inode. Because we hold a reference count on the
* inode, it will not be deleted now. It will be deleted when all
* of the references to to the inode have been released (perhaps
* when inode_release() is called below). inode_remove() will
* return -EBUSY to indicate that the inode was not deleted now.
*/
ret = inode_remove(pathname);
inode_semgive();
if (ret < 0 && ret != -EBUSY)
{
errcode = -ret;
goto errout_with_inode;
}
}
else
{
errcode = EISDIR;
goto errout_with_inode;
}
}
#else
{
errcode = ENXIO;
goto errout_with_inode;
}
#endif
/* Successfully unlinked */
inode_release(inode);
return OK;
errout_with_inode:
inode_release(inode);
errout:
set_errno(errcode);
return ERROR;
}
#endif /* FS_HAVE_UNLINK */
+195
View File
@@ -0,0 +1,195 @@
/****************************************************************************
* fs/vfs/fs_write.c
*
* Copyright (C) 2007-2009, 2012-2013 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 <unistd.h>
#include <fcntl.h>
#include <sched.h>
#include <errno.h>
#include <assert.h>
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
# include <sys/socket.h>
#endif
#include "fs.h"
/****************************************************************************
* Private Functions
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
static inline ssize_t file_write(int fd, 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;
goto errout;
}
/* Is a driver registered? Does it support the write method? */
inode = filep->f_inode;
if (!inode || !inode->u.i_ops || !inode->u.i_ops->write)
{
err = EBADF;
goto errout;
}
/* Yes, then let the driver perform the write */
ret = inode->u.i_ops->write(filep, buf, nbytes);
if (ret < 0)
{
err = -ret;
goto errout;
}
return ret;
errout:
set_errno(err);
return ERROR;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/***************************************************************************
* Name: write
*
* Description:
* write() writes up to nytes bytes to the file referenced by the file
* descriptor fd from the buffer starting at buf.
*
* Parameters:
* fd file descriptor (or socket descriptor) to write to
* buf Data to write
* nbytes Length of data to write
*
* Returned Value:
* On success, the number of bytes written are returned (zero indicates
* nothing was written). On error, -1 is returned, and errno is set appro-
* priately:
*
* EAGAIN
* Non-blocking I/O has been selected using O_NONBLOCK and the write
* would block.
* EBADF
* fd is not a valid file descriptor or is not open for writing.
* EFAULT
* buf is outside your accessible address space.
* EFBIG
* An attempt was made to write a file that exceeds the implementation
* defined maximum file size or the process' file size limit, or
* to write at a position past the maximum allowed offset.
* EINTR
* The call was interrupted by a signal before any data was written.
* EINVAL
* fd is attached to an object which is unsuitable for writing; or
* the file was opened with the O_DIRECT flag, and either the address
* specified in buf, the value specified in count, or the current
* file offset is not suitably aligned.
* EIO
* A low-level I/O error occurred while modifying the inode.
* ENOSPC
* The device containing the file referred to by fd has no room for
* the data.
* EPIPE
* fd is connected to a pipe or socket whose reading end is closed.
* When this happens the writing process will also receive a SIGPIPE
* signal. (Thus, the write return value is seen only if the program
* catches, blocks or ignores this signal.)
*
* Assumptions:
*
********************************************************************************************/
ssize_t write(int fd, FAR const void *buf, size_t nbytes)
{
/* Did we get a valid file descriptor? */
#if CONFIG_NFILE_DESCRIPTORS > 0
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
{
/* Write to a socket descriptor is equivalent to send with flags == 0 */
#if defined(CONFIG_NET_TCP) && CONFIG_NSOCKET_DESCRIPTORS > 0
return send(fd, buf, nbytes, 0);
#else
set_errno(EBADF);
return ERROR;
#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);
#endif
}