mirror of
https://github.com/apache/nuttx.git
synced 2025-12-06 09:01:15 +08:00
fs/vfs: Separate file descriptors from file descriptions
This patch is a rework of the NuttX file descriptor implementation. The goal is two-fold: 1. Improve POSIX compliance. The old implementation tied file description to inode only, not the file struct. POSIX however dictates otherwise. 2. Fix a bug with descriptor duplication (dup2() and dup3()). There is an existing race condition with this POSIX API that currently results in a kernel side crash. The crash occurs when a partially open / closed file descriptor is duplicated. The reason for the crash is that even if the descriptor is closed, the file might still be in use by the kernel (due to e.g. ongoing write to file). The open file data is changed by file_dup3() and this causes a crash in the device / drivers themselves as they lose access to the inode and private data. The fix is done by separating struct file into file and file descriptor structs. The file struct can live on even if the descriptor is closed, fixing the crash. This also fixes the POSIX issue, as two descriptors can now point to the same file. Signed-off-by: Ville Juven <ville.juven@unikie.com> Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
@@ -1028,8 +1028,7 @@ static int cryptoioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
TAILQ_INIT(&fcr->csessions);
|
||||
TAILQ_INIT(&fcr->crpk_ret);
|
||||
|
||||
fd = file_allocate(&g_cryptoinode, 0,
|
||||
0, fcr, 0, true);
|
||||
fd = file_allocate_from_inode(&g_cryptoinode, 0, 0, fcr, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
kmm_free(fcr);
|
||||
|
||||
@@ -1038,7 +1038,8 @@ optee_ioctl_shm_register(FAR struct optee_priv_data *priv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = file_allocate(&g_optee_shm_inode, O_CLOEXEC, 0, shm, 0, true);
|
||||
ret = file_allocate_from_inode(&g_optee_shm_inode, O_CLOEXEC,
|
||||
0, shm, 0, true);
|
||||
if (ret < 0)
|
||||
{
|
||||
optee_shm_free(shm);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -72,21 +72,21 @@
|
||||
while (0)
|
||||
|
||||
#if CONFIG_FS_BACKTRACE > 0
|
||||
# define FS_ADD_BACKTRACE(filep) \
|
||||
# define FS_ADD_BACKTRACE(fd) \
|
||||
do \
|
||||
{ \
|
||||
int n = sched_backtrace(_SCHED_GETTID(), \
|
||||
(filep)->f_backtrace, \
|
||||
(fd)->f_backtrace, \
|
||||
CONFIG_FS_BACKTRACE, \
|
||||
CONFIG_FS_BACKTRACE_SKIP); \
|
||||
if (n < CONFIG_FS_BACKTRACE) \
|
||||
{ \
|
||||
(filep)->f_backtrace[n] = NULL; \
|
||||
(fd)->f_backtrace[n] = NULL; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
#else
|
||||
# define FS_ADD_BACKTRACE(filep)
|
||||
# define FS_ADD_BACKTRACE(fd)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -264,7 +264,6 @@ static int file_mq_vopen(FAR struct file *mq, FAR const char *mq_name,
|
||||
|
||||
/* Associate the inode with a file structure */
|
||||
|
||||
memset(mq, 0, sizeof(*mq));
|
||||
mq->f_oflags = oflags;
|
||||
mq->f_inode = inode;
|
||||
|
||||
@@ -308,7 +307,6 @@ static int file_mq_vopen(FAR struct file *mq, FAR const char *mq_name,
|
||||
|
||||
/* Associate the inode with a file structure */
|
||||
|
||||
memset(mq, 0, sizeof(*mq));
|
||||
mq->f_oflags = oflags;
|
||||
mq->f_inode = inode;
|
||||
|
||||
@@ -347,28 +345,26 @@ errout:
|
||||
|
||||
static mqd_t nxmq_vopen(FAR const char *mq_name, int oflags, va_list ap)
|
||||
{
|
||||
struct file mq;
|
||||
FAR struct file *mq;
|
||||
int created;
|
||||
int ret;
|
||||
int fd;
|
||||
|
||||
ret = file_mq_vopen(&mq, mq_name, oflags, getumask(), ap, &created);
|
||||
fd = file_allocate(oflags, 0, &mq);
|
||||
if (fd < 0)
|
||||
{
|
||||
return fd;
|
||||
}
|
||||
|
||||
ret = file_mq_vopen(mq, mq_name, oflags, getumask(), ap, &created);
|
||||
file_put(mq);
|
||||
if (ret < 0)
|
||||
{
|
||||
nx_close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = file_allocate(mq.f_inode, mq.f_oflags,
|
||||
mq.f_pos, mq.f_priv, 0, false);
|
||||
if (ret < 0)
|
||||
{
|
||||
file_mq_close(&mq);
|
||||
if (created)
|
||||
{
|
||||
file_mq_unlink(mq_name);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return fd;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -1025,7 +1025,7 @@ static inline void notify_queue_filep_event(FAR struct file *filep,
|
||||
|
||||
static void notify_free_entry(FAR ENTRY *entry)
|
||||
{
|
||||
/* Key is alloced by lib_malloc, value is alloced by fs_heap_malloc */
|
||||
/* Key is allocated by lib_malloc, value is allocated by fs_heap_malloc */
|
||||
|
||||
fs_heap_free(entry->key);
|
||||
fs_heap_free(entry->data);
|
||||
@@ -1255,8 +1255,8 @@ int inotify_init1(int flags)
|
||||
goto exit_set_errno;
|
||||
}
|
||||
|
||||
ret = file_allocate(&g_inotify_inode, O_RDOK | flags,
|
||||
0, dev, 0, true);
|
||||
ret = file_allocate_from_inode(&g_inotify_inode, O_RDOK | flags,
|
||||
0, dev, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
ferr("Failed to allocate inotify fd\n");
|
||||
|
||||
@@ -1252,7 +1252,6 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile,
|
||||
size_t buflen, off_t offset)
|
||||
{
|
||||
FAR struct task_group_s *group = tcb->group;
|
||||
FAR struct file *filep;
|
||||
FAR char *path;
|
||||
size_t remaining;
|
||||
size_t linesize;
|
||||
@@ -1263,7 +1262,7 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile,
|
||||
|
||||
DEBUGASSERT(group != NULL);
|
||||
|
||||
count = files_countlist(&group->tg_filelist);
|
||||
count = fdlist_count(&group->tg_fdlist);
|
||||
if (count == 0)
|
||||
{
|
||||
return 0;
|
||||
@@ -1303,11 +1302,12 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile,
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
filep = files_fget(&group->tg_filelist, i);
|
||||
FAR struct file *filep;
|
||||
FAR struct fd *fdp;
|
||||
|
||||
/* Is there an inode associated with the file descriptor? */
|
||||
|
||||
if (filep == NULL)
|
||||
if (fdlist_get2(&group->tg_fdlist, i, &filep, &fdp) < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1327,7 +1327,7 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile,
|
||||
#if CONFIG_FS_BACKTRACE > 0
|
||||
linesize += backtrace_format(procfile->line + linesize,
|
||||
STATUS_LINELEN - linesize,
|
||||
filep->f_backtrace,
|
||||
fdp->f_backtrace,
|
||||
CONFIG_FS_BACKTRACE);
|
||||
#endif
|
||||
procfile->line[linesize - 2] = '\n';
|
||||
|
||||
@@ -150,7 +150,6 @@ static int file_shm_open(FAR struct file *shm, FAR const char *name,
|
||||
|
||||
/* Associate the inode with a file structure */
|
||||
|
||||
memset(shm, 0, sizeof(*shm));
|
||||
shm->f_oflags = oflags | O_CLOEXEC | O_NOFOLLOW;
|
||||
shm->f_inode = inode;
|
||||
|
||||
@@ -173,24 +172,25 @@ errout_with_sem:
|
||||
|
||||
int shm_open(FAR const char *name, int oflag, mode_t mode)
|
||||
{
|
||||
struct file shm;
|
||||
FAR struct file *shm;
|
||||
int ret;
|
||||
int fd;
|
||||
|
||||
ret = file_shm_open(&shm, name, oflag, mode);
|
||||
fd = file_allocate(oflag, 0, &shm);
|
||||
if (fd < 0)
|
||||
{
|
||||
set_errno(-fd);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = file_shm_open(shm, name, oflag, mode);
|
||||
file_put(shm);
|
||||
if (ret < 0)
|
||||
{
|
||||
nx_close(fd);
|
||||
set_errno(-ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = file_allocate(shm.f_inode, shm.f_oflags, shm.f_pos, shm.f_priv, 0,
|
||||
false);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
file_close(&shm);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return fd;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ static int sock_file_truncate(FAR struct file *filep, off_t length)
|
||||
|
||||
int sockfd_allocate(FAR struct socket *psock, int oflags)
|
||||
{
|
||||
return file_allocate(&g_sock_inode, oflags, 0, psock, 0, true);
|
||||
return file_allocate_from_inode(&g_sock_inode, oflags, 0, psock, 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -76,11 +76,10 @@ static FAR char *file_get_path(FAR struct file *filep)
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_close_without_clear
|
||||
* Name: file_close
|
||||
*
|
||||
* Description:
|
||||
* Close a file that was previously opened with file_open(), but without
|
||||
* clear filep.
|
||||
* Close a file that was previously opened with file_open().
|
||||
*
|
||||
* Input Parameters:
|
||||
* filep - A pointer to a user provided memory location containing the
|
||||
@@ -92,7 +91,7 @@ static FAR char *file_get_path(FAR struct file *filep)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_close_without_clear(FAR struct file *filep)
|
||||
int file_close(FAR struct file *filep)
|
||||
{
|
||||
struct inode *inode;
|
||||
#ifdef CONFIG_FS_NOTIFY
|
||||
@@ -140,44 +139,14 @@ int file_close_without_clear(FAR struct file *filep)
|
||||
|
||||
inode_release(inode);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_close
|
||||
*
|
||||
* Description:
|
||||
* Close a file that was previously opened with file_open().
|
||||
*
|
||||
* Input Parameters:
|
||||
* filep - A pointer to a user provided memory location containing the
|
||||
* open file data returned by file_open().
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; A negated errno value is returned on
|
||||
* any failure to indicate the nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_close(FAR struct file *filep)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = file_close_without_clear(filep);
|
||||
if (ret >= 0 && filep->f_inode)
|
||||
{
|
||||
#ifdef CONFIG_FDCHECK
|
||||
filep->f_tag_fdcheck = 0;
|
||||
#ifdef CONFIG_FS_NOTIFY
|
||||
if (path != NULL)
|
||||
{
|
||||
lib_put_pathbuffer(path);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FDSAN
|
||||
filep->f_tag_fdsan = 0;
|
||||
#endif
|
||||
|
||||
/* Reset the user file struct instance so that it cannot be reused. */
|
||||
|
||||
filep->f_inode = NULL;
|
||||
}
|
||||
|
||||
@@ -208,7 +177,7 @@ int file_close(FAR struct file *filep)
|
||||
|
||||
int nx_close(int fd)
|
||||
{
|
||||
return nx_close_from_tcb(this_task(), fd);
|
||||
return fdlist_close(nxsched_get_fdlist_from_tcb(this_task()), fd);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -33,7 +33,9 @@
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "sched/sched.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -54,32 +56,8 @@
|
||||
|
||||
int file_dup(FAR struct file *filep, int minfd, int flags)
|
||||
{
|
||||
FAR struct file *filep2;
|
||||
int fd2;
|
||||
int ret;
|
||||
#ifdef CONFIG_FDCHECK
|
||||
minfd = fdcheck_restore(minfd);
|
||||
#endif
|
||||
|
||||
fd2 = file_allocate(g_root_inode, 0, 0, NULL, minfd, true);
|
||||
if (fd2 < 0)
|
||||
{
|
||||
return fd2;
|
||||
}
|
||||
|
||||
ret = file_get(fd2, &filep2);
|
||||
DEBUGASSERT(ret >= 0);
|
||||
|
||||
ret = file_dup3(filep, filep2, flags);
|
||||
|
||||
file_put(filep2);
|
||||
if (ret >= 0)
|
||||
{
|
||||
return fd2;
|
||||
}
|
||||
|
||||
file_put(filep2);
|
||||
return ret;
|
||||
return fdlist_dupfile(nxsched_get_fdlist_from_tcb(this_task()),
|
||||
flags, minfd, filep);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -42,13 +42,13 @@
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_dup3
|
||||
* Name: file_dup2
|
||||
*
|
||||
* Description:
|
||||
* Assign an inode to a specific files structure. This is the heart of
|
||||
* dup3.
|
||||
* dup2.
|
||||
*
|
||||
* Equivalent to the non-standard dup3() function except that it
|
||||
* Equivalent to the non-standard dup2() function except that it
|
||||
* accepts struct file instances instead of file descriptors and it does
|
||||
* not set the errno variable.
|
||||
*
|
||||
@@ -58,7 +58,7 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_dup3(FAR struct file *filep1, FAR struct file *filep2, int flags)
|
||||
int file_dup2(FAR struct file *filep1, FAR struct file *filep2)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
int ret;
|
||||
@@ -68,11 +68,6 @@ int file_dup3(FAR struct file *filep1, FAR struct file *filep2, int flags)
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
if (flags != 0 && flags != O_CLOEXEC)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (filep1 == filep2)
|
||||
{
|
||||
return OK;
|
||||
@@ -83,29 +78,15 @@ int file_dup3(FAR struct file *filep1, FAR struct file *filep2, int flags)
|
||||
inode = filep1->f_inode;
|
||||
inode_addref(inode);
|
||||
|
||||
/* If there is already an inode contained in the new file structure,
|
||||
* close the file and release the inode.
|
||||
* But we need keep the filep2->f_inode, in case of realloced by others.
|
||||
*/
|
||||
/* Close the second file */
|
||||
|
||||
ret = file_close_without_clear(filep2);
|
||||
ret = file_close(filep2);
|
||||
if (ret < 0)
|
||||
{
|
||||
inode_release(inode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The two filep don't share flags (the close-on-exec flag). */
|
||||
|
||||
if (flags == O_CLOEXEC)
|
||||
{
|
||||
filep2->f_oflags = filep1->f_oflags | O_CLOEXEC;
|
||||
}
|
||||
else
|
||||
{
|
||||
filep2->f_oflags = filep1->f_oflags & ~O_CLOEXEC;
|
||||
}
|
||||
|
||||
filep2->f_priv = NULL;
|
||||
filep2->f_pos = filep1->f_pos;
|
||||
filep2->f_inode = inode;
|
||||
@@ -159,34 +140,10 @@ int file_dup3(FAR struct file *filep1, FAR struct file *filep2, int flags)
|
||||
if (ret < 0)
|
||||
{
|
||||
inode_release(inode);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
FS_ADD_BACKTRACE(filep2);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_dup2
|
||||
*
|
||||
* Description:
|
||||
* Assign an inode to a specific files structure. This is the heart of
|
||||
* dup2.
|
||||
*
|
||||
* Equivalent to the non-standard dup2() function except that it
|
||||
* accepts struct file instances instead of file descriptors and it does
|
||||
* not set the errno variable.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is return on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_dup2(FAR struct file *filep1, FAR struct file *filep2)
|
||||
{
|
||||
return file_dup3(filep1, filep2, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -209,7 +166,7 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2)
|
||||
|
||||
int nx_dup2(int fd1, int fd2)
|
||||
{
|
||||
return nx_dup2_from_tcb(this_task(), fd1, fd2);
|
||||
return fdlist_dup2(nxsched_get_fdlist_from_tcb(this_task()), fd1, fd2);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -49,7 +49,8 @@ int dup3(int fd1, int fd2, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = nx_dup3_from_tcb(this_task(), fd1, fd2, flags);
|
||||
ret = fdlist_dup3(nxsched_get_fdlist_from_tcb(this_task()),
|
||||
fd1, fd2, flags);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
|
||||
@@ -258,7 +258,7 @@ static int epoll_do_create(int size, int flags)
|
||||
|
||||
/* Alloc the file descriptor */
|
||||
|
||||
fd = file_allocate(&g_epoll_inode, flags, 0, eph, 0, true);
|
||||
fd = file_allocate_from_inode(&g_epoll_inode, flags, 0, eph, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
nxmutex_destroy(&eph->lock);
|
||||
|
||||
@@ -528,8 +528,8 @@ int eventfd(unsigned int count, int flags)
|
||||
}
|
||||
|
||||
new_dev->counter = count;
|
||||
new_fd = file_allocate(&g_eventfd_inode, O_RDWR | flags,
|
||||
0, new_dev, 0, true);
|
||||
new_fd = file_allocate_from_inode(&g_eventfd_inode, O_RDWR | flags,
|
||||
0, new_dev, 0);
|
||||
if (new_fd < 0)
|
||||
{
|
||||
ret = new_fd;
|
||||
|
||||
@@ -59,70 +59,6 @@ static int file_vfcntl(FAR struct file *filep, int cmd, va_list ap)
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
{
|
||||
/* Does not set the errno variable in the event of a failure */
|
||||
|
||||
ret = file_dup(filep, va_arg(ap, int), 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case F_DUPFD_CLOEXEC:
|
||||
{
|
||||
ret = file_dup(filep, va_arg(ap, int), O_CLOEXEC);
|
||||
}
|
||||
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.
|
||||
*/
|
||||
|
||||
{
|
||||
ret = filep->f_oflags & O_CLOEXEC ? FD_CLOEXEC : 0;
|
||||
}
|
||||
break;
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
{
|
||||
int oflags = va_arg(ap, int);
|
||||
|
||||
if (oflags & ~FD_CLOEXEC)
|
||||
{
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (oflags & FD_CLOEXEC)
|
||||
{
|
||||
ret = file_ioctl(filep, FIOCLEX, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = file_ioctl(filep, FIONCLEX, NULL);
|
||||
}
|
||||
}
|
||||
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
|
||||
@@ -347,27 +283,100 @@ int fcntl(int fd, int cmd, ...)
|
||||
|
||||
va_start(ap, cmd);
|
||||
|
||||
/* Get the file structure corresponding to the file descriptor. */
|
||||
|
||||
ret = file_get(fd, &filep);
|
||||
if (ret >= 0)
|
||||
if (ret < 0)
|
||||
{
|
||||
/* Let file_vfcntl() do the real work. The errno is not set on
|
||||
* failures.
|
||||
*/
|
||||
|
||||
ret = file_vfcntl(filep, cmd, ap);
|
||||
file_put(filep);
|
||||
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(filep, va_arg(ap, int), 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case F_DUPFD_CLOEXEC:
|
||||
{
|
||||
ret = file_dup(filep, va_arg(ap, int), O_CLOEXEC);
|
||||
}
|
||||
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.
|
||||
*/
|
||||
|
||||
{
|
||||
int flags;
|
||||
|
||||
ret = file_ioctl(filep, FIOGCLEX, &flags);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = flags;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
{
|
||||
int oflags = va_arg(ap, int);
|
||||
|
||||
if (oflags & ~FD_CLOEXEC)
|
||||
{
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (oflags & FD_CLOEXEC)
|
||||
{
|
||||
ret = file_ioctl(filep, FIOCLEX, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = file_ioctl(filep, FIONCLEX, NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
ret = file_vfcntl(filep, cmd, ap);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
file_put(filep);
|
||||
|
||||
errout:
|
||||
va_end(ap);
|
||||
leave_cancellation_point();
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
ret = ERROR;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
leave_cancellation_point();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -89,22 +89,6 @@ static int file_vioctl(FAR struct file *filep, int req, va_list ap)
|
||||
}
|
||||
break;
|
||||
|
||||
case FIOCLEX:
|
||||
if (ret == OK || ret == -ENOTTY)
|
||||
{
|
||||
filep->f_oflags |= O_CLOEXEC;
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case FIONCLEX:
|
||||
if (ret == OK || ret == -ENOTTY)
|
||||
{
|
||||
filep->f_oflags &= ~O_CLOEXEC;
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case FIOC_FILEPATH:
|
||||
if (ret == -ENOTTY && !INODE_IS_MOUNTPT(inode))
|
||||
{
|
||||
@@ -135,30 +119,6 @@ static int file_vioctl(FAR struct file *filep, int req, va_list ap)
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_FDSAN
|
||||
case FIOC_SETTAG_FDSAN:
|
||||
filep->f_tag_fdsan = *(FAR uint64_t *)arg;
|
||||
ret = OK;
|
||||
break;
|
||||
|
||||
case FIOC_GETTAG_FDSAN:
|
||||
*(FAR uint64_t *)arg = filep->f_tag_fdsan;
|
||||
ret = OK;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FDCHECK
|
||||
case FIOC_SETTAG_FDCHECK:
|
||||
filep->f_tag_fdcheck = *(FAR uint8_t *)arg;
|
||||
ret = OK;
|
||||
break;
|
||||
|
||||
case FIOC_GETTAG_FDCHECK:
|
||||
*(FAR uint8_t *)arg = filep->f_tag_fdcheck;
|
||||
ret = OK;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
case BIOC_BLKSSZGET:
|
||||
if (ret == -ENOTTY && inode->u.i_ops != NULL &&
|
||||
@@ -194,6 +154,65 @@ static int file_vioctl(FAR struct file *filep, int req, va_list ap)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nx_vioctl
|
||||
****************************************************************************/
|
||||
|
||||
static int nx_vioctl(int fd, int req, va_list ap)
|
||||
{
|
||||
FAR struct file *filep;
|
||||
FAR struct fd *fdp;
|
||||
int ret;
|
||||
|
||||
ret = file_get2(fd, &filep, &fdp);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (req)
|
||||
{
|
||||
case FIOCLEX:
|
||||
fdp->f_cloexec = true;
|
||||
break;
|
||||
|
||||
case FIONCLEX:
|
||||
fdp->f_cloexec = false;
|
||||
break;
|
||||
|
||||
case FIOGCLEX:
|
||||
*va_arg(ap, FAR int *) = fdp->f_cloexec ? O_CLOEXEC : 0;
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_FDSAN
|
||||
case FIOC_SETTAG_FDSAN:
|
||||
fdp->f_tag_fdsan = *va_arg(ap, FAR uint64_t *);
|
||||
break;
|
||||
|
||||
case FIOC_GETTAG_FDSAN:
|
||||
*va_arg(ap, FAR uint64_t *) = fdp->f_tag_fdsan;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FDCHECK
|
||||
case FIOC_SETTAG_FDCHECK:
|
||||
fdp->f_tag_fdcheck = *va_arg(ap, FAR uint8_t *);
|
||||
break;
|
||||
|
||||
case FIOC_GETTAG_FDCHECK:
|
||||
*va_arg(ap, FAR uint8_t *) = fdp->f_tag_fdcheck;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
ret = file_vioctl(filep, req, ap);
|
||||
break;
|
||||
}
|
||||
|
||||
file_put(filep);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@@ -260,33 +279,21 @@ int file_ioctl(FAR struct file *filep, int req, ...)
|
||||
|
||||
int ioctl(int fd, int req, ...)
|
||||
{
|
||||
FAR struct file *filep;
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
/* Get the file structure corresponding to the file descriptor. */
|
||||
va_start(ap, req);
|
||||
|
||||
ret = file_get(fd, &filep);
|
||||
/* Let nx_vioctl() do the real work. */
|
||||
|
||||
ret = nx_vioctl(fd, req, ap);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto err;
|
||||
set_errno(-ret);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
/* Let file_vioctl() do the real work. */
|
||||
|
||||
va_start(ap, req);
|
||||
ret = file_vioctl(filep, req, ap);
|
||||
va_end(ap);
|
||||
|
||||
file_put(filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
err:
|
||||
set_errno(-ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
@@ -227,7 +227,6 @@ static int file_vopen(FAR struct file *filep, FAR const char *path,
|
||||
|
||||
/* Associate the inode with a file structure */
|
||||
|
||||
memset(filep, 0, sizeof(*filep));
|
||||
filep->f_oflags = oflags;
|
||||
filep->f_inode = inode;
|
||||
|
||||
@@ -308,28 +307,29 @@ errout_with_search:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nx_vopen(FAR struct tcb_s *tcb,
|
||||
static int nx_vopen(FAR struct fdlist *list,
|
||||
FAR const char *path, int oflags, va_list ap)
|
||||
{
|
||||
struct file filep;
|
||||
FAR struct file *filep;
|
||||
int ret;
|
||||
int fd;
|
||||
|
||||
/* Let file_vopen() do all of the work */
|
||||
|
||||
ret = file_vopen(&filep, path, oflags, getumask(), ap);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allocate a new file descriptor for the inode */
|
||||
|
||||
fd = file_allocate_from_tcb(tcb, filep.f_inode, filep.f_oflags,
|
||||
filep.f_pos, filep.f_priv, 0, false);
|
||||
fd = fdlist_allocate(list, oflags, 0, &filep);
|
||||
if (fd < 0)
|
||||
{
|
||||
file_close(&filep);
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Let file_vopen() do all of the work */
|
||||
|
||||
ret = file_vopen(filep, path, oflags, getumask(), ap);
|
||||
file_put(filep);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdlist_close(list, fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return fd;
|
||||
@@ -370,23 +370,18 @@ int file_open(FAR struct file *filep, FAR const char *path, int oflags, ...)
|
||||
ret = file_vopen(filep, path, oflags, 0, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (ret >= OK)
|
||||
{
|
||||
FS_ADD_BACKTRACE(filep);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nx_open_from_tcb
|
||||
* Name: fdlist_open
|
||||
*
|
||||
* Description:
|
||||
* nx_open_from_tcb() is similar to the standard 'open' interface except
|
||||
* fdlist_open() is similar to the standard 'open' interface except
|
||||
* that it is not a cancellation point and it does not modify the errno
|
||||
* variable.
|
||||
*
|
||||
* nx_open_from_tcb() is an internal NuttX interface and should not be
|
||||
* fdlist_open() is an internal NuttX interface and should not be
|
||||
* called from applications.
|
||||
*
|
||||
* Input Parameters:
|
||||
@@ -401,8 +396,8 @@ int file_open(FAR struct file *filep, FAR const char *path, int oflags, ...)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nx_open_from_tcb(FAR struct tcb_s *tcb,
|
||||
FAR const char *path, int oflags, ...)
|
||||
int fdlist_open(FAR struct fdlist *list,
|
||||
FAR const char *path, int oflags, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int fd;
|
||||
@@ -410,7 +405,7 @@ int nx_open_from_tcb(FAR struct tcb_s *tcb,
|
||||
/* Let nx_vopen() do all of the work */
|
||||
|
||||
va_start(ap, oflags);
|
||||
fd = nx_vopen(tcb, path, oflags, ap);
|
||||
fd = nx_vopen(list, path, oflags, ap);
|
||||
va_end(ap);
|
||||
|
||||
return fd;
|
||||
@@ -445,7 +440,7 @@ int nx_open(FAR const char *path, int oflags, ...)
|
||||
/* Let nx_vopen() do all of the work */
|
||||
|
||||
va_start(ap, oflags);
|
||||
fd = nx_vopen(this_task(), path, oflags, ap);
|
||||
fd = nx_vopen(nxsched_get_fdlist_from_tcb(this_task()), path, oflags, ap);
|
||||
va_end(ap);
|
||||
|
||||
return fd;
|
||||
@@ -475,7 +470,7 @@ int open(FAR const char *path, int oflags, ...)
|
||||
/* Let nx_vopen() do most of the work */
|
||||
|
||||
va_start(ap, oflags);
|
||||
fd = nx_vopen(this_task(), path, oflags, ap);
|
||||
fd = nx_vopen(nxsched_get_fdlist_from_tcb(this_task()), path, oflags, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Set the errno value if any errors were reported by nx_open() */
|
||||
|
||||
@@ -352,8 +352,8 @@ int signalfd(int fd, FAR const sigset_t *mask, int flags)
|
||||
|
||||
nxmutex_init(&dev->mutex);
|
||||
|
||||
fd = file_allocate(&g_signalfd_inode, O_RDOK | flags,
|
||||
0, dev, 0, true);
|
||||
fd = file_allocate_from_inode(&g_signalfd_inode, O_RDOK | flags,
|
||||
0, dev, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
ret = -fd;
|
||||
|
||||
@@ -462,8 +462,8 @@ int timerfd_create(int clockid, int flags)
|
||||
/* Initialize the timer instance */
|
||||
|
||||
new_dev->clock = clockid;
|
||||
new_fd = file_allocate(&g_timerfd_inode, O_RDONLY | flags,
|
||||
0, new_dev, 0, true);
|
||||
new_fd = file_allocate_from_inode(&g_timerfd_inode, O_RDONLY | flags,
|
||||
0, new_dev, 0);
|
||||
if (new_fd < 0)
|
||||
{
|
||||
ret = new_fd;
|
||||
|
||||
@@ -188,7 +188,6 @@ struct stat;
|
||||
struct statfs;
|
||||
struct pollfd;
|
||||
struct mtd_dev_s;
|
||||
struct tcb_s;
|
||||
struct uio;
|
||||
|
||||
/* The internal representation of type DIR is just a container for an inode
|
||||
@@ -464,21 +463,24 @@ struct file
|
||||
off_t f_pos; /* File position */
|
||||
FAR struct inode *f_inode; /* Driver or file system interface */
|
||||
FAR void *f_priv; /* Per file driver private data */
|
||||
#ifdef CONFIG_FDSAN
|
||||
uint64_t f_tag_fdsan; /* File owner fdsan tag, init to 0 */
|
||||
#if CONFIG_FS_LOCK_BUCKET_SIZE > 0
|
||||
bool f_locked; /* Filelock state: false - unlocked, true - locked */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct fd
|
||||
{
|
||||
FAR struct file *f_file; /* The file associated with descriptor */
|
||||
bool f_cloexec; /* Close on exec */
|
||||
#ifdef CONFIG_FDCHECK
|
||||
uint8_t f_tag_fdcheck; /* File owner fdcheck tag, init to 0 */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FDSAN
|
||||
uint64_t f_tag_fdsan; /* File owner fdsan tag, init to 0 */
|
||||
#endif
|
||||
#if CONFIG_FS_BACKTRACE > 0
|
||||
FAR void *f_backtrace[CONFIG_FS_BACKTRACE]; /* Backtrace to while file opens */
|
||||
#endif
|
||||
|
||||
#if CONFIG_FS_LOCK_BUCKET_SIZE > 0
|
||||
bool f_locked; /* Filelock state: false - unlocked, true - locked */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* This defines a two layer array of files indexed by the file descriptor.
|
||||
@@ -488,20 +490,20 @@ struct file
|
||||
* (file descriptor % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK) as column index.
|
||||
*/
|
||||
|
||||
struct filelist
|
||||
struct fdlist
|
||||
{
|
||||
spinlock_t fl_lock; /* Manage access to the file list */
|
||||
uint8_t fl_rows; /* The number of rows of fl_files array */
|
||||
FAR struct file **fl_files; /* The pointer of two layer file descriptors array */
|
||||
spinlock_t fl_lock; /* Manage access to the file descriptor list */
|
||||
uint8_t fl_rows; /* The number of rows of fl_fds array */
|
||||
FAR struct fd **fl_fds; /* The pointer of two layer file descriptors array */
|
||||
|
||||
/* Pre-allocated files to avoid allocator access during thread creation
|
||||
* phase, For functional safety requirements, increase
|
||||
/* Pre-allocated file descriptors to avoid allocator access during thread
|
||||
* creation phase, For functional safety requirements, increasing
|
||||
* CONFIG_NFILE_DESCRIPTORS_PER_BLOCK could also avoid allocator access
|
||||
* caused by the file descriptor exceeding the limit.
|
||||
*/
|
||||
|
||||
FAR struct file *fl_prefile;
|
||||
struct file fl_prefiles[CONFIG_NFILE_DESCRIPTORS_PER_BLOCK];
|
||||
FAR struct fd *fl_prefd;
|
||||
struct fd fl_prefds[CONFIG_NFILE_DESCRIPTORS_PER_BLOCK];
|
||||
};
|
||||
|
||||
/* The following structure defines the list of files used for standard C I/O.
|
||||
@@ -880,57 +882,63 @@ int nx_umount2(FAR const char *target, unsigned int flags);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_initlist
|
||||
* Name: fdlist_init
|
||||
*
|
||||
* Description:
|
||||
* Initializes the list of files for a new task
|
||||
* Initializes the list of file descriptors for a new task.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void files_initlist(FAR struct filelist *list);
|
||||
void fdlist_init(FAR struct fdlist *list);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_dumplist
|
||||
* Name: fdlist_dump
|
||||
*
|
||||
* Description:
|
||||
* Dump the list of files.
|
||||
* Dump the list of file descriptors.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SCHED_DUMP_ON_EXIT
|
||||
void files_dumplist(FAR struct filelist *list);
|
||||
void fdlist_dump(FAR struct fdlist *list);
|
||||
#else
|
||||
# define files_dumplist(l)
|
||||
# define fdlist_dump(l)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_putlist
|
||||
* Name: fdlist_free
|
||||
*
|
||||
* Description:
|
||||
* Release the list of files.
|
||||
* Release the list of file descriptors.
|
||||
*
|
||||
* Assumptions:
|
||||
* Called during task deletion in a safe context.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void files_putlist(FAR struct filelist * list);
|
||||
void fdlist_free(FAR struct fdlist *list);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_countlist
|
||||
* Name: fdlist_count
|
||||
*
|
||||
* Description:
|
||||
* Get file count from file list
|
||||
* Get file descriptor count from file list.
|
||||
*
|
||||
* Input Parameters:
|
||||
* list - Pointer to the file descriptor list structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* file count of file list
|
||||
* file descriptor count of file list.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int files_countlist(FAR struct filelist *list);
|
||||
int fdlist_count(FAR struct fdlist *list);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_duplist
|
||||
* Name: fdlist_copy
|
||||
*
|
||||
* Description:
|
||||
* Duplicate parent task's file descriptors.
|
||||
* Copy parent task's file descriptors to child task.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
@@ -938,59 +946,136 @@ int files_countlist(FAR struct filelist *list);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist,
|
||||
FAR const posix_spawn_file_actions_t *actions,
|
||||
bool cloexec);
|
||||
int fdlist_copy(FAR struct fdlist *plist, FAR struct fdlist *clist,
|
||||
FAR const posix_spawn_file_actions_t *actions,
|
||||
bool cloexec);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_fget
|
||||
* Name: fdlist_get2
|
||||
*
|
||||
* Description:
|
||||
* Get the instance of struct file from file list by file descriptor.
|
||||
* Given a file descriptor, return the corresponding instance of struct
|
||||
* fd and filep.
|
||||
*
|
||||
* Input Parameters:
|
||||
* list - The list of files for a task.
|
||||
* fd - A valid descriptor between 0 and files_countlist(list).
|
||||
* list - Pointer to the file descriptor list structure.
|
||||
* fd - The file descriptor
|
||||
* filep - The location to return the struct file instance
|
||||
* fdp - The location to return the struct fd instance
|
||||
*
|
||||
* Returned Value:
|
||||
* Pointer to file structure of list[fd].
|
||||
* Return the pointer to file structure of list[fd] when list[fd].f_file
|
||||
* is valid, othersize, a null pointer is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct file *files_fget(FAR struct filelist *list, int fd);
|
||||
int fdlist_get2(FAR struct fdlist *list, int fd,
|
||||
FAR struct file **filep, FAR struct fd **fdp);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_allocate_from_tcb
|
||||
* Name: fdlist_get
|
||||
*
|
||||
* Description:
|
||||
* Allocate a struct files instance and associate it with an inode
|
||||
* instance.
|
||||
* Given a file descriptor, return the corresponding instance of struct
|
||||
* filep.
|
||||
*
|
||||
* Input Parameters:
|
||||
* list - Pointer to the file descriptor list structure.
|
||||
* fd - The file descriptor
|
||||
* filep - The location to return the struct file instance
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns the file descriptor == index into the files array on success;
|
||||
* a negated errno value is returned on any failure.
|
||||
* Return the pointer to file structure of list[fd] when list[fd].f_file
|
||||
* is valid, othersize, a null pointer is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_allocate_from_tcb(FAR struct tcb_s *tcb, FAR struct inode *inode,
|
||||
int oflags, off_t pos, FAR void *priv, int minfd,
|
||||
bool addref);
|
||||
#define fdlist_get(list, fd, filep) fdlist_get2(list, fd, filep, NULL)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fdlist_dupfile
|
||||
*
|
||||
* Description:
|
||||
* Allocate a struct fd instance and bind it to the corresponding file
|
||||
* handle.
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns the file descriptor == index into the files array on success;
|
||||
* a negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int fdlist_dupfile(FAR struct fdlist *list, int oflags, int minfd,
|
||||
FAR struct file *filep);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fdlist_allocate
|
||||
*
|
||||
* Description:
|
||||
* Allocate a struct fd instance and associate it with an empty file
|
||||
* instance. The difference between this function and
|
||||
* file_allocate_from_inode is that this function is only used for
|
||||
* placeholder purposes. Later, the caller will initialize the file entity
|
||||
* through the returned filep.
|
||||
*
|
||||
* The fd allocated by this function can be released using fdlist_close.
|
||||
*
|
||||
* After the function call is completed, it will hold a reference count
|
||||
* for the filep. Therefore, when the filep is no longer in use, it is
|
||||
* necessary to call file_put to release the reference count, in order
|
||||
* to avoid a race condition where the file might be closed during
|
||||
* this process.
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns the file descriptor == index into the files array on success;
|
||||
* a negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int fdlist_allocate(FAR struct fdlist *list, int oflags,
|
||||
int minfd, FAR struct file **filep);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_allocate
|
||||
*
|
||||
* Description:
|
||||
* Allocate a struct files instance and associate it with an inode
|
||||
* instance.
|
||||
* Allocate a struct fd instance and associate it with an empty file
|
||||
* instance. The difference between this function and
|
||||
* file_allocate_from_inode is that this function is only used for
|
||||
* placeholder purposes. Later, the caller will initialize the file entity
|
||||
* through the returned filep.
|
||||
*
|
||||
* The fd allocated by this function can be released using nx_close.
|
||||
*
|
||||
* After the function call is completed, it will hold a reference count
|
||||
* for the filep. Therefore, when the filep is no longer in use, it is
|
||||
* necessary to call file_put to release the reference count, in order
|
||||
* to avoid a race condition where the file might be closed during
|
||||
* this process.
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns the file descriptor == index into the files array on success;
|
||||
* a negated errno value is returned on any failure.
|
||||
* Returns the file descriptor == index into the files array on success;
|
||||
* a negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_allocate(FAR struct inode *inode, int oflags, off_t pos,
|
||||
FAR void *priv, int minfd, bool addref);
|
||||
int file_allocate(int oflags, int minfd, FAR struct file **filep);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_allocate_from_inode
|
||||
*
|
||||
* Description:
|
||||
* Allocate a struct fd instance and associate it with an file instance.
|
||||
* And initialize them with inode, oflags, pos and priv.
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns the file descriptor == index into the files array on success;
|
||||
* a negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_allocate_from_inode(FAR struct inode *inode, int oflags, off_t pos,
|
||||
FAR void *priv, int minfd);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_dup
|
||||
@@ -1026,14 +1111,14 @@ int file_dup(FAR struct file *filep, int minfd, int flags);
|
||||
int file_dup2(FAR struct file *filep1, FAR struct file *filep2);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nx_dup3_from_tcb
|
||||
* Name: fdlist_dup3
|
||||
*
|
||||
* Description:
|
||||
* nx_dup3_from_tcb() is similar to the standard 'dup3' interface
|
||||
* fdlist_dup3() is similar to the standard 'dup3' interface
|
||||
* except that is not a cancellation point and it does not modify the
|
||||
* errno variable.
|
||||
*
|
||||
* nx_dup3_from_tcb() is an internal NuttX interface and should not be
|
||||
* fdlist_dup3() is an internal NuttX interface and should not be
|
||||
* called from applications.
|
||||
*
|
||||
* Clone a file descriptor to a specific descriptor number.
|
||||
@@ -1044,17 +1129,17 @@ int file_dup2(FAR struct file *filep1, FAR struct file *filep2);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nx_dup3_from_tcb(FAR struct tcb_s *tcb, int fd1, int fd2, int flags);
|
||||
int fdlist_dup3(FAR struct fdlist *list, int fd1, int fd2, int flags);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nx_dup2_from_tcb
|
||||
* Name: fdlist_dup2
|
||||
*
|
||||
* Description:
|
||||
* nx_dup2_from_tcb() is similar to the standard 'dup2' interface
|
||||
* fdlist_dup2() is similar to the standard 'dup2' interface
|
||||
* except that is not a cancellation point and it does not modify the
|
||||
* errno variable.
|
||||
*
|
||||
* nx_dup2_from_tcb() is an internal NuttX interface and should not be
|
||||
* fdlist_dup2() is an internal NuttX interface and should not be
|
||||
* called from applications.
|
||||
*
|
||||
* Clone a file descriptor to a specific descriptor number.
|
||||
@@ -1065,7 +1150,7 @@ int nx_dup3_from_tcb(FAR struct tcb_s *tcb, int fd1, int fd2, int flags);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nx_dup2_from_tcb(FAR struct tcb_s *tcb, int fd1, int fd2);
|
||||
int fdlist_dup2(FAR struct fdlist *list, int fd1, int fd2);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nx_dup2
|
||||
@@ -1085,24 +1170,6 @@ int nx_dup2_from_tcb(FAR struct tcb_s *tcb, int fd1, int fd2);
|
||||
|
||||
int nx_dup2(int fd1, int fd2);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_dup3
|
||||
*
|
||||
* Description:
|
||||
* Assign an inode to a specific files structure. This is the heart of
|
||||
* dup3.
|
||||
*
|
||||
* Equivalent to the non-standard dup3() function except that it
|
||||
* accepts struct file instances instead of file descriptors.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is return on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_dup3(FAR struct file *filep1, FAR struct file *filep2, int flags);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_open
|
||||
*
|
||||
@@ -1127,18 +1194,18 @@ int file_dup3(FAR struct file *filep1, FAR struct file *filep2, int flags);
|
||||
int file_open(FAR struct file *filep, FAR const char *path, int oflags, ...);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nx_open_from_tcb
|
||||
* Name: fdlist_open
|
||||
*
|
||||
* Description:
|
||||
* nx_open_from_tcb() is similar to the standard 'open' interface except
|
||||
* fdlist_open() is similar to the standard 'open' interface except
|
||||
* that it is not a cancellation point and it does not modify the errno
|
||||
* variable.
|
||||
*
|
||||
* nx_open_from_tcb() is an internal NuttX interface and should not be
|
||||
* fdlist_open() is an internal NuttX interface and should not be
|
||||
* called from applications.
|
||||
*
|
||||
* Input Parameters:
|
||||
* tcb - Address of the task's TCB
|
||||
* list - Pointer to the file descriptor list structure.
|
||||
* path - The full path to the file to be opened.
|
||||
* oflags - open flags.
|
||||
* ... - Variable number of arguments, may include 'mode_t mode'
|
||||
@@ -1149,8 +1216,8 @@ int file_open(FAR struct file *filep, FAR const char *path, int oflags, ...);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nx_open_from_tcb(FAR struct tcb_s *tcb,
|
||||
FAR const char *path, int oflags, ...);
|
||||
int fdlist_open(FAR struct fdlist *list,
|
||||
FAR const char *path, int oflags, ...);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nx_open
|
||||
@@ -1170,6 +1237,26 @@ int nx_open_from_tcb(FAR struct tcb_s *tcb,
|
||||
|
||||
int nx_open(FAR const char *path, int oflags, ...);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_get2
|
||||
*
|
||||
* Description:
|
||||
* Given a file descriptor, return the corresponding instance of struct
|
||||
* fd and filep
|
||||
*
|
||||
* Input Parameters:
|
||||
* fd - The file descriptor
|
||||
* filep - The location to return the struct file instance
|
||||
* fdp - The location to return the struct fd instance
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_get2(int fd, FAR struct file **filep, FAR struct fd **fdp);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_get
|
||||
*
|
||||
@@ -1188,7 +1275,7 @@ int nx_open(FAR const char *path, int oflags, ...);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_get(int fd, FAR struct file **filep);
|
||||
#define file_get(fd, filep) file_get2(fd, filep, NULL)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_ref
|
||||
@@ -1240,33 +1327,14 @@ int file_put(FAR struct file *filep);
|
||||
int file_close(FAR struct file *filep);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_close_without_clear
|
||||
* Name: fdlist_close
|
||||
*
|
||||
* Description:
|
||||
* Close a file that was previously opened with file_open(), but without
|
||||
* clear filep.
|
||||
*
|
||||
* Input Parameters:
|
||||
* filep - A pointer to a user provided memory location containing the
|
||||
* open file data returned by file_open().
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; A negated errno value is returned on
|
||||
* any failure to indicate the nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int file_close_without_clear(FAR struct file *filep);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nx_close_from_tcb
|
||||
*
|
||||
* Description:
|
||||
* nx_close_from_tcb() is similar to the standard 'close' interface
|
||||
* fdlist_close() is similar to the standard 'close' interface
|
||||
* except that is not a cancellation point and it does not modify the
|
||||
* errno variable.
|
||||
*
|
||||
* nx_close_from_tcb() is an internal NuttX interface and should not
|
||||
* fdlist_close() is an internal NuttX interface and should not
|
||||
* be called from applications.
|
||||
*
|
||||
* Close an inode (if open)
|
||||
@@ -1281,7 +1349,7 @@ int file_close_without_clear(FAR struct file *filep);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nx_close_from_tcb(FAR struct tcb_s *tcb, int fd);
|
||||
int fdlist_close(FAR struct fdlist *list, int fd);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nx_close
|
||||
|
||||
@@ -235,6 +235,16 @@
|
||||
* OUT: Current file xip base address
|
||||
*/
|
||||
|
||||
#define FIOC_GETFLAGS _FIOC(0x0016) /* IN: None
|
||||
* OUT: None
|
||||
*/
|
||||
#define FIOC_SETFLAGS _FIOC(0x0017) /* IN: The flags that need to set to file
|
||||
* OUT: None
|
||||
*/
|
||||
#define FIOGCLEX _FIOC(0x0018) /* IN: FAR int *
|
||||
* OUT: None
|
||||
*/
|
||||
|
||||
/* NuttX file system ioctl definitions **************************************/
|
||||
|
||||
#define _DIOCVALID(c) (_IOC_TYPE(c)==_DIOCBASE)
|
||||
|
||||
@@ -539,7 +539,7 @@ struct task_group_s
|
||||
|
||||
/* File descriptors *******************************************************/
|
||||
|
||||
struct filelist tg_filelist; /* Maps file descriptor to file */
|
||||
struct fdlist tg_fdlist; /* Maps file descriptor to file */
|
||||
|
||||
/* Virtual memory mapping info ********************************************/
|
||||
|
||||
@@ -932,10 +932,10 @@ int nxsched_release_tcb(FAR struct tcb_s *tcb, uint8_t ttype);
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxsched_get_files_from_tcb
|
||||
* Name: nxsched_get_fdlist_from_tcb
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the file list from task context
|
||||
* Return a pointer to the file descriptor list from task context.
|
||||
*
|
||||
* Input Parameters:
|
||||
* tcb - Address of the new task's TCB
|
||||
@@ -947,25 +947,25 @@ int nxsched_release_tcb(FAR struct tcb_s *tcb, uint8_t ttype);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct filelist *nxsched_get_files_from_tcb(FAR struct tcb_s *tcb);
|
||||
FAR struct fdlist *nxsched_get_fdlist_from_tcb(FAR struct tcb_s *tcb);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxsched_get_files
|
||||
* Name: nxsched_get_fdlist
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the file list for this thread
|
||||
* Return a pointer to the file descriptor list for this thread.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* A pointer to the errno.
|
||||
* A pointer to the file descriptor list.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct filelist *nxsched_get_files(void);
|
||||
FAR struct fdlist *nxsched_get_fdlist(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxtask_init
|
||||
|
||||
@@ -168,7 +168,7 @@ int group_initialize(FAR struct task_tcb_s *tcb, uint8_t ttype)
|
||||
|
||||
/* Initialize file descriptors for the TCB */
|
||||
|
||||
files_initlist(&group->tg_filelist);
|
||||
fdlist_init(&group->tg_fdlist);
|
||||
|
||||
/* Alloc task info for group */
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ group_release(FAR struct task_group_s *group, uint8_t ttype)
|
||||
|
||||
/* Free resources held by the file descriptor list */
|
||||
|
||||
files_putlist(&group->tg_filelist);
|
||||
fdlist_free(&group->tg_fdlist);
|
||||
|
||||
#ifndef CONFIG_DISABLE_ENVIRON
|
||||
/* Release all shared environment variables */
|
||||
|
||||
@@ -83,8 +83,8 @@ int group_setuptaskfiles(FAR struct task_tcb_s *tcb,
|
||||
|
||||
if (group != rtcb->group)
|
||||
{
|
||||
files_duplist(&rtcb->group->tg_filelist,
|
||||
&group->tg_filelist, actions, cloexec);
|
||||
ret = fdlist_copy(&rtcb->group->tg_fdlist,
|
||||
&group->tg_fdlist, actions, cloexec);
|
||||
}
|
||||
|
||||
if (ret >= 0 && actions != NULL)
|
||||
|
||||
@@ -456,10 +456,10 @@ static void dump_backtrace(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SCHED_DUMP_ON_EXIT
|
||||
static void dump_filelist(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
static void dump_fdlist(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
{
|
||||
FAR struct filelist *filelist = &tcb->group->tg_filelist;
|
||||
files_dumplist(filelist);
|
||||
FAR struct fdlist *list = &tcb->group->tg_fdlist;
|
||||
fdlist_dump(list);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -548,7 +548,7 @@ static void dump_tasks(void)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCHED_DUMP_ON_EXIT
|
||||
nxsched_foreach(dump_filelist, NULL);
|
||||
nxsched_foreach(dump_fdlist, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -33,22 +33,22 @@
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxsched_get_files_from_tcb
|
||||
* Name: nxsched_get_fdlist_from_tcb
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the file list from task context
|
||||
* Return a pointer to the file descriptor list from task context.
|
||||
*
|
||||
* Input Parameters:
|
||||
* tcb - Address of the new task's TCB
|
||||
*
|
||||
* Returned Value:
|
||||
* A pointer to the errno.
|
||||
* A pointer to the file descriptor list.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct filelist *nxsched_get_files_from_tcb(FAR struct tcb_s *tcb)
|
||||
FAR struct fdlist *nxsched_get_fdlist_from_tcb(FAR struct tcb_s *tcb)
|
||||
{
|
||||
FAR struct task_group_s *group = tcb->group;
|
||||
|
||||
@@ -60,7 +60,7 @@ FAR struct filelist *nxsched_get_files_from_tcb(FAR struct tcb_s *tcb)
|
||||
|
||||
if (group)
|
||||
{
|
||||
return &group->tg_filelist;
|
||||
return &group->tg_fdlist;
|
||||
}
|
||||
|
||||
/* Higher level logic must handle the NULL gracefully */
|
||||
@@ -69,22 +69,22 @@ FAR struct filelist *nxsched_get_files_from_tcb(FAR struct tcb_s *tcb)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxsched_get_files
|
||||
* Name: nxsched_get_fdlist
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the file list for this thread
|
||||
* Return a pointer to the file descriptor list for this thread.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* A pointer to the errno.
|
||||
* A pointer to the file descriptor list.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct filelist *nxsched_get_files(void)
|
||||
FAR struct fdlist *nxsched_get_fdlist(void)
|
||||
{
|
||||
return nxsched_get_files_from_tcb(this_task());
|
||||
return nxsched_get_fdlist_from_tcb(this_task());
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ nxspawn_close(FAR struct tcb_s *tcb,
|
||||
|
||||
sinfo("Closing fd=%d\n", action->fd);
|
||||
|
||||
nx_close_from_tcb(tcb, action->fd);
|
||||
fdlist_close(nxsched_get_fdlist_from_tcb(tcb), action->fd);
|
||||
}
|
||||
|
||||
static inline int nxspawn_dup2(FAR struct tcb_s *tcb,
|
||||
@@ -78,12 +78,14 @@ static inline int nxspawn_dup2(FAR struct tcb_s *tcb,
|
||||
|
||||
sinfo("Dup'ing %d->%d\n", action->fd1, action->fd2);
|
||||
|
||||
return nx_dup2_from_tcb(tcb, action->fd1, action->fd2);
|
||||
return fdlist_dup2(nxsched_get_fdlist_from_tcb(tcb),
|
||||
action->fd1, action->fd2);
|
||||
}
|
||||
|
||||
static inline int nxspawn_open(FAR struct tcb_s *tcb,
|
||||
FAR struct spawn_open_file_action_s *action)
|
||||
{
|
||||
FAR struct fdlist *list;
|
||||
int ret = OK;
|
||||
int fd;
|
||||
|
||||
@@ -92,22 +94,23 @@ static inline int nxspawn_open(FAR struct tcb_s *tcb,
|
||||
sinfo("Open'ing path=%s oflags=%04x mode=%04x\n",
|
||||
action->path, action->oflags, action->mode);
|
||||
|
||||
nx_close_from_tcb(tcb, action->fd);
|
||||
list = nxsched_get_fdlist_from_tcb(tcb);
|
||||
fdlist_close(list, action->fd);
|
||||
|
||||
fd = nx_open_from_tcb(tcb, action->path, action->oflags, action->mode);
|
||||
fd = fdlist_open(list, action->path, action->oflags, action->mode);
|
||||
if (fd < 0)
|
||||
{
|
||||
ret = fd;
|
||||
}
|
||||
else if (fd != action->fd)
|
||||
{
|
||||
ret = nx_dup2_from_tcb(tcb, fd, action->fd);
|
||||
ret = fdlist_dup2(list, fd, action->fd);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
nx_close_from_tcb(tcb, fd);
|
||||
fdlist_close(list, fd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user