mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 03:45:50 +08:00
Major structure of file system functions to better support asynchronous I/O. Respository should not be trusted until I have a chance to verify everything
This commit is contained in:
+4
-1
@@ -67,10 +67,12 @@
|
|||||||
* pre-allocated, the number pre-allocated controlled by CONFIG_FS_NAIOC.
|
* pre-allocated, the number pre-allocated controlled by CONFIG_FS_NAIOC.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct file;
|
||||||
struct aio_container_s
|
struct aio_container_s
|
||||||
{
|
{
|
||||||
dq_entry_t aioc_link; /* Supports a doubly linked list */
|
dq_entry_t aioc_link; /* Supports a doubly linked list */
|
||||||
FAR struct aiocb *aioc_aiocbp; /* The contained AIO control block */
|
FAR struct aiocb *aioc_aiocbp; /* The contained AIO control block */
|
||||||
|
FAR struct file *aioc_filep; /* File structure to use with the I/O */
|
||||||
struct work_s aioc_work; /* Used to defer I/O to the work thread */
|
struct work_s aioc_work; /* Used to defer I/O to the work thread */
|
||||||
pid_t aioc_pid; /* ID of the waiting task */
|
pid_t aioc_pid; /* ID of the waiting task */
|
||||||
uint8_t aioc_prio; /* Priority of the waiting task */
|
uint8_t aioc_prio; /* Priority of the waiting task */
|
||||||
@@ -182,7 +184,8 @@ void aioc_free(FAR struct aio_container_s *aioc);
|
|||||||
* Returned Value:
|
* Returned Value:
|
||||||
* A reference to the new AIO control block container. This function
|
* A reference to the new AIO control block container. This function
|
||||||
* will not fail but will wait if necessary for the resources to perform
|
* will not fail but will wait if necessary for the resources to perform
|
||||||
* this operation.
|
* this operation. NULL will be returned on certain errors with the
|
||||||
|
* errno value already set appropriately.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
|||||||
+12
-5
@@ -46,6 +46,7 @@
|
|||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#include <nuttx/wqueue.h>
|
#include <nuttx/wqueue.h>
|
||||||
|
#include <nuttx/fs/fs.h>
|
||||||
|
|
||||||
#include "aio/aio.h"
|
#include "aio/aio.h"
|
||||||
|
|
||||||
@@ -103,9 +104,9 @@ static void aio_fsync_worker(FAR void *arg)
|
|||||||
pid = aioc->aioc_pid;
|
pid = aioc->aioc_pid;
|
||||||
aiocbp = aioc_decant(aioc);
|
aiocbp = aioc_decant(aioc);
|
||||||
|
|
||||||
/* Perform the fsync using aio_fildes */
|
/* Perform the fsync using aioc_filep */
|
||||||
|
|
||||||
ret = fsync(aiocbp->aio_fildes);
|
ret = file_fsync(aioc->aioc_filep);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
int errcode = get_errno();
|
int errcode = get_errno();
|
||||||
@@ -218,12 +219,18 @@ int aio_fsync(int op, FAR struct aiocb *aiocbp)
|
|||||||
aiocbp->aio_result = -EINPROGRESS;
|
aiocbp->aio_result = -EINPROGRESS;
|
||||||
aiocbp->aio_priv = NULL;
|
aiocbp->aio_priv = NULL;
|
||||||
|
|
||||||
/* Create a container for the AIO control block. This will not fail but
|
/* Create a container for the AIO control block. This may cause us to
|
||||||
* may cause us to block if there are insufficient resources to satisfy
|
* block if there are insufficient resources to satisfy the request.
|
||||||
* the request.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
aioc = aio_contain(aiocbp);
|
aioc = aio_contain(aiocbp);
|
||||||
|
if (!aioc)
|
||||||
|
{
|
||||||
|
/* The errno has already been set (probably EBADF) */
|
||||||
|
|
||||||
|
aiocbp->aio_result = -get_errno();
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* Defer the work to the worker thread */
|
/* Defer the work to the worker thread */
|
||||||
|
|
||||||
|
|||||||
+12
-6
@@ -106,14 +106,14 @@ static void aio_read_worker(FAR void *arg)
|
|||||||
|
|
||||||
/* Perform the read using:
|
/* Perform the read using:
|
||||||
*
|
*
|
||||||
* aio_fildes - File descriptor
|
* aioc_filep - File structure pointer
|
||||||
* aio_buf - Location of buffer
|
* aio_buf - Location of buffer
|
||||||
* aio_nbytes - Length of transfer
|
* aio_nbytes - Length of transfer
|
||||||
* aio_offset - File offset
|
* aio_offset - File offset
|
||||||
*/
|
*/
|
||||||
|
|
||||||
nread = pread(aiocbp->aio_fildes, (FAR void *)aiocbp->aio_buf,
|
nread = file_pread(aioc->aioc_filep, (FAR void *)aiocbp->aio_buf,
|
||||||
aiocbp->aio_nbytes, aiocbp->aio_offset);
|
aiocbp->aio_nbytes, aiocbp->aio_offset);
|
||||||
|
|
||||||
/* Set the result of the read */
|
/* Set the result of the read */
|
||||||
|
|
||||||
@@ -266,12 +266,18 @@ int aio_read(FAR struct aiocb *aiocbp)
|
|||||||
aiocbp->aio_result = -EINPROGRESS;
|
aiocbp->aio_result = -EINPROGRESS;
|
||||||
aiocbp->aio_priv = NULL;
|
aiocbp->aio_priv = NULL;
|
||||||
|
|
||||||
/* Create a container for the AIO control block. This will not fail but
|
/* Create a container for the AIO control block. This may cause us to
|
||||||
* may cause us to block if there are insufficient resources to satisfy
|
* block if there are insufficient resources to satisfy the request.
|
||||||
* the request.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
aioc = aio_contain(aiocbp);
|
aioc = aio_contain(aiocbp);
|
||||||
|
if (!aioc)
|
||||||
|
{
|
||||||
|
/* The errno has already been set (probably EBADF) */
|
||||||
|
|
||||||
|
aiocbp->aio_result = -get_errno();
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* Defer the work to the worker thread */
|
/* Defer the work to the worker thread */
|
||||||
|
|
||||||
|
|||||||
+34
-12
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
@@ -73,6 +74,21 @@
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: file_fcntl
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static inline int file_fcntl(FAR struct file *filep, int cmd, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
va_start(ap, cmd);
|
||||||
|
ret = file_vfcntl(filep, cmd, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: aio_write_worker
|
* Name: aio_write_worker
|
||||||
*
|
*
|
||||||
@@ -108,7 +124,7 @@ static void aio_write_worker(FAR void *arg)
|
|||||||
|
|
||||||
/* Call fcntl(F_GETFL) to get the file open mode. */
|
/* Call fcntl(F_GETFL) to get the file open mode. */
|
||||||
|
|
||||||
oflags = fcntl(aiocbp->aio_fildes, F_GETFL);
|
oflags = file_fcntl(aioc->aioc_filep, F_GETFL);
|
||||||
if (oflags < 0)
|
if (oflags < 0)
|
||||||
{
|
{
|
||||||
int errcode = get_errno();
|
int errcode = get_errno();
|
||||||
@@ -119,7 +135,7 @@ static void aio_write_worker(FAR void *arg)
|
|||||||
{
|
{
|
||||||
/* Perform the write using:
|
/* Perform the write using:
|
||||||
*
|
*
|
||||||
* aio_fildes - File descriptor
|
* aioc_filep - File descriptor
|
||||||
* aio_buf - Location of buffer
|
* aio_buf - Location of buffer
|
||||||
* aio_nbytes - Length of transfer
|
* aio_nbytes - Length of transfer
|
||||||
* aio_offset - File offset
|
* aio_offset - File offset
|
||||||
@@ -131,16 +147,16 @@ static void aio_write_worker(FAR void *arg)
|
|||||||
{
|
{
|
||||||
/* Append to the current file position */
|
/* Append to the current file position */
|
||||||
|
|
||||||
nwritten = write(aiocbp->aio_fildes,
|
nwritten = file_write(aioc->aioc_filep,
|
||||||
(FAR const void *)aiocbp->aio_buf,
|
(FAR const void *)aiocbp->aio_buf,
|
||||||
aiocbp->aio_nbytes);
|
aiocbp->aio_nbytes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nwritten = pwrite(aiocbp->aio_fildes,
|
nwritten = file_pwrite(aioc->aioc_filep,
|
||||||
(FAR const void *)aiocbp->aio_buf,
|
(FAR const void *)aiocbp->aio_buf,
|
||||||
aiocbp->aio_nbytes,
|
aiocbp->aio_nbytes,
|
||||||
aiocbp->aio_offset);
|
aiocbp->aio_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the result of the write */
|
/* Set the result of the write */
|
||||||
@@ -297,12 +313,18 @@ int aio_write(FAR struct aiocb *aiocbp)
|
|||||||
aiocbp->aio_result = -EINPROGRESS;
|
aiocbp->aio_result = -EINPROGRESS;
|
||||||
aiocbp->aio_priv = NULL;
|
aiocbp->aio_priv = NULL;
|
||||||
|
|
||||||
/* Create a container for the AIO control block. This will not fail but
|
/* Create a container for the AIO control block. This may cause us to
|
||||||
* may cause us to block if there are insufficient resources to satisfy
|
* block if there are insufficient resources to satisfy the request.
|
||||||
* the request.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
aioc = aio_contain(aiocbp);
|
aioc = aio_contain(aiocbp);
|
||||||
|
if (!aioc)
|
||||||
|
{
|
||||||
|
/* The errno has already been set (probably EBADF) */
|
||||||
|
|
||||||
|
aiocbp->aio_result = -get_errno();
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* Defer the work to the worker thread */
|
/* Defer the work to the worker thread */
|
||||||
|
|
||||||
|
|||||||
+16
-1
@@ -41,6 +41,8 @@
|
|||||||
|
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
|
|
||||||
|
#include <nuttx/fs.h>
|
||||||
|
|
||||||
#include "aio/aio.h"
|
#include "aio/aio.h"
|
||||||
|
|
||||||
#ifdef CONFIG_FS_AIO
|
#ifdef CONFIG_FS_AIO
|
||||||
@@ -80,15 +82,27 @@
|
|||||||
* Returned Value:
|
* Returned Value:
|
||||||
* A reference to the new AIO control block container. This function
|
* A reference to the new AIO control block container. This function
|
||||||
* will not fail but will wait if necessary for the resources to perform
|
* will not fail but will wait if necessary for the resources to perform
|
||||||
* this operation.
|
* this operation. NULL will be returned on certain errors with the
|
||||||
|
* errno value already set appropriately.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
FAR struct aio_container_s *aio_contain(FAR struct aiocb *aiocbp)
|
FAR struct aio_container_s *aio_contain(FAR struct aiocb *aiocbp)
|
||||||
{
|
{
|
||||||
FAR struct aio_container_s *aioc;
|
FAR struct aio_container_s *aioc;
|
||||||
|
FAR struct file *filep;
|
||||||
struct sched_param param;
|
struct sched_param param;
|
||||||
|
|
||||||
|
/* Get the file structure corresponding to the file descriptor. */
|
||||||
|
|
||||||
|
filep = fs_getfilep(aiocbp->aio_fildes);
|
||||||
|
if (!filep)
|
||||||
|
{
|
||||||
|
/* The errno value has already been set */
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate the AIO control block container, waiting for one to become
|
/* Allocate the AIO control block container, waiting for one to become
|
||||||
* available if necessary. This should never fail.
|
* available if necessary. This should never fail.
|
||||||
*/
|
*/
|
||||||
@@ -100,6 +114,7 @@ FAR struct aio_container_s *aio_contain(FAR struct aiocb *aiocbp)
|
|||||||
|
|
||||||
memset(aioc, 0, sizeof(struct aio_container_s));
|
memset(aioc, 0, sizeof(struct aio_container_s));
|
||||||
aioc->aioc_aiocbp = aiocbp;
|
aioc->aioc_aiocbp = aiocbp;
|
||||||
|
aioc->aioc_filep = filep;
|
||||||
aioc->aioc_pid = getpid();
|
aioc->aioc_pid = getpid();
|
||||||
|
|
||||||
DEBUGVERIFY(sched_getparam (aioc->aioc_pid, ¶m));
|
DEBUGVERIFY(sched_getparam (aioc->aioc_pid, ¶m));
|
||||||
|
|||||||
+2
-2
@@ -200,7 +200,7 @@ void files_releaselist(FAR struct filelist *list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: files_dup
|
* Name: file_dup2
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Assign an inode to a specific files structure. This is the heart of
|
* Assign an inode to a specific files structure. This is the heart of
|
||||||
@@ -208,7 +208,7 @@ void files_releaselist(FAR struct filelist *list)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int files_dup(FAR struct file *filep1, FAR struct file *filep2)
|
int file_dup2(FAR struct file *filep1, FAR struct file *filep2)
|
||||||
{
|
{
|
||||||
FAR struct filelist *list;
|
FAR struct filelist *list;
|
||||||
FAR struct inode *inode;
|
FAR struct inode *inode;
|
||||||
|
|||||||
+4
-4
@@ -69,10 +69,10 @@ else
|
|||||||
|
|
||||||
# Common file/socket descriptor support
|
# 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_close.c fs_dup.c fs_dup2.c fs_fcntl.c fs_dupfd.c fs_dupfd2.c
|
||||||
CSRCS += fs_fsync.c fs_ioctl.c fs_lseek.c fs_mkdir.c fs_open.c fs_poll.c
|
CSRCS += fs_fsync.c fs_getfilep.c fs_ioctl.c fs_lseek.c fs_mkdir.c fs_open.c
|
||||||
CSRCS += fs_read.c fs_rename.c fs_rmdir.c fs_stat.c fs_statfs.c fs_select.c
|
CSRCS += fs_poll.c fs_read.c fs_rename.c fs_rmdir.c fs_stat.c fs_statfs.c
|
||||||
CSRCS += fs_unlink.c fs_write.c
|
CSRCS += fs_select.c fs_unlink.c fs_write.c
|
||||||
|
|
||||||
# Support for positional file access
|
# Support for positional file access
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -68,7 +68,7 @@
|
|||||||
|
|
||||||
int dup(int fd)
|
int dup(int fd)
|
||||||
{
|
{
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
|
|
||||||
/* Check the range of the descriptor to see if we got a file or a socket
|
/* Check the range of the descriptor to see if we got a file or a socket
|
||||||
* descriptor. */
|
* descriptor. */
|
||||||
@@ -79,19 +79,19 @@ int dup(int fd)
|
|||||||
/* Its a valid file descriptor.. dup the file descriptor using any
|
/* Its a valid file descriptor.. dup the file descriptor using any
|
||||||
* other file descriptor*/
|
* other file descriptor*/
|
||||||
|
|
||||||
ret = file_dup(fd, 0);
|
ret = fs_dupfd(fd, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
/* Not a vailid file descriptor. Did we get a valid socket descriptor? */
|
/* Not a valid file descriptor. Did we get a valid socket descriptor? */
|
||||||
|
|
||||||
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
||||||
if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
|
if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
|
||||||
{
|
{
|
||||||
/* Yes.. dup the socket descriptor */
|
/* Yes.. dup the socket descriptor */
|
||||||
|
|
||||||
ret = net_dup(fd, CONFIG_NFILE_DESCRIPTORS);
|
ret = net_dupsd(fd, CONFIG_NFILE_DESCRIPTORS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+2
-2
@@ -87,7 +87,7 @@ int dup2(int fd1, int fd2)
|
|||||||
{
|
{
|
||||||
/* Yes.. dup the socket descriptor */
|
/* Yes.. dup the socket descriptor */
|
||||||
|
|
||||||
return net_dup2(fd1, fd2);
|
return net_dupsd2(fd1, fd2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -101,7 +101,7 @@ int dup2(int fd1, int fd2)
|
|||||||
{
|
{
|
||||||
/* Its a valid file descriptor.. dup the file descriptor */
|
/* Its a valid file descriptor.. dup the file descriptor */
|
||||||
|
|
||||||
return file_dup2(fd1, fd2);
|
return fs_dupfd2(fd1, fd2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* fs/vfs/fs_filedup.c
|
* fs/vfs/fs_dupfd.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007-2009, 2011-2014 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -53,20 +53,57 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define DUP_ISOPEN(fd, list) \
|
#define DUP_ISOPEN(filep) (filep->f_inode != NULL)
|
||||||
((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS && \
|
|
||||||
list->fl_files[fd].f_inode != NULL)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Global Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: file_dup OR dup
|
* Name: file_dup
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Equivalent to the non-standard fs_dupfd() function except that it
|
||||||
|
* accepts a struct file instance instead of a file descriptor. Currently
|
||||||
|
* used only by file_vfcntl();
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int file_dup(FAR struct file *filep, int minfd)
|
||||||
|
{
|
||||||
|
int fd2;
|
||||||
|
|
||||||
|
/* Verify that fd is a valid, open file descriptor */
|
||||||
|
|
||||||
|
if (!DUP_ISOPEN(filep))
|
||||||
|
{
|
||||||
|
set_errno(EBADF);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increment the reference count on the contained inode */
|
||||||
|
|
||||||
|
inode_addref(filep->f_inode);
|
||||||
|
|
||||||
|
/* Then allocate a new file descriptor for the inode */
|
||||||
|
|
||||||
|
fd2 = files_allocate(filep->f_inode, filep->f_oflags, filep->f_pos, minfd);
|
||||||
|
if (fd2 < 0)
|
||||||
|
{
|
||||||
|
set_errno(EMFILE);
|
||||||
|
inode_release(filep->f_inode);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: fs_dupfd OR dup
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Clone a file descriptor 'fd' to an arbitray descriptor number (any value
|
* Clone a file descriptor 'fd' to an arbitray descriptor number (any value
|
||||||
@@ -77,42 +114,23 @@
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int file_dup(int fd, int minfd)
|
int fs_dupfd(int fd, int minfd)
|
||||||
{
|
{
|
||||||
FAR struct filelist *list;
|
FAR struct file *filep;
|
||||||
int fd2;
|
|
||||||
|
|
||||||
/* Get the thread-specific file list */
|
/* Get the file structure corresponding to the file descriptor. */
|
||||||
|
|
||||||
list = sched_getfiles();
|
filep = fs_getfilep(fd);
|
||||||
DEBUGASSERT(list);
|
if (!filep)
|
||||||
|
|
||||||
/* Verify that fd is a valid, open file descriptor */
|
|
||||||
|
|
||||||
if (!DUP_ISOPEN(fd, list))
|
|
||||||
{
|
{
|
||||||
set_errno(EBADF);
|
/* The errno value has already been set */
|
||||||
|
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increment the reference count on the contained inode */
|
/* Let file_dup() do the real work */
|
||||||
|
|
||||||
inode_addref(list->fl_files[fd].f_inode);
|
return file_dup(filep, minfd);
|
||||||
|
|
||||||
/* 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 */
|
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* fs/vfs/fs_filedup2.c
|
* fs/vfs/fs_dupfd2.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007-2009, 2011-2014 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -51,9 +51,7 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define DUP_ISOPEN(fd, list) \
|
#define DUP_ISOPEN(filep) (filep->f_inode != NULL)
|
||||||
((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS && \
|
|
||||||
list->fl_files[fd].f_inode != NULL)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
@@ -64,7 +62,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: file_dup2 OR dup2
|
* Name: fs_dupfd2 OR dup2
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Clone a file descriptor to a specific descriptor number. If socket
|
* Clone a file descriptor to a specific descriptor number. If socket
|
||||||
@@ -75,25 +73,29 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
||||||
int file_dup2(int fd1, int fd2)
|
int fs_dupfd2(int fd1, int fd2)
|
||||||
#else
|
#else
|
||||||
int dup2(int fd1, int fd2)
|
int dup2(int fd1, int fd2)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
FAR struct filelist *list;
|
FAR struct file *filep1;
|
||||||
|
FAR struct file *filep2;
|
||||||
|
|
||||||
/* Get the thread-specific file list */
|
/* Get the file structures corresponding to the file descriptors. */
|
||||||
|
|
||||||
list = sched_getfiles();
|
filep1 = fs_getfilep(fd1);
|
||||||
if (!list)
|
filep2 = fs_getfilep(fd2);
|
||||||
|
|
||||||
|
if (!filep1 || !filep2)
|
||||||
{
|
{
|
||||||
set_errno(EMFILE);
|
/* The errno value has already been set */
|
||||||
|
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify that fd is a valid, open file descriptor */
|
/* Verify that fd1 is a valid, open file descriptor */
|
||||||
|
|
||||||
if (!DUP_ISOPEN(fd1, list))
|
if (!DUP_ISOPEN(filep1))
|
||||||
{
|
{
|
||||||
set_errno(EBADF);
|
set_errno(EBADF);
|
||||||
return ERROR;
|
return ERROR;
|
||||||
@@ -106,15 +108,9 @@ int dup2(int fd1, int fd2)
|
|||||||
return fd1;
|
return fd1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify fd2 */
|
/* Perform the dup2 operation */
|
||||||
|
|
||||||
if ((unsigned int)fd2 >= CONFIG_NFILE_DESCRIPTORS)
|
return file_dup2(filep1, filep2);
|
||||||
{
|
|
||||||
set_errno(EBADF);
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return files_dup(&list->fl_files[fd1], &list->fl_files[fd2]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
|
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
|
||||||
+26
-18
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* fs/vfs/fs_fcntl.c
|
* fs/vfs/fs_fcntl.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009, 2012-2013 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2009, 2012-2014 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -58,26 +58,28 @@
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: file_vfcntl
|
* Name: file_vfcntl
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Similar to the standard vfcntl function except that is accepts a struct
|
||||||
|
* struct file instance instead of a file descriptor. Currently used
|
||||||
|
* only by aio_fcntl();
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
static inline int file_vfcntl(int fd, int cmd, va_list ap)
|
int file_vfcntl(FAR struct file *filep, int cmd, va_list ap)
|
||||||
{
|
{
|
||||||
FAR struct filelist *list;
|
|
||||||
FAR struct file *filep;
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
|
|
||||||
/* Get the thread-specific file list */
|
|
||||||
|
|
||||||
list = sched_getfiles();
|
|
||||||
DEBUGASSERT(list);
|
|
||||||
|
|
||||||
/* Was this file opened ? */
|
/* Was this file opened ? */
|
||||||
|
|
||||||
filep = &list->fl_files[fd];
|
|
||||||
if (!filep->f_inode)
|
if (!filep->f_inode)
|
||||||
{
|
{
|
||||||
err = EBADF;
|
err = EBADF;
|
||||||
@@ -98,7 +100,7 @@ static inline int file_vfcntl(int fd, int cmd, va_list ap)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
{
|
{
|
||||||
ret = file_dup(fd, va_arg(ap, int));
|
ret = file_dup(filep, va_arg(ap, int));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -216,16 +218,13 @@ errout:
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
|
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Global Functions
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: fcntl
|
* Name: fcntl
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int fcntl(int fd, int cmd, ...)
|
int fcntl(int fd, int cmd, ...)
|
||||||
{
|
{
|
||||||
|
FAR struct file *filep;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -238,9 +237,19 @@ int fcntl(int fd, int cmd, ...)
|
|||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
if ((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS)
|
if ((unsigned int)fd < CONFIG_NFILE_DESCRIPTORS)
|
||||||
{
|
{
|
||||||
/* Yes.. defer file operations to file_vfcntl() */
|
/* Get the file structure corresponding to the file descriptor. */
|
||||||
|
|
||||||
ret = file_vfcntl(fd, cmd, ap);
|
filep = fs_getfilep(fd);
|
||||||
|
if (!filep)
|
||||||
|
{
|
||||||
|
/* The errno value has already been set */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let file_vfcntl() do the real work */
|
||||||
|
|
||||||
|
ret = file_vfcntl(filep, cmd, ap);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@@ -266,4 +275,3 @@ int fcntl(int fd, int cmd, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-6
@@ -65,22 +65,28 @@
|
|||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
static inline int fs_checkfd(FAR struct tcb_s *tcb, int fd, int oflags)
|
static inline int fs_checkfd(FAR struct tcb_s *tcb, int fd, int oflags)
|
||||||
{
|
{
|
||||||
FAR struct filelist *flist;
|
FAR struct file *filep;
|
||||||
FAR struct inode *inode;
|
FAR struct inode *inode;
|
||||||
|
|
||||||
DEBUGASSERT(tcb && tcb->group);
|
DEBUGASSERT(tcb && tcb->group);
|
||||||
|
|
||||||
/* Get the file list from the task group */
|
/* Get the file structure corresponding to the file descriptor. */
|
||||||
|
|
||||||
flist = &tcb->group->tg_filelist;
|
filep = fs_getfilep(fd);
|
||||||
|
if (!filep)
|
||||||
|
{
|
||||||
|
/* The errno value has already been set */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the inode associated with the file descriptor. This should
|
/* Get the inode associated with the file descriptor. This should
|
||||||
* normally be the case if fd >= 0. But not in the case where the
|
* normally be the case if fd >= 0. But not in the case where the
|
||||||
* called attempts to explictly stdin with fdopen(0) but stdin has
|
* called attempts to explicitly stdin with fdopen(0) but stdin has
|
||||||
* been closed.
|
* been closed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inode = flist->fl_files[fd].f_inode;
|
inode = filep->f_inode;
|
||||||
if (!inode)
|
if (!inode)
|
||||||
{
|
{
|
||||||
/* No inode -- descriptor does not correspond to an open file */
|
/* No inode -- descriptor does not correspond to an open file */
|
||||||
|
|||||||
+34
-22
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* fs/vfs/fs_fsync.c
|
* fs/vfs/fs_fsync.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007-2009, 2013-2014 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -70,36 +70,22 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: fsync
|
* Name: file_fsync
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* This func simply binds inode sync methods to the sync system call.
|
* Equivalent to the standard fsync() function except that is accepts a
|
||||||
|
* struct file instance instead of a file descriptor. Currently used
|
||||||
|
* only by aio_fsync();
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int fsync(int fd)
|
int file_fsync(FAR struct file *filep)
|
||||||
{
|
{
|
||||||
FAR struct filelist *list;
|
struct inode *inode;
|
||||||
FAR struct file *filep;
|
int ret;
|
||||||
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? */
|
/* Was this file opened for write access? */
|
||||||
|
|
||||||
filep = &list->fl_files[fd];
|
|
||||||
if ((filep->f_oflags & O_WROK) == 0)
|
if ((filep->f_oflags & O_WROK) == 0)
|
||||||
{
|
{
|
||||||
ret = EBADF;
|
ret = EBADF;
|
||||||
@@ -134,3 +120,29 @@ errout:
|
|||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: fsync
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This func simply binds inode sync methods to the sync system call.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int fsync(int fd)
|
||||||
|
{
|
||||||
|
FAR struct file *filep;
|
||||||
|
|
||||||
|
/* Get the file structure corresponding to the file descriptor. */
|
||||||
|
|
||||||
|
filep = fs_getfilep(fd);
|
||||||
|
if (!filep)
|
||||||
|
{
|
||||||
|
/* The errno value has already been set */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform the fsync operation */
|
||||||
|
|
||||||
|
return file_fsync(filep);
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* fs/vfs/fs_getfilep.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "inode/inode.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: fs_getfilep
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Given a file descriptor, return the corresponding instance of struct
|
||||||
|
* file. NOTE that this function will currently fail if it is provided
|
||||||
|
* with a socket descriptor.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* fd - The file descriptor
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* A point to the corresponding struct file instance is returned on
|
||||||
|
* success. On failure, NULL is returned and the errno value is
|
||||||
|
* set appropriately (EBADF).
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR struct file *fs_getfilep(int fd)
|
||||||
|
{
|
||||||
|
FAR struct filelist *list;
|
||||||
|
int errcode;
|
||||||
|
|
||||||
|
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
|
||||||
|
{
|
||||||
|
errcode = EBADF;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The descriptor is in a valid range to file descriptor... Get the
|
||||||
|
* thread-specific file list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
list = sched_getfiles();
|
||||||
|
|
||||||
|
/* The file list can be NULL under one obscure cornercase: When memory
|
||||||
|
* management debug output is enabled. Then there may be attempts to
|
||||||
|
* write to stdout from malloc before the group data has been allocated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!list)
|
||||||
|
{
|
||||||
|
errcode = EAGAIN;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And return the file pointer from the list */
|
||||||
|
|
||||||
|
return &list->fl_files[fd];
|
||||||
|
|
||||||
|
errout:
|
||||||
|
set_errno(errcode);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
+9
-7
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* fs/vfs/fs_ioctl.c
|
* fs/vfs/fs_ioctl.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2010, 2012-2013 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007-2010, 2012-2014 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -89,7 +89,6 @@ int ioctl(int fd, int req, unsigned long arg)
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
FAR struct filelist *list;
|
|
||||||
FAR struct file *filep;
|
FAR struct file *filep;
|
||||||
FAR struct inode *inode;
|
FAR struct inode *inode;
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
@@ -115,16 +114,19 @@ int ioctl(int fd, int req, unsigned long arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
/* Get the thread-specific file list */
|
/* Get the file structure corresponding to the file descriptor. */
|
||||||
|
|
||||||
list = sched_getfiles();
|
filep = fs_getfilep(fd);
|
||||||
DEBUGASSERT(list);
|
if (!filep)
|
||||||
|
{
|
||||||
|
/* The errno value has already been set */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* Is a driver registered? Does it support the ioctl method? */
|
/* Is a driver registered? Does it support the ioctl method? */
|
||||||
|
|
||||||
filep = &list->fl_files[fd];
|
|
||||||
inode = filep->f_inode;
|
inode = filep->f_inode;
|
||||||
|
|
||||||
if (inode && inode->u.i_ops && inode->u.i_ops->ioctl)
|
if (inode && inode->u.i_ops && inode->u.i_ops->ioctl)
|
||||||
{
|
{
|
||||||
/* Yes, then let it perform the ioctl */
|
/* Yes, then let it perform the ioctl */
|
||||||
|
|||||||
+9
-17
@@ -50,7 +50,7 @@
|
|||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Global Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -71,9 +71,6 @@
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef CONFIG_NET_SENDFILE
|
|
||||||
static inline
|
|
||||||
#endif
|
|
||||||
off_t file_seek(FAR struct file *filep, off_t offset, int whence)
|
off_t file_seek(FAR struct file *filep, off_t offset, int whence)
|
||||||
{
|
{
|
||||||
FAR struct inode *inode;
|
FAR struct inode *inode;
|
||||||
@@ -172,26 +169,21 @@ errout:
|
|||||||
|
|
||||||
off_t lseek(int fd, off_t offset, int whence)
|
off_t lseek(int fd, off_t offset, int whence)
|
||||||
{
|
{
|
||||||
FAR struct filelist *list;
|
FAR struct file *filep;
|
||||||
|
|
||||||
/* Did we get a valid file descriptor? */
|
/* Get the file structure corresponding to the file descriptor. */
|
||||||
|
|
||||||
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
|
filep = fs_getfilep(fd);
|
||||||
|
if (!filep)
|
||||||
{
|
{
|
||||||
set_errno(EBADF);
|
/* The errno value has already been set */
|
||||||
|
|
||||||
return (off_t)ERROR;
|
return (off_t)ERROR;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Get the thread-specific file list */
|
|
||||||
|
|
||||||
list = sched_getfiles();
|
/* Then let file_seek do the real work */
|
||||||
DEBUGASSERT(list);
|
|
||||||
|
|
||||||
/* Then let file_seek do the real work */
|
return file_seek(filep, offset, whence);
|
||||||
|
|
||||||
return file_seek(&list->fl_files[fd], offset, whence);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+18
-14
@@ -91,19 +91,14 @@ int inode_checkflags(FAR struct inode *inode, int oflags)
|
|||||||
|
|
||||||
int open(const char *path, int oflags, ...)
|
int open(const char *path, int oflags, ...)
|
||||||
{
|
{
|
||||||
FAR struct filelist *list;
|
FAR struct file *filep;
|
||||||
FAR struct inode *inode;
|
FAR struct inode *inode;
|
||||||
FAR const char *relpath = NULL;
|
FAR const char *relpath = NULL;
|
||||||
#if defined(CONFIG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT)
|
#if defined(CONFIG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT)
|
||||||
mode_t mode = 0666;
|
mode_t mode = 0666;
|
||||||
#endif
|
#endif
|
||||||
int ret;
|
int ret;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
/* Get the thread-specific file list */
|
|
||||||
|
|
||||||
list = sched_getfiles();
|
|
||||||
DEBUGASSERT(list);
|
|
||||||
|
|
||||||
#ifdef CONFIG_FILE_MODE
|
#ifdef CONFIG_FILE_MODE
|
||||||
# ifdef CONFIG_CPP_HAVE_WARNING
|
# ifdef CONFIG_CPP_HAVE_WARNING
|
||||||
@@ -168,6 +163,16 @@ int open(const char *path, int oflags, ...)
|
|||||||
goto errout_with_inode;
|
goto errout_with_inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the file structure corresponding to the file descriptor. */
|
||||||
|
|
||||||
|
filep = fs_getfilep(fd);
|
||||||
|
if (!filep)
|
||||||
|
{
|
||||||
|
/* The errno value has already been set */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* Perform the driver open operation. NOTE that the open method may be
|
/* Perform the driver open operation. NOTE that the open method may be
|
||||||
* called many times. The driver/mountpoint logic should handled this
|
* called many times. The driver/mountpoint logic should handled this
|
||||||
* because it may also be closed that many times.
|
* because it may also be closed that many times.
|
||||||
@@ -179,13 +184,12 @@ int open(const char *path, int oflags, ...)
|
|||||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||||
if (INODE_IS_MOUNTPT(inode))
|
if (INODE_IS_MOUNTPT(inode))
|
||||||
{
|
{
|
||||||
ret = inode->u.i_mops->open((FAR struct file*)&list->fl_files[fd],
|
ret = inode->u.i_mops->open(filep, relpath, oflags, mode);
|
||||||
relpath, oflags, mode);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
ret = inode->u.i_ops->open((FAR struct file*)&list->fl_files[fd]);
|
ret = inode->u.i_ops->open(filep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-9
@@ -97,10 +97,9 @@ static void poll_semtake(FAR sem_t *sem)
|
|||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
static int poll_fdsetup(int fd, FAR struct pollfd *fds, bool setup)
|
static int poll_fdsetup(int fd, FAR struct pollfd *fds, bool setup)
|
||||||
{
|
{
|
||||||
FAR struct filelist *list;
|
FAR struct file *filep;
|
||||||
FAR struct file *filep;
|
FAR struct inode *inode;
|
||||||
FAR struct inode *inode;
|
int ret = -ENOSYS;
|
||||||
int ret = -ENOSYS;
|
|
||||||
|
|
||||||
/* Check for a valid file descriptor */
|
/* Check for a valid file descriptor */
|
||||||
|
|
||||||
@@ -120,18 +119,21 @@ static int poll_fdsetup(int fd, FAR struct pollfd *fds, bool setup)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the thread-specific file list */
|
/* Get the file pointer corresponding to this file descriptor */
|
||||||
|
|
||||||
list = sched_getfiles();
|
filep = fs_getfilep(fd);
|
||||||
DEBUGASSERT(list);
|
if (!filep)
|
||||||
|
{
|
||||||
|
/* The errno value has already been set */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* Is a driver registered? Does it support the poll method?
|
/* Is a driver registered? Does it support the poll method?
|
||||||
* If not, return -ENOSYS
|
* If not, return -ENOSYS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
filep = &list->fl_files[fd];
|
|
||||||
inode = filep->f_inode;
|
inode = filep->f_inode;
|
||||||
|
|
||||||
if (inode && inode->u.i_ops && inode->u.i_ops->poll)
|
if (inode && inode->u.i_ops && inode->u.i_ops->poll)
|
||||||
{
|
{
|
||||||
/* Yes, then setup the poll */
|
/* Yes, then setup the poll */
|
||||||
|
|||||||
+69
-37
@@ -43,6 +43,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <nuttx/fs/fs.h>
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -51,6 +53,65 @@
|
|||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: file_pread
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Equivalent to the standard pread function except that is accepts a
|
||||||
|
* struct file instance instead of a file descriptor. Currently used
|
||||||
|
* only by aio_read();
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
ssize_t file_pread(FAR struct file *filep, FAR void *buf, size_t nbytes,
|
||||||
|
off_t offset)
|
||||||
|
{
|
||||||
|
off_t savepos;
|
||||||
|
off_t pos;
|
||||||
|
ssize_t ret;
|
||||||
|
int errcode;
|
||||||
|
|
||||||
|
/* Perform the seek to the current position. This will not move the
|
||||||
|
* file pointer, but will return its current setting
|
||||||
|
*/
|
||||||
|
|
||||||
|
savepos = file_seek(filep, 0, SEEK_CUR);
|
||||||
|
if (savepos == (off_t)-1)
|
||||||
|
{
|
||||||
|
/* file_seek might fail if this if the media is not seekable */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then seek to the correct position in the file */
|
||||||
|
|
||||||
|
pos = file_seek(filep, offset, SEEK_SET);
|
||||||
|
if (pos == (off_t)-1)
|
||||||
|
{
|
||||||
|
/* This might fail is the offset is beyond the end of file */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then perform the read operation */
|
||||||
|
|
||||||
|
ret = file_read(filep, buf, nbytes);
|
||||||
|
errcode = get_errno();
|
||||||
|
|
||||||
|
/* Restore the file position */
|
||||||
|
|
||||||
|
pos = file_seek(filep, savepos, SEEK_SET);
|
||||||
|
if (pos == (off_t)-1 && ret >= 0)
|
||||||
|
{
|
||||||
|
/* This really should not fail */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_errno(errcode);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: pread
|
* Name: pread
|
||||||
*
|
*
|
||||||
@@ -82,48 +143,19 @@
|
|||||||
|
|
||||||
ssize_t pread(int fd, FAR void *buf, size_t nbytes, off_t offset)
|
ssize_t pread(int fd, FAR void *buf, size_t nbytes, off_t offset)
|
||||||
{
|
{
|
||||||
off_t savepos;
|
FAR struct file *filep;
|
||||||
off_t pos;
|
|
||||||
ssize_t ret;
|
|
||||||
int errcode;
|
|
||||||
|
|
||||||
/* Perform the lseek to the current position. This will not move the
|
/* Get the file structure corresponding to the file descriptor. */
|
||||||
* file pointer, but will return its current setting
|
|
||||||
*/
|
|
||||||
|
|
||||||
savepos = lseek(fd, 0, SEEK_CUR);
|
filep = fs_getfilep(fd);
|
||||||
if (savepos == (off_t)-1)
|
if (!filep)
|
||||||
{
|
{
|
||||||
/* lseek might fail if this if the media is not seekable */
|
/* The errno value has already been set */
|
||||||
|
|
||||||
return ERROR;
|
return (ssize_t)ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then seek to the correct position in the file */
|
/* Let file_pread do the real work */
|
||||||
|
|
||||||
pos = lseek(fd, offset, SEEK_SET);
|
return file_pread(filep, buf, nbytes, offset);
|
||||||
if (pos == (off_t)-1)
|
|
||||||
{
|
|
||||||
/* This might fail is the offset is beyond the end of file */
|
|
||||||
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Then perform the read operation */
|
|
||||||
|
|
||||||
ret = read(fd, buf, nbytes);
|
|
||||||
errcode = get_errno();
|
|
||||||
|
|
||||||
/* Restore the file position */
|
|
||||||
|
|
||||||
pos = lseek(fd, savepos, SEEK_SET);
|
|
||||||
if (pos == (off_t)-1 && ret >= 0)
|
|
||||||
{
|
|
||||||
/* This really should not fail */
|
|
||||||
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_errno(errcode);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+69
-37
@@ -43,6 +43,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <nuttx/fs/fs.h>
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -51,6 +53,65 @@
|
|||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: file_pwrite
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Equivalent to the standard pwrite function except that is accepts a
|
||||||
|
* struct file instance instead of a file descriptor. Currently used
|
||||||
|
* only by aio_write();
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
ssize_t file_pwrite(FAR struct file *filep, FAR const void *buf,
|
||||||
|
size_t nbytes, off_t offset)
|
||||||
|
{
|
||||||
|
off_t savepos;
|
||||||
|
off_t pos;
|
||||||
|
ssize_t ret;
|
||||||
|
int errcode;
|
||||||
|
|
||||||
|
/* Perform the seek to the current position. This will not move the
|
||||||
|
* file pointer, but will return its current setting
|
||||||
|
*/
|
||||||
|
|
||||||
|
savepos = file_seek(filep, 0, SEEK_CUR);
|
||||||
|
if (savepos == (off_t)-1)
|
||||||
|
{
|
||||||
|
/* file_seek might fail if this if the media is not seekable */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then seek to the correct position in the file */
|
||||||
|
|
||||||
|
pos = file_seek(filep, offset, SEEK_SET);
|
||||||
|
if (pos == (off_t)-1)
|
||||||
|
{
|
||||||
|
/* This might fail is the offset is beyond the end of file */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then perform the write operation */
|
||||||
|
|
||||||
|
ret = file_write(filep, buf, nbytes);
|
||||||
|
errcode = get_errno();
|
||||||
|
|
||||||
|
/* Restore the file position */
|
||||||
|
|
||||||
|
pos = file_seek(filep, savepos, SEEK_SET);
|
||||||
|
if (pos == (off_t)-1 && ret >= 0)
|
||||||
|
{
|
||||||
|
/* This really should not fail */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_errno(errcode);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: pwrite
|
* Name: pwrite
|
||||||
*
|
*
|
||||||
@@ -80,48 +141,19 @@
|
|||||||
|
|
||||||
ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset)
|
ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset)
|
||||||
{
|
{
|
||||||
off_t savepos;
|
FAR struct file *filep;
|
||||||
off_t pos;
|
|
||||||
ssize_t ret;
|
|
||||||
int errcode;
|
|
||||||
|
|
||||||
/* Perform the lseek to the current position. This will not move the
|
/* Get the file structure corresponding to the file descriptor. */
|
||||||
* file pointer, but will return its current setting
|
|
||||||
*/
|
|
||||||
|
|
||||||
savepos = lseek(fd, 0, SEEK_CUR);
|
filep = fs_getfilep(fd);
|
||||||
if (savepos == (off_t)-1)
|
if (!filep)
|
||||||
{
|
{
|
||||||
/* lseek might fail if this if the media is not seekable */
|
/* The errno value has already been set */
|
||||||
|
|
||||||
return ERROR;
|
return (ssize_t)ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then seek to the correct position in the file */
|
/* Let file_pread do the real work */
|
||||||
|
|
||||||
pos = lseek(fd, offset, SEEK_SET);
|
return file_pwrite(filep, buf, nbytes, offset);
|
||||||
if (pos == (off_t)-1)
|
|
||||||
{
|
|
||||||
/* This might fail is the offset is beyond the end of file */
|
|
||||||
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Then perform the write operation */
|
|
||||||
|
|
||||||
ret = write(fd, buf, nbytes);
|
|
||||||
errcode = get_errno();
|
|
||||||
|
|
||||||
/* Restore the file position */
|
|
||||||
|
|
||||||
pos = lseek(fd, savepos, SEEK_SET);
|
|
||||||
if (pos == (off_t)-1 && ret >= 0)
|
|
||||||
{
|
|
||||||
/* This really should not fail */
|
|
||||||
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_errno(errcode);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-15
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* fs/vfs/fs_read.c
|
* fs/vfs/fs_read.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2009, 2012-2013 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007-2009, 2012-2014 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -73,10 +73,6 @@
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
|
||||||
#ifndef CONFIG_NET_SENDFILE
|
|
||||||
static inline
|
|
||||||
#endif
|
|
||||||
ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
|
ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
|
||||||
{
|
{
|
||||||
FAR struct inode *inode;
|
FAR struct inode *inode;
|
||||||
@@ -120,7 +116,6 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: read
|
* Name: read
|
||||||
@@ -141,10 +136,6 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
|
|||||||
|
|
||||||
ssize_t read(int fd, FAR void *buf, size_t nbytes)
|
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? */
|
/* Did we get a valid file descriptor? */
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
@@ -168,16 +159,23 @@ ssize_t read(int fd, FAR void *buf, size_t nbytes)
|
|||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Thee descriptor is in a valid range to file descriptor... do the
|
FAR struct file *filep;
|
||||||
* read. Get the thread-specific file list.
|
|
||||||
|
/* The descriptor is in a valid range to file descriptor... do the
|
||||||
|
* read. First, get the file structure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
list = sched_getfiles();
|
filep = fs_getfilep(fd);
|
||||||
DEBUGASSERT(list);
|
if (!filep)
|
||||||
|
{
|
||||||
|
/* The errno value has already been set */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* Then let file_read do all of the work */
|
/* Then let file_read do all of the work */
|
||||||
|
|
||||||
return file_read(&list->fl_files[fd], buf, nbytes);
|
return file_read(filep, buf, nbytes);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-6
@@ -127,18 +127,23 @@ ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count)
|
|||||||
if ((unsigned int)outfd >= CONFIG_NFILE_DESCRIPTORS &&
|
if ((unsigned int)outfd >= CONFIG_NFILE_DESCRIPTORS &&
|
||||||
(unsigned int)infd < CONFIG_NFILE_DESCRIPTORS)
|
(unsigned int)infd < CONFIG_NFILE_DESCRIPTORS)
|
||||||
{
|
{
|
||||||
FAR struct filelist *list;
|
FAR struct file *filep;
|
||||||
|
|
||||||
/* This appears to be a file-to-socket transfer. Get the thread-
|
/* This appears to be a file-to-socket transfer. Get the file
|
||||||
* specific file list.
|
* structure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
list = sched_getfiles();
|
filep = fs_getfilep(fd);
|
||||||
DEBUGASSERT(list);
|
if (!filep)
|
||||||
|
{
|
||||||
|
/* The errno value has already been set */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* Then let net_sendfile do the work. */
|
/* Then let net_sendfile do the work. */
|
||||||
|
|
||||||
return net_sendfile(outfd, &list->fl_files[infd], offset, count);
|
return net_sendfile(outfd, filep, offset, count);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+35
-30
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* fs/vfs/fs_write.c
|
* fs/vfs/fs_write.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2009, 2012-2013 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007-2009, 2012-2014 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -55,33 +55,28 @@
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
/****************************************************************************
|
||||||
static inline ssize_t file_write(int fd, FAR const void *buf, size_t nbytes)
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: file_write
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Equivalent to the standard write() function except that is accepts a
|
||||||
|
* struct file instance instead of a file descriptor. Currently used
|
||||||
|
* only by aio_write();
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes)
|
||||||
{
|
{
|
||||||
FAR struct filelist *list;
|
|
||||||
FAR struct file *filep;
|
|
||||||
FAR struct inode *inode;
|
FAR struct inode *inode;
|
||||||
int ret;
|
int ret;
|
||||||
int err;
|
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? */
|
/* Was this file opened for write access? */
|
||||||
|
|
||||||
filep = &list->fl_files[fd];
|
|
||||||
if ((filep->f_oflags & O_WROK) == 0)
|
if ((filep->f_oflags & O_WROK) == 0)
|
||||||
{
|
{
|
||||||
err = EBADF;
|
err = EBADF;
|
||||||
@@ -112,11 +107,6 @@ errout:
|
|||||||
set_errno(err);
|
set_errno(err);
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Public Functions
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Name: write
|
* Name: write
|
||||||
@@ -170,6 +160,10 @@ errout:
|
|||||||
|
|
||||||
ssize_t write(int fd, FAR const void *buf, size_t nbytes)
|
ssize_t write(int fd, FAR const void *buf, size_t nbytes)
|
||||||
{
|
{
|
||||||
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
FAR struct file *filep;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Did we get a valid file descriptor? */
|
/* Did we get a valid file descriptor? */
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
@@ -186,10 +180,21 @@ ssize_t write(int fd, FAR const void *buf, size_t nbytes)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The descriptor is in the right range to be a file descriptor... write to the file */
|
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
return file_write(fd, buf, nbytes);
|
/* The descriptor is in the right range to be a file descriptor... write
|
||||||
|
* to the file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
filep = fs_getfilep(fd);
|
||||||
|
if (!filep)
|
||||||
|
{
|
||||||
|
/* The errno value has already been set */
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform the write operation using the file descriptor as an index */
|
||||||
|
|
||||||
|
return file_write(filep, buf, nbytes);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+125
-12
@@ -44,6 +44,7 @@
|
|||||||
#include <nuttx/compiler.h>
|
#include <nuttx/compiler.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
@@ -505,7 +506,7 @@ void files_releaselist(FAR struct filelist *list);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: files_dup
|
* Name: file_dup2
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Assign an inode to a specific files structure. This is the heart of
|
* Assign an inode to a specific files structure. This is the heart of
|
||||||
@@ -514,12 +515,12 @@ void files_releaselist(FAR struct filelist *list);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
int files_dup(FAR struct file *filep1, FAR struct file *filep2);
|
int file_dup2(FAR struct file *filep1, FAR struct file *filep2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* fs_filedup.c *************************************************************/
|
/* fs_filedup.c *************************************************************/
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: file_dup OR dup
|
* Name: fs_dupfd OR dup
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Clone a file descriptor 'fd' to an arbitray descriptor number (any value
|
* Clone a file descriptor 'fd' to an arbitray descriptor number (any value
|
||||||
@@ -534,12 +535,24 @@ int files_dup(FAR struct file *filep1, FAR struct file *filep2);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
int file_dup(int fd, int minfd);
|
int fs_dupfd(int fd, int minfd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: file_dup
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Equivalent to the non-standard fs_dupfd() function except that it
|
||||||
|
* accepts a struct file instance instead of a file descriptor. Currently
|
||||||
|
* used only by file_vfcntl();
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int file_dup(FAR struct file *filep, int minfd);
|
||||||
|
|
||||||
/* fs_filedup2.c ************************************************************/
|
/* fs_filedup2.c ************************************************************/
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: file_dup2 OR dup2
|
* Name: fs_dupfd2 OR dup2
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Clone a file descriptor to a specific descriptor number. If socket
|
* Clone a file descriptor to a specific descriptor number. If socket
|
||||||
@@ -554,9 +567,9 @@ int file_dup(int fd, int minfd);
|
|||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
|
||||||
int file_dup2(int fd1, int fd2);
|
int fs_dupfd2(int fd1, int fd2);
|
||||||
#else
|
#else
|
||||||
# define file_dup2(fd1, fd2) dup2(fd1, fd2)
|
# define fs_dupfd2(fd1, fd2) dup2(fd1, fd2)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -653,22 +666,92 @@ int lib_flushall(FAR struct streamlist *list);
|
|||||||
ssize_t lib_sendfile(int outfd, int infd, off_t *offset, size_t count);
|
ssize_t lib_sendfile(int outfd, int infd, off_t *offset, size_t count);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* fs/fs_fileread.c *********************************************************/
|
/* fs/fs_getfilep.c *********************************************************/
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: fs_getfilep
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Given a file descriptor, return the corresponding instance of struct
|
||||||
|
* file. NOTE that this function will currently fail if it is provided
|
||||||
|
* with a socket descriptor.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* fd - The file descriptor
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* A point to the corresponding struct file instance is returned on
|
||||||
|
* success. On failure, NULL is returned and the errno value is
|
||||||
|
* set appropriately (EBADF).
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
FAR struct file *fs_getfilep(int fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* fs/fs_read.c *************************************************************/
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: file_read
|
* Name: file_read
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Equivalent to the standard read() function except that is accepts a
|
* Equivalent to the standard read() function except that is accepts a
|
||||||
* struct file instance instead of a file descriptor. Currently used
|
* struct file instance instead of a file descriptor. Currently used
|
||||||
* only by net_sendfile()
|
* only by net_sendfile() and aio_read();
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_NET_SENDFILE)
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes);
|
ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* fs/fs_fileread.c *********************************************************/
|
/* fs/fs_write.c ************************************************************/
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: file_write
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Equivalent to the standard write() function except that is accepts a
|
||||||
|
* struct file instance instead of a file descriptor. Currently used
|
||||||
|
* only by aio_write();
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* fs/fs_pread.c ************************************************************/
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: file_pread
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Equivalent to the standard pread function except that is accepts a
|
||||||
|
* struct file instance instead of a file descriptor. Currently used
|
||||||
|
* only by aio_read();
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
ssize_t file_pread(FAR struct file *filep, FAR void *buf, size_t nbytes,
|
||||||
|
off_t offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* fs/fs_pwrite.c ***********************************************************/
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: file_pwrite
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Equivalent to the standard pwrite function except that is accepts a
|
||||||
|
* struct file instance instead of a file descriptor. Currently used
|
||||||
|
* only by aio_write();
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
ssize_t file_pwrite(FAR struct file *filep, FAR const void *buf,
|
||||||
|
size_t nbytes, off_t offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* fs/fs_lseek.c ************************************************************/
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: file_seek
|
* Name: file_seek
|
||||||
*
|
*
|
||||||
@@ -679,10 +762,40 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes);
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_NET_SENDFILE)
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
off_t file_seek(FAR struct file *filep, off_t offset, int whence);
|
off_t file_seek(FAR struct file *filep, off_t offset, int whence);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* fs/fs_fsync.c ************************************************************/
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: file_fsync
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Equivalent to the standard fsync() function except that is accepts a
|
||||||
|
* struct file instance instead of a file descriptor. Currently used
|
||||||
|
* only by aio_fsync();
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
int file_fsync(FAR struct file *filep);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* fs/fs_fcntl.c ************************************************************/
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: file_vfcntl
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Similar to the standard vfcntl function except that is accepts a struct
|
||||||
|
* struct file instance instead of a file descriptor. Currently used
|
||||||
|
* only by aio_fcntl();
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
int file_vfcntl(FAR struct file *filep, int cmd, va_list ap);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* drivers/dev_null.c *******************************************************/
|
/* drivers/dev_null.c *******************************************************/
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: devnull_register
|
* Name: devnull_register
|
||||||
|
|||||||
@@ -871,7 +871,7 @@ int net_poll(int sockfd, struct pollfd *fds, bool setup);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function: net_dup
|
* Function: net_dupsd
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Clone a socket descriptor to an arbitray descriptor number. If file
|
* Clone a socket descriptor to an arbitray descriptor number. If file
|
||||||
@@ -881,10 +881,10 @@ int net_poll(int sockfd, struct pollfd *fds, bool setup);
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int net_dup(int sockfd, int minsd);
|
int net_dupsd(int sockfd, int minsd);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function: net_dup2
|
* Function: net_dupsd2
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Clone a socket descriptor to an arbitray descriptor number. If file
|
* Clone a socket descriptor to an arbitray descriptor number. If file
|
||||||
@@ -894,13 +894,13 @@ int net_dup(int sockfd, int minsd);
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int net_dup2(int sockfd1, int sockfd2);
|
int net_dupsd2(int sockfd1, int sockfd2);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function: net_clone
|
* Function: net_clone
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Performs the low level, common portion of net_dup() and net_dup2()
|
* Performs the low level, common portion of net_dupsd() and net_dupsd2()
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
# Include socket source files
|
# Include socket source files
|
||||||
|
|
||||||
SOCK_CSRCS += bind.c connect.c getsockname.c recv.c recvfrom.c socket.c
|
SOCK_CSRCS += bind.c connect.c getsockname.c recv.c recvfrom.c socket.c
|
||||||
SOCK_CSRCS += sendto.c net_sockets.c net_close.c net_dup.c net_dup2.c
|
SOCK_CSRCS += sendto.c net_sockets.c net_close.c net_dupsd.c net_dupsd2.c
|
||||||
SOCK_CSRCS += net_clone.c net_poll.c net_vfcntl.c
|
SOCK_CSRCS += net_clone.c net_poll.c net_vfcntl.c
|
||||||
|
|
||||||
# TCP/IP support
|
# TCP/IP support
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
* Function: net_clone
|
* Function: net_clone
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Performs the low level, common portion of net_dup() and net_dup2()
|
* Performs the low level, common portion of net_dupsd() and net_dupsd2()
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* net/socket/net_dup.c
|
* net/socket/net_dupsd.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2009 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function: net_dup
|
* Function: net_dupsd
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Clone a socket descriptor to an arbitray descriptor number. If file
|
* Clone a socket descriptor to an arbitray descriptor number. If file
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int net_dup(int sockfd, int minsd)
|
int net_dupsd(int sockfd, int minsd)
|
||||||
{
|
{
|
||||||
FAR struct socket *psock1 = sockfd_socket(sockfd);
|
FAR struct socket *psock1 = sockfd_socket(sockfd);
|
||||||
FAR struct socket *psock2;
|
FAR struct socket *psock2;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* net/socket/net_dup2.c
|
* net/socket/net_dupsd2.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Function: net_dup2
|
* Function: net_dupsd2
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Clone a socket descriptor to an arbitray descriptor number. If file
|
* Clone a socket descriptor to an arbitray descriptor number. If file
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
int net_dup2(int sockfd1, int sockfd2)
|
int net_dupsd2(int sockfd1, int sockfd2)
|
||||||
#else
|
#else
|
||||||
int dup2(int sockfd1, int sockfd2)
|
int dup2(int sockfd1, int sockfd2)
|
||||||
#endif
|
#endif
|
||||||
@@ -108,7 +108,7 @@ int net_vfcntl(int sockfd, int cmd, va_list ap)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
{
|
{
|
||||||
ret = net_dup(sockfd, va_arg(ap, int));
|
ret = net_dupsd(sockfd, va_arg(ap, int));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -113,8 +113,8 @@ int group_setupidlefiles(FAR struct task_tcb_s *tcb)
|
|||||||
{
|
{
|
||||||
/* Successfully opened /dev/console as stdin (fd == 0) */
|
/* Successfully opened /dev/console as stdin (fd == 0) */
|
||||||
|
|
||||||
(void)file_dup2(0, 1);
|
(void)fs_dupfd2(0, 1);
|
||||||
(void)file_dup2(0, 2);
|
(void)fs_dupfd2(0, 2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ static inline void sched_dupfiles(FAR struct task_tcb_s *tcb)
|
|||||||
{
|
{
|
||||||
/* Yes... duplicate it for the child */
|
/* Yes... duplicate it for the child */
|
||||||
|
|
||||||
(void)files_dup(&parent[i], &child[i]);
|
(void)file_dup2(&parent[i], &child[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user