mirror of
https://github.com/apache/nuttx.git
synced 2025-12-09 19:54:55 +08:00
fs: allocate file/socket dynamically
Change-Id: I8aea63eaf0275f47f21fc8d5482b51ffecd5c906 Signed-off-by: Jiuzhu Dong <dongjiuzhu1@xiaomi.com>
This commit is contained in:
@@ -69,18 +69,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
FAR struct file_struct *filep;
|
||||
#endif
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid);
|
||||
sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
|
||||
|
||||
filelist = tcb->group->tg_filelist;
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < filelist->fl_rows; i++)
|
||||
{
|
||||
struct inode *inode = filelist->fl_files[i].f_inode;
|
||||
if (inode)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i, inode->i_crefs);
|
||||
struct inode *inode = filelist->fl_files[i][j].f_inode;
|
||||
if (inode)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j,
|
||||
inode->i_crefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,18 +84,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
FAR struct file_struct *filep;
|
||||
#endif
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid);
|
||||
sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
|
||||
|
||||
filelist = tcb->group->tg_filelist;
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < filelist->fl_rows; i++)
|
||||
{
|
||||
struct inode *inode = filelist->fl_files[i].f_inode;
|
||||
if (inode)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i, inode->i_crefs);
|
||||
struct inode *inode = filelist->fl_files[i][j].f_inode;
|
||||
if (inode)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j,
|
||||
inode->i_crefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,18 +68,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
FAR struct file_struct *filep;
|
||||
#endif
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid);
|
||||
sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
|
||||
|
||||
filelist = tcb->group->tg_filelist;
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < filelist->fl_rows; i++)
|
||||
{
|
||||
struct inode *inode = filelist->fl_files[i].f_inode;
|
||||
if (inode)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i, inode->i_crefs);
|
||||
struct inode *inode = filelist->fl_files[i][j].f_inode;
|
||||
if (inode)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j,
|
||||
inode->i_crefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,18 +86,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
FAR struct file_struct *filep;
|
||||
#endif
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid);
|
||||
sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
|
||||
|
||||
filelist = tcb->group->tg_filelist;
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < filelist->fl_rows; i++)
|
||||
{
|
||||
struct inode *inode = filelist->fl_files[i].f_inode;
|
||||
if (inode)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i, inode->i_crefs);
|
||||
struct inode *inode = filelist->fl_files[i][j].f_inode;
|
||||
if (inode)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j,
|
||||
inode->i_crefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,18 +79,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
FAR struct file_struct *filep;
|
||||
#endif
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid);
|
||||
sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
|
||||
|
||||
filelist = tcb->group->tg_filelist;
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < filelist->fl_rows; i++)
|
||||
{
|
||||
struct inode *inode = filelist->fl_files[i].f_inode;
|
||||
if (inode)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i, inode->i_crefssinfo);
|
||||
struct inode *inode = filelist->fl_files[i][j].f_inode;
|
||||
if (inode)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j,
|
||||
inode->i_crefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,17 +79,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
FAR struct file_struct *filep;
|
||||
#endif
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid);
|
||||
sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
|
||||
|
||||
filelist = tcb->group->tg_filelist;
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < filelist->fl_rows; i++)
|
||||
{
|
||||
struct inode *inode = filelist->fl_files[i].f_inode;
|
||||
if (inode)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n", i, inode->i_crefssinfo);
|
||||
struct inode *inode = filelist->fl_files[i][j].f_inode;
|
||||
if (inode)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j,
|
||||
inode->i_crefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,18 +84,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
FAR struct file_struct *filep;
|
||||
#endif
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid);
|
||||
sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
|
||||
|
||||
filelist = tcb->group->tg_filelist;
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < filelist->fl_rows; i++)
|
||||
{
|
||||
struct inode *inode = filelist->fl_files[i].f_inode;
|
||||
if (inode != NULL)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i, inode->i_crefssinfo);
|
||||
struct inode *inode = filelist->fl_files[i][j].f_inode;
|
||||
if (inode)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j,
|
||||
inode->i_crefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,18 +68,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
FAR struct file_struct *filep;
|
||||
#endif
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sinfo(" TCB=%p name=%s\n", tcb, tcb->argv[0]);
|
||||
sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
|
||||
|
||||
filelist = tcb->group->tg_filelist;
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < filelist->fl_rows; i++)
|
||||
{
|
||||
struct inode *inode = filelist->fl_files[i].f_inode;
|
||||
if (inode)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i, inode->i_crefs);
|
||||
struct inode *inode = filelist->fl_files[i][j].f_inode;
|
||||
if (inode)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j,
|
||||
inode->i_crefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,18 +86,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
FAR struct file_struct *filep;
|
||||
#endif
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid);
|
||||
sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
|
||||
|
||||
filelist = tcb->group->tg_filelist;
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < filelist->fl_rows; i++)
|
||||
{
|
||||
struct inode *inode = filelist->fl_files[i].f_inode;
|
||||
if (inode)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i, inode->i_crefs);
|
||||
struct inode *inode = filelist->fl_files[i][j].f_inode;
|
||||
if (inode)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j,
|
||||
inode->i_crefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,18 +68,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
FAR struct file_struct *filep;
|
||||
#endif
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid);
|
||||
sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
|
||||
|
||||
filelist = tcb->group->tg_filelist;
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < filelist->fl_rows; i++)
|
||||
{
|
||||
struct inode *inode = filelist->fl_files[i].f_inode;
|
||||
if (inode)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i, inode->i_crefs);
|
||||
struct inode *inode = filelist->fl_files[i][j].f_inode;
|
||||
if (inode)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j,
|
||||
inode->i_crefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,29 +63,30 @@
|
||||
#ifdef CONFIG_DUMP_ON_EXIT
|
||||
static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
{
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
FAR struct filelist *filelist;
|
||||
#ifdef CONFIG_FILE_STREAM
|
||||
FAR struct file_struct *filep;
|
||||
#endif
|
||||
int i;
|
||||
#endif
|
||||
int j;
|
||||
|
||||
sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid);
|
||||
sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
filelist = tcb->group->tg_filelist;
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < filelist->fl_rows; i++)
|
||||
{
|
||||
struct inode *inode = filelist->fl_files[i].f_inode;
|
||||
if (inode)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i, inode->i_crefs);
|
||||
struct inode *inode = filelist->fl_files[i][j].f_inode;
|
||||
if (inode)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j,
|
||||
inode->i_crefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FILE_STREAM
|
||||
filep = tcb->group->tg_streamlist->sl_head;
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
* assumed.
|
||||
*/
|
||||
|
||||
#if !defined(CONFIG_DEV_CONSOLE) || CONFIG_NFILE_DESCRIPTORS <= 0
|
||||
#if !defined(CONFIG_DEV_CONSOLE)
|
||||
# undef USE_SERIALDRIVER
|
||||
# undef USE_EARLYSERIALINIT
|
||||
# undef CONFIG_DEV_LOWCONSOLE
|
||||
@@ -115,9 +115,9 @@ typedef void (*up_vector_t)(void);
|
||||
|
||||
extern volatile uint64_t *g_current_regs;
|
||||
|
||||
/* This is the beginning of heap as provided from up_head.S. This is the first
|
||||
* address in DRAM after the loaded program+bss+idle stack. The end of the
|
||||
* heap is CONFIG_RAM_END
|
||||
/* This is the beginning of heap as provided from up_head.S. This is the
|
||||
* first address in DRAM after the loaded program+bss+idle stack. The
|
||||
* end of the heap is CONFIG_RAM_END
|
||||
*/
|
||||
|
||||
extern uint64_t g_idle_topstack;
|
||||
@@ -128,14 +128,14 @@ extern uint64_t g_idle_topstack;
|
||||
extern uint64_t g_intstackbase;
|
||||
#endif
|
||||
|
||||
/* These 'addresses' of these values are setup by the linker script. They are
|
||||
* not actual uint32_t storage locations! They are only used meaningfully in the
|
||||
* following way:
|
||||
/* These 'addresses' of these values are setup by the linker script. They
|
||||
* are not actual uint32_t storage locations! They are only used
|
||||
* meaningfully in the following way:
|
||||
*
|
||||
* - The linker script defines, for example, the symbol_sdata.
|
||||
* - The declareion extern uint32_t _sdata; makes C happy. C will believe
|
||||
* that the value _sdata is the address of a uint32_t variable _data (it is
|
||||
* not!).
|
||||
* that the value _sdata is the address of a uint32_t variable _data
|
||||
* (it is not!).
|
||||
* - We can recoved the linker value then by simply taking the address of
|
||||
* of _data. like: uint32_t *pdata = &_sdata;
|
||||
*/
|
||||
@@ -202,13 +202,8 @@ void up_addregion(void);
|
||||
|
||||
/* Defined in xyz_serial.c */
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
void up_earlyserialinit(void);
|
||||
void up_serialinit(void);
|
||||
#else
|
||||
# define up_earlyserialinit()
|
||||
# define up_serialinit()
|
||||
#endif
|
||||
|
||||
/* Defined in xyz_watchdog.c */
|
||||
|
||||
|
||||
@@ -85,18 +85,23 @@ static void _xtensa_dumponexit(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
FAR struct file_struct *filep;
|
||||
#endif
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid);
|
||||
sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
|
||||
|
||||
filelist = tcb->group->tg_filelist;
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < filelist->fl_rows; i++)
|
||||
{
|
||||
struct inode *inode = filelist->fl_files[i].f_inode;
|
||||
if (inode)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i, inode->i_crefs);
|
||||
struct inode *inode = filelist->fl_files[i][j].f_inode;
|
||||
if (inode)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j,
|
||||
inode->i_crefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,18 +68,23 @@ static void _z16_dumponexit(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
FAR struct file_struct *filep;
|
||||
#endif
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sinfo(" TCB=%p name=%s\n", tcb, tcb->argv[0]);
|
||||
sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
|
||||
|
||||
filelist = tcb->group->tg_filelist;
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < filelist->fl_rows; i++)
|
||||
{
|
||||
struct inode *inode = filelist->fl_files[i].f_inode;
|
||||
if (inode)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i, inode->i_crefs);
|
||||
struct inode *inode = filelist->fl_files[i][j].f_inode;
|
||||
if (inode)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j,
|
||||
inode->i_crefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,18 +70,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg)
|
||||
FAR struct file_struct *filep;
|
||||
#endif
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sinfo(" TCB=%p name=%s\n", tcb, tcb->argv[0]);
|
||||
sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
|
||||
|
||||
filelist = tcb->group->tg_filelist;
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < filelist->fl_rows; i++)
|
||||
{
|
||||
struct inode *inode = filelist->fl_files[i].f_inode;
|
||||
if (inode)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i, inode->i_crefs);
|
||||
struct inode *inode = filelist->fl_files[i][j].f_inode;
|
||||
if (inode)
|
||||
{
|
||||
sinfo(" fd=%d refcount=%d\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j,
|
||||
inode->i_crefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,10 +62,6 @@
|
||||
# error "Mountpoint support is disabled"
|
||||
#endif
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS < 4
|
||||
# error "Not enough file descriptors"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_FS_ROMFS
|
||||
# error "ROMFS support not enabled"
|
||||
#endif
|
||||
|
||||
@@ -44,8 +44,10 @@
|
||||
struct hostfs_rpmsg_server_s
|
||||
{
|
||||
struct rpmsg_endpoint ept;
|
||||
struct file files[CONFIG_NFILE_DESCRIPTORS];
|
||||
void *dirs[CONFIG_NFILE_DESCRIPTORS];
|
||||
FAR struct file **files;
|
||||
FAR void **dirs;
|
||||
int file_rows;
|
||||
int dir_nums;
|
||||
sem_t sem;
|
||||
};
|
||||
|
||||
@@ -154,33 +156,181 @@ static const rpmsg_ept_cb g_hostfs_rpmsg_handler[] =
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int hostfs_rpmsg_attach_file(FAR struct hostfs_rpmsg_server_s *priv,
|
||||
FAR struct file *filep)
|
||||
{
|
||||
FAR struct file **tmp;
|
||||
int ret;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
nxsem_wait(&priv->sem);
|
||||
|
||||
for (i = 0; i < priv->file_rows; i++)
|
||||
{
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
if (priv->files[i][j].f_inode == NULL)
|
||||
{
|
||||
memcpy(&priv->files[i][j], filep, sizeof(*filep));
|
||||
ret = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tmp = kmm_realloc(priv->files, sizeof(FAR struct file *) * (i + 1));
|
||||
DEBUGASSERT(tmp);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
ret = -ENFILE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp[i] = kmm_zalloc(sizeof(struct file) *
|
||||
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK);
|
||||
DEBUGASSERT(tmp[i]);
|
||||
if (tmp[i] == NULL)
|
||||
{
|
||||
kmm_free(tmp);
|
||||
ret = -ENFILE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv->files = tmp;
|
||||
priv->file_rows++;
|
||||
|
||||
memcpy(&priv->files[i][0], filep, sizeof(*filep));
|
||||
ret = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
|
||||
|
||||
out:
|
||||
nxsem_post(&priv->sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_detach_file(FAR struct hostfs_rpmsg_server_s *priv,
|
||||
int fd, FAR struct file *filep)
|
||||
{
|
||||
struct file *tfilep;
|
||||
|
||||
if (fd < 0 || fd >= priv->file_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK)
|
||||
{
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
nxsem_wait(&priv->sem);
|
||||
tfilep = &priv->files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]
|
||||
[fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK];
|
||||
memcpy(filep, tfilep, sizeof(*filep));
|
||||
memset(tfilep, 0, sizeof(*tfilep));
|
||||
nxsem_post(&priv->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FAR struct file *hostfs_rpmsg_get_file(
|
||||
FAR struct hostfs_rpmsg_server_s *priv,
|
||||
int fd)
|
||||
{
|
||||
FAR struct file *filep;
|
||||
|
||||
if (fd < 0 || fd >= priv->file_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nxsem_wait(&priv->sem);
|
||||
filep = &priv->files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]
|
||||
[fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK];
|
||||
nxsem_post(&priv->sem);
|
||||
|
||||
return filep;
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_attach_dir(FAR struct hostfs_rpmsg_server_s *priv,
|
||||
FAR void *dir)
|
||||
{
|
||||
FAR void **tmp;
|
||||
int i;
|
||||
|
||||
nxsem_wait(&priv->sem);
|
||||
for (i = 1; i < priv->dir_nums; i++)
|
||||
{
|
||||
if (priv->dirs[i] == NULL)
|
||||
{
|
||||
priv->dirs[i] = dir;
|
||||
nxsem_post(&priv->sem);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
tmp = kmm_realloc(priv->dirs, sizeof(FAR void *) *
|
||||
(priv->dir_nums + CONFIG_NFILE_DESCRIPTORS_PER_BLOCK));
|
||||
DEBUGASSERT(tmp);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
nxsem_post(&priv->sem);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->dirs = tmp;
|
||||
priv->dir_nums += CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
|
||||
|
||||
priv->dirs[i] = dir;
|
||||
nxsem_post(&priv->sem);
|
||||
return i;
|
||||
}
|
||||
|
||||
static void *hostfs_rpmsg_detach_dir(FAR struct hostfs_rpmsg_server_s *priv,
|
||||
int fd)
|
||||
{
|
||||
FAR void *dir = NULL;
|
||||
|
||||
if (fd >= 1 && fd < priv->dir_nums)
|
||||
{
|
||||
nxsem_wait(&priv->sem);
|
||||
dir = priv->dirs[fd];
|
||||
priv->dirs[fd] = NULL;
|
||||
nxsem_post(&priv->sem);
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
static FAR void *hostfs_rpmsg_get_dir(
|
||||
FAR struct hostfs_rpmsg_server_s *priv,
|
||||
int fd)
|
||||
{
|
||||
FAR void *dir = NULL;
|
||||
|
||||
if (fd >= 1 && fd < priv->dir_nums)
|
||||
{
|
||||
nxsem_wait(&priv->sem);
|
||||
dir = priv->dirs[fd];
|
||||
nxsem_post(&priv->sem);
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_open_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = priv_;
|
||||
FAR struct hostfs_rpmsg_open_s *msg = data;
|
||||
int i;
|
||||
int ret = -ENOENT;
|
||||
struct file file;
|
||||
int ret;
|
||||
|
||||
nxsem_wait(&priv->sem);
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
ret = file_open(&file, msg->pathname, msg->flags, msg->mode);
|
||||
if (ret >= 0)
|
||||
{
|
||||
if (!priv->files[i].f_inode)
|
||||
ret = hostfs_rpmsg_attach_file(priv_, &file);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = file_open(&priv->files[i], msg->pathname, msg->flags,
|
||||
msg->mode);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = i;
|
||||
}
|
||||
|
||||
break;
|
||||
file_close(&file);
|
||||
}
|
||||
}
|
||||
|
||||
nxsem_post(&priv->sem);
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
@@ -189,15 +339,14 @@ static int hostfs_rpmsg_close_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = priv_;
|
||||
FAR struct hostfs_rpmsg_close_s *msg = data;
|
||||
int ret = -ENOENT;
|
||||
struct file file;
|
||||
int ret;
|
||||
|
||||
if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS)
|
||||
ret = hostfs_rpmsg_detach_file(priv_, msg->fd, &file);
|
||||
if (ret >= 0)
|
||||
{
|
||||
nxsem_wait(&priv->sem);
|
||||
ret = file_close(&priv->files[msg->fd]);
|
||||
nxsem_post(&priv->sem);
|
||||
ret = file_close(&file);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
@@ -208,9 +357,9 @@ static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = priv_;
|
||||
FAR struct hostfs_rpmsg_read_s *msg = data;
|
||||
FAR struct hostfs_rpmsg_read_s *rsp;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
uint32_t space;
|
||||
|
||||
@@ -228,9 +377,10 @@ static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept,
|
||||
space = msg->count;
|
||||
}
|
||||
|
||||
if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS)
|
||||
filep = hostfs_rpmsg_get_file(priv_, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_read(&priv->files[msg->fd], rsp->buf, space);
|
||||
ret = file_read(filep, rsp->buf, space);
|
||||
}
|
||||
|
||||
rsp->header.result = ret;
|
||||
@@ -241,13 +391,14 @@ static int hostfs_rpmsg_write_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = priv_;
|
||||
FAR struct hostfs_rpmsg_write_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS)
|
||||
filep = hostfs_rpmsg_get_file(priv_, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_write(&priv->files[msg->fd], msg->buf, msg->count);
|
||||
ret = file_write(filep, msg->buf, msg->count);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
@@ -258,13 +409,14 @@ static int hostfs_rpmsg_lseek_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = priv_;
|
||||
FAR struct hostfs_rpmsg_lseek_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS)
|
||||
filep = hostfs_rpmsg_get_file(priv_, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_seek(&priv->files[msg->fd], msg->offset, msg->whence);
|
||||
ret = file_seek(filep, msg->offset, msg->whence);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
@@ -275,13 +427,14 @@ static int hostfs_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = priv_;
|
||||
FAR struct hostfs_rpmsg_ioctl_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS)
|
||||
filep = hostfs_rpmsg_get_file(priv_, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_ioctl(&priv->files[msg->fd], msg->request, msg->arg);
|
||||
ret = file_ioctl(filep, msg->request, msg->arg);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
@@ -292,13 +445,14 @@ static int hostfs_rpmsg_sync_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = priv_;
|
||||
FAR struct hostfs_rpmsg_sync_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS)
|
||||
filep = hostfs_rpmsg_get_file(priv_, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_fsync(&priv->files[msg->fd]);
|
||||
ret = file_fsync(filep);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
@@ -309,29 +463,23 @@ static int hostfs_rpmsg_dup_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = priv_;
|
||||
FAR struct hostfs_rpmsg_dup_s *msg = data;
|
||||
int i;
|
||||
FAR struct file *filep;
|
||||
struct file newfile;
|
||||
int ret = -ENOENT;
|
||||
|
||||
if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS)
|
||||
filep = hostfs_rpmsg_get_file(priv_, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
nxsem_wait(&priv->sem);
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
ret = file_dup2(filep, &newfile);
|
||||
if (ret >= 0)
|
||||
{
|
||||
if (!priv->files[i].f_inode)
|
||||
ret = hostfs_rpmsg_attach_file(priv_, &newfile);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = file_dup2(&priv->files[msg->fd], &priv->files[i]);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = i;
|
||||
}
|
||||
|
||||
break;
|
||||
file_close(&newfile);
|
||||
}
|
||||
}
|
||||
|
||||
nxsem_post(&priv->sem);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
@@ -342,14 +490,15 @@ static int hostfs_rpmsg_fstat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = priv_;
|
||||
FAR struct hostfs_rpmsg_fstat_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
struct stat buf;
|
||||
|
||||
if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS)
|
||||
filep = hostfs_rpmsg_get_file(priv_, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_fstat(&priv->files[msg->fd], &buf);
|
||||
ret = file_fstat(filep, &buf);
|
||||
if (ret >= 0)
|
||||
{
|
||||
msg->buf = buf;
|
||||
@@ -364,13 +513,14 @@ static int hostfs_rpmsg_ftruncate_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = priv_;
|
||||
FAR struct hostfs_rpmsg_ftruncate_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS)
|
||||
filep = hostfs_rpmsg_get_file(priv_, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_truncate(&priv->files[msg->fd], msg->length);
|
||||
ret = file_truncate(filep, msg->length);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
@@ -381,28 +531,14 @@ static int hostfs_rpmsg_opendir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = priv_;
|
||||
FAR struct hostfs_rpmsg_opendir_s *msg = data;
|
||||
FAR void *dir;
|
||||
int i;
|
||||
int ret = -ENOENT;
|
||||
|
||||
dir = opendir(msg->pathname);
|
||||
if (dir)
|
||||
{
|
||||
nxsem_wait(&priv->sem);
|
||||
for (i = 1; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
{
|
||||
if (!priv->dirs[i])
|
||||
{
|
||||
priv->dirs[i] = dir;
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nxsem_post(&priv->sem);
|
||||
|
||||
ret = hostfs_rpmsg_attach_dir(priv_, dir);
|
||||
if (ret < 0)
|
||||
{
|
||||
closedir(dir);
|
||||
@@ -417,14 +553,15 @@ static int hostfs_rpmsg_readdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = priv_;
|
||||
FAR struct hostfs_rpmsg_readdir_s *msg = data;
|
||||
FAR struct dirent *entry;
|
||||
int ret = -ENOENT;
|
||||
FAR void *dir;
|
||||
|
||||
if (msg->fd >= 1 && msg->fd < CONFIG_NFILE_DESCRIPTORS)
|
||||
dir = hostfs_rpmsg_get_dir(priv_, msg->fd);
|
||||
if (dir)
|
||||
{
|
||||
entry = readdir(priv->dirs[msg->fd]);
|
||||
entry = readdir(dir);
|
||||
if (entry)
|
||||
{
|
||||
msg->type = entry->d_type;
|
||||
@@ -442,13 +579,14 @@ static int hostfs_rpmsg_rewinddir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = priv_;
|
||||
FAR struct hostfs_rpmsg_rewinddir_s *msg = data;
|
||||
int ret = -ENOENT;
|
||||
FAR void *dir;
|
||||
|
||||
if (msg->fd >= 1 && msg->fd < CONFIG_NFILE_DESCRIPTORS)
|
||||
dir = hostfs_rpmsg_get_dir(priv_, msg->fd);
|
||||
if (dir)
|
||||
{
|
||||
rewinddir(priv->dirs[msg->fd]);
|
||||
rewinddir(dir);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
@@ -460,17 +598,14 @@ static int hostfs_rpmsg_closedir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = priv_;
|
||||
FAR struct hostfs_rpmsg_closedir_s *msg = data;
|
||||
int ret = -ENOENT;
|
||||
FAR void *dir;
|
||||
|
||||
if (msg->fd >= 1 && msg->fd < CONFIG_NFILE_DESCRIPTORS)
|
||||
dir = hostfs_rpmsg_detach_dir(priv_, msg->fd);
|
||||
if (dir)
|
||||
{
|
||||
ret = closedir(priv->dirs[msg->fd]);
|
||||
nxsem_wait(&priv->sem);
|
||||
priv->dirs[msg->fd] = NULL;
|
||||
nxsem_post(&priv->sem);
|
||||
ret = ret ? -get_errno() : 0;
|
||||
ret = closedir(dir) ? -get_errno() : 0;
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
@@ -603,16 +738,22 @@ static void hostfs_rpmsg_ns_unbind(FAR struct rpmsg_endpoint *ept)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = ept->priv;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < priv->file_rows; i++)
|
||||
{
|
||||
if (priv->files[i].f_inode)
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
file_close(&priv->files[i]);
|
||||
if (priv->files[i][j].f_inode)
|
||||
{
|
||||
file_close(&priv->files[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
kmm_free(priv->files[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
for (i = 0; i < priv->dir_nums; i++)
|
||||
{
|
||||
if (priv->dirs[i])
|
||||
{
|
||||
@@ -623,6 +764,8 @@ static void hostfs_rpmsg_ns_unbind(FAR struct rpmsg_endpoint *ept)
|
||||
rpmsg_destroy_ept(&priv->ept);
|
||||
nxsem_destroy(&priv->sem);
|
||||
|
||||
kmm_free(priv->files);
|
||||
kmm_free(priv->dirs);
|
||||
kmm_free(priv);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <assert.h>
|
||||
#include <sched.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
@@ -56,6 +57,50 @@ static int _files_semtake(FAR struct filelist *list)
|
||||
|
||||
#define _files_semgive(list) nxsem_post(&list->fl_sem)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_extend
|
||||
****************************************************************************/
|
||||
|
||||
static int files_extend(FAR struct filelist *list, size_t row)
|
||||
{
|
||||
FAR struct file **tmp;
|
||||
int i;
|
||||
|
||||
if (row <= list->fl_rows)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp = kmm_realloc(list->fl_files, sizeof(FAR struct file *) * row);
|
||||
DEBUGASSERT(tmp);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
return -ENFILE;
|
||||
}
|
||||
|
||||
i = list->fl_rows;
|
||||
do
|
||||
{
|
||||
tmp[i] = kmm_zalloc(sizeof(struct file) *
|
||||
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK);
|
||||
if (tmp[i] == NULL)
|
||||
{
|
||||
while (--i >= list->fl_rows)
|
||||
{
|
||||
kmm_free(tmp[i]);
|
||||
}
|
||||
|
||||
kmm_free(tmp);
|
||||
return -ENFILE;
|
||||
}
|
||||
}
|
||||
while (++i < row);
|
||||
|
||||
list->fl_files = tmp;
|
||||
list->fl_rows = row;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@@ -87,6 +132,7 @@ void files_initlist(FAR struct filelist *list)
|
||||
void files_releaselist(FAR struct filelist *list)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
|
||||
DEBUGASSERT(list);
|
||||
|
||||
@@ -95,11 +141,18 @@ void files_releaselist(FAR struct filelist *list)
|
||||
* because there should not be any references in this context.
|
||||
*/
|
||||
|
||||
for (i = CONFIG_NFILE_DESCRIPTORS; i > 0; i--)
|
||||
for (i = list->fl_rows - 1; i >= 0; i--)
|
||||
{
|
||||
file_close(&list->fl_files[i - 1]);
|
||||
for (j = CONFIG_NFILE_DESCRIPTORS_PER_BLOCK - 1; j >= 0; j--)
|
||||
{
|
||||
file_close(&list->fl_files[i][j]);
|
||||
}
|
||||
|
||||
kmm_free(list->fl_files[i]);
|
||||
}
|
||||
|
||||
kmm_free(list->fl_files);
|
||||
|
||||
/* Destroy the semaphore */
|
||||
|
||||
nxsem_destroy(&list->fl_sem);
|
||||
@@ -120,6 +173,7 @@ int files_allocate(FAR struct inode *inode, int oflags, off_t pos,
|
||||
FAR struct filelist *list;
|
||||
int ret;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
/* Get the file descriptor list. It should not be NULL in this context. */
|
||||
|
||||
@@ -134,21 +188,188 @@ int files_allocate(FAR struct inode *inode, int oflags, off_t pos,
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = minfd; i < CONFIG_NFILE_DESCRIPTORS; i++)
|
||||
/* Calcuate minfd whether is in list->fl_files.
|
||||
* if not, allocate a new filechunk.
|
||||
*/
|
||||
|
||||
i = minfd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
|
||||
if (i >= list->fl_rows)
|
||||
{
|
||||
if (!list->fl_files[i].f_inode)
|
||||
ret = files_extend(list, i + 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
list->fl_files[i].f_oflags = oflags;
|
||||
list->fl_files[i].f_pos = pos;
|
||||
list->fl_files[i].f_inode = inode;
|
||||
list->fl_files[i].f_priv = priv;
|
||||
_files_semgive(list);
|
||||
return i;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find free file */
|
||||
|
||||
j = minfd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!list->fl_files[i][j].f_inode)
|
||||
{
|
||||
list->fl_files[i][j].f_oflags = oflags;
|
||||
list->fl_files[i][j].f_pos = pos;
|
||||
list->fl_files[i][j].f_inode = inode;
|
||||
list->fl_files[i][j].f_priv = priv;
|
||||
_files_semgive(list);
|
||||
return i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j;
|
||||
}
|
||||
}
|
||||
while (++j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK);
|
||||
|
||||
j = 0;
|
||||
}
|
||||
while (++i < list->fl_rows);
|
||||
|
||||
/* The space of file array isn't enough, allocate a new filechunk */
|
||||
|
||||
ret = files_extend(list, i + 1);
|
||||
if (ret >= 0)
|
||||
{
|
||||
list->fl_files[i][0].f_oflags = oflags;
|
||||
list->fl_files[i][0].f_pos = pos;
|
||||
list->fl_files[i][0].f_inode = inode;
|
||||
list->fl_files[i][0].f_priv = priv;
|
||||
ret = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
|
||||
}
|
||||
|
||||
_files_semgive(list);
|
||||
return -EMFILE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_duplist
|
||||
*
|
||||
* Description:
|
||||
* Duplicate parent task's file descriptors.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
ret = _files_semtake(plist);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* Probably canceled */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < plist->fl_rows; i++)
|
||||
{
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
FAR struct file *filep;
|
||||
#ifdef CONFIG_FDCLONE_STDIO
|
||||
|
||||
/* Determine how many file descriptors to clone. If
|
||||
* CONFIG_FDCLONE_DISABLE is set, no file descriptors will be
|
||||
* cloned. If CONFIG_FDCLONE_STDIO is set, only the first
|
||||
* three descriptors (stdin, stdout, and stderr) will be
|
||||
* cloned. Otherwise all file descriptors will be cloned.
|
||||
*/
|
||||
|
||||
if (i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j >= 3)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
filep = &plist->fl_files[i][j];
|
||||
if (filep->f_inode == NULL || (filep->f_oflags & O_CLOEXEC) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = files_extend(clist, i + 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Yes... duplicate it for the child */
|
||||
|
||||
ret = file_dup2(filep, &clist->fl_files[i][j]);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
_files_semgive(plist);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fs_getfilep
|
||||
*
|
||||
* Description:
|
||||
* Given a file descriptor, return the corresponding instance of struct
|
||||
* file.
|
||||
*
|
||||
* Input Parameters:
|
||||
* fd - The file descriptor
|
||||
* filep - The location to return the struct file instance
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int fs_getfilep(int fd, FAR struct file **filep)
|
||||
{
|
||||
FAR struct filelist *list;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(filep != NULL);
|
||||
*filep = (FAR struct file *)NULL;
|
||||
|
||||
list = nxsched_get_files();
|
||||
|
||||
/* The file list can be NULL under two cases: (1) One is an 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. The other other is (2) if this is a kernel
|
||||
* thread. Kernel threads have no allocated file descriptors.
|
||||
*/
|
||||
|
||||
if (list == NULL)
|
||||
{
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS_PER_BLOCK * list->fl_rows)
|
||||
{
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
/* The descriptor is in a valid range to file descriptor... Get the
|
||||
* thread-specific file list.
|
||||
*/
|
||||
|
||||
/* And return the file pointer from the list */
|
||||
|
||||
ret = _files_semtake(list);
|
||||
if (ret >= 0)
|
||||
{
|
||||
*filep = &list->fl_files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]
|
||||
[fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK];
|
||||
_files_semgive(list);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -174,17 +395,17 @@ int nx_dup2(int fd1, int fd2)
|
||||
FAR struct filelist *list;
|
||||
int ret;
|
||||
|
||||
if (fd1 < 0 || fd1 >= CONFIG_NFILE_DESCRIPTORS ||
|
||||
fd2 < 0 || fd2 >= CONFIG_NFILE_DESCRIPTORS)
|
||||
{
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
/* Get the file descriptor list. It should not be NULL in this context. */
|
||||
|
||||
list = nxsched_get_files();
|
||||
DEBUGASSERT(list != NULL);
|
||||
|
||||
if (fd1 < 0 || fd1 >= CONFIG_NFILE_DESCRIPTORS_PER_BLOCK * list->fl_rows ||
|
||||
fd2 < 0)
|
||||
{
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
ret = _files_semtake(list);
|
||||
if (ret < 0)
|
||||
{
|
||||
@@ -193,16 +414,25 @@ int nx_dup2(int fd1, int fd2)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Perform the dup2 operation */
|
||||
|
||||
ret = file_dup2(&list->fl_files[fd1], &list->fl_files[fd2]);
|
||||
_files_semgive(list);
|
||||
if (ret < 0)
|
||||
if (fd2 >= CONFIG_NFILE_DESCRIPTORS_PER_BLOCK * list->fl_rows)
|
||||
{
|
||||
return ret;
|
||||
ret = files_extend(list, fd2 / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
_files_semgive(list);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return fd2;
|
||||
/* Perform the dup2 operation */
|
||||
|
||||
ret = file_dup2(&list->fl_files[fd1 / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]
|
||||
[fd1 % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK],
|
||||
&list->fl_files[fd2 / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]
|
||||
[fd2 % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]);
|
||||
_files_semgive(list);
|
||||
|
||||
return ret < 0 ? ret : fd2;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -262,23 +492,28 @@ int nx_close(int fd)
|
||||
list = nxsched_get_files();
|
||||
DEBUGASSERT(list != NULL);
|
||||
|
||||
/* If the file was properly opened, there should be an inode assigned */
|
||||
|
||||
if (fd < 0 || fd >= CONFIG_NFILE_DESCRIPTORS ||
|
||||
!list->fl_files[fd].f_inode)
|
||||
{
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
/* Perform the protected close operation */
|
||||
|
||||
ret = _files_semtake(list);
|
||||
if (ret >= 0)
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = file_close(&list->fl_files[fd]);
|
||||
_files_semgive(list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If the file was properly opened, there should be an inode assigned */
|
||||
|
||||
if (fd < 0 || fd >= list->fl_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK ||
|
||||
!list->fl_files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]
|
||||
[fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK].f_inode)
|
||||
{
|
||||
_files_semgive(list);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
ret = file_close(&list->fl_files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]
|
||||
[fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]);
|
||||
_files_semgive(list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1024,6 +1024,7 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile,
|
||||
size_t copysize;
|
||||
size_t totalsize;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
DEBUGASSERT(group != NULL);
|
||||
|
||||
@@ -1046,27 +1047,32 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile,
|
||||
|
||||
/* Examine each open file descriptor */
|
||||
|
||||
for (i = 0, file = group->tg_filelist.fl_files;
|
||||
i < CONFIG_NFILE_DESCRIPTORS;
|
||||
i++, file++)
|
||||
for (i = 0; i < group->tg_filelist.fl_rows; i++)
|
||||
{
|
||||
/* Is there an inode associated with the file descriptor? */
|
||||
|
||||
if (file->f_inode && !INODE_IS_SOCKET(file->f_inode))
|
||||
for (j = 0, file = group->tg_filelist.fl_files[i];
|
||||
j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
|
||||
j++, file++)
|
||||
{
|
||||
linesize = snprintf(procfile->line, STATUS_LINELEN,
|
||||
"%3d %8ld %04x\n", i, (long)file->f_pos,
|
||||
file->f_oflags);
|
||||
copysize = procfs_memcpy(procfile->line, linesize, buffer,
|
||||
remaining, &offset);
|
||||
/* Is there an inode associated with the file descriptor? */
|
||||
|
||||
totalsize += copysize;
|
||||
buffer += copysize;
|
||||
remaining -= copysize;
|
||||
|
||||
if (totalsize >= buflen)
|
||||
if (file->f_inode && !INODE_IS_SOCKET(file->f_inode))
|
||||
{
|
||||
return totalsize;
|
||||
linesize = snprintf(procfile->line, STATUS_LINELEN,
|
||||
"%3d %8ld %04x\n",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK +
|
||||
j, (long)file->f_pos,
|
||||
file->f_oflags);
|
||||
copysize = procfs_memcpy(procfile->line, linesize, buffer,
|
||||
remaining, &offset);
|
||||
|
||||
totalsize += copysize;
|
||||
buffer += copysize;
|
||||
remaining -= copysize;
|
||||
|
||||
if (totalsize >= buflen)
|
||||
{
|
||||
return totalsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1089,30 +1095,33 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile,
|
||||
|
||||
/* Examine each open socket descriptor */
|
||||
|
||||
for (i = 0, file = group->tg_filelist.fl_files;
|
||||
i < CONFIG_NFILE_DESCRIPTORS;
|
||||
i++, file++)
|
||||
for (i = 0; i < group->tg_filelist.fl_rows; i++)
|
||||
{
|
||||
/* Is there an connection associated with the socket descriptor? */
|
||||
|
||||
if (file->f_inode && INODE_IS_SOCKET(file->f_inode))
|
||||
for (j = 0, file = group->tg_filelist.fl_files[i];
|
||||
j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
|
||||
j++, file++)
|
||||
{
|
||||
FAR struct socket *socket = file->f_priv;
|
||||
linesize = snprintf(procfile->line, STATUS_LINELEN,
|
||||
"%3d %3d %02x",
|
||||
i + CONFIG_NFILE_DESCRIPTORS,
|
||||
socket->s_type,
|
||||
socket->s_flags);
|
||||
copysize = procfs_memcpy(procfile->line, linesize, buffer,
|
||||
remaining, &offset);
|
||||
/* Is there an connection associated with the socket descriptor? */
|
||||
|
||||
totalsize += copysize;
|
||||
buffer += copysize;
|
||||
remaining -= copysize;
|
||||
|
||||
if (totalsize >= buflen)
|
||||
if (file->f_inode && INODE_IS_SOCKET(file->f_inode))
|
||||
{
|
||||
return totalsize;
|
||||
FAR struct socket *socket = file->f_priv;
|
||||
linesize = snprintf(procfile->line, STATUS_LINELEN,
|
||||
"%3d %3d %02x",
|
||||
i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK +
|
||||
j, socket->s_type,
|
||||
socket->s_flags);
|
||||
copysize = procfs_memcpy(procfile->line, linesize, buffer,
|
||||
remaining, &offset);
|
||||
|
||||
totalsize += copysize;
|
||||
buffer += copysize;
|
||||
remaining -= copysize;
|
||||
|
||||
if (totalsize >= buflen)
|
||||
{
|
||||
return totalsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
# Common file/socket descriptor support
|
||||
|
||||
CSRCS += fs_close.c fs_dup.c fs_dup2.c fs_fcntl.c
|
||||
CSRCS += fs_epoll.c fs_fstat.c fs_fstatfs.c fs_getfilep.c fs_ioctl.c
|
||||
CSRCS += fs_epoll.c fs_fstat.c fs_fstatfs.c fs_ioctl.c
|
||||
CSRCS += fs_lseek.c fs_mkdir.c fs_open.c fs_poll.c fs_read.c fs_rename.c
|
||||
CSRCS += fs_rmdir.c fs_statfs.c fs_stat.c fs_select.c fs_unlink.c fs_write.c
|
||||
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/****************************************************************************
|
||||
* fs/vfs/fs_getfilep.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* 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"
|
||||
|
||||
/****************************************************************************
|
||||
* 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.
|
||||
*
|
||||
* Input Parameters:
|
||||
* fd - The file descriptor
|
||||
* filep - The location to return the struct file instance
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int fs_getfilep(int fd, FAR struct file **filep)
|
||||
{
|
||||
FAR struct filelist *list;
|
||||
|
||||
DEBUGASSERT(filep != NULL);
|
||||
*filep = (FAR struct file *)NULL;
|
||||
|
||||
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
|
||||
{
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
/* The descriptor is in a valid range to file descriptor... Get the
|
||||
* thread-specific file list.
|
||||
*/
|
||||
|
||||
list = nxsched_get_files();
|
||||
|
||||
/* The file list can be NULL under two cases: (1) One is an 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. The other other is (2) if this is a kernel
|
||||
* thread. Kernel threads have no allocated file descriptors.
|
||||
*/
|
||||
|
||||
if (list == NULL)
|
||||
{
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/* And return the file pointer from the list */
|
||||
|
||||
*filep = &list->fl_files[fd];
|
||||
return OK;
|
||||
}
|
||||
@@ -113,11 +113,7 @@ struct aiocb
|
||||
FAR volatile void *aio_buf; /* Location of buffer */
|
||||
off_t aio_offset; /* File offset */
|
||||
size_t aio_nbytes; /* Length of transfer */
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 127
|
||||
int16_t aio_fildes; /* File descriptor (should be int) */
|
||||
#else
|
||||
int8_t aio_fildes; /* File descriptor (should be int) */
|
||||
#endif
|
||||
int8_t aio_reqprio; /* Request priority offset (not used, should be int) */
|
||||
uint8_t aio_lio_opcode; /* Operation to be performed (should be int) */
|
||||
|
||||
|
||||
@@ -120,10 +120,10 @@
|
||||
#define _POSIX_MAX_INPUT 255
|
||||
#define _POSIX_NAME_MAX CONFIG_NAME_MAX
|
||||
#define _POSIX_NGROUPS_MAX 0
|
||||
#define _POSIX_OPEN_MAX CONFIG_NFILE_DESCRIPTORS
|
||||
#define _POSIX_OPEN_MAX INT_MAX
|
||||
#define _POSIX_PATH_MAX CONFIG_PATH_MAX
|
||||
#define _POSIX_PIPE_BUF 512
|
||||
#define _POSIX_STREAM_MAX CONFIG_NFILE_DESCRIPTORS
|
||||
#define _POSIX_STREAM_MAX INT_MAX
|
||||
#define _POSIX_TZNAME_MAX 3
|
||||
|
||||
#ifdef CONFIG_SMALL_MEMORY
|
||||
|
||||
@@ -377,12 +377,18 @@ struct file
|
||||
FAR void *f_priv; /* Per file driver private data */
|
||||
};
|
||||
|
||||
/* This defines a list of files indexed by the file descriptor */
|
||||
/* This defines a two layer array of files indexed by the file descriptor.
|
||||
* Each row of this array is fixed size: CONFIG_NFILE_DESCRIPTORS_PER_BLOCK.
|
||||
* You can get file instance in filelist by the follow methods:
|
||||
* (file descriptor / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK) as row index and
|
||||
* (file descriptor % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK) as column index.
|
||||
*/
|
||||
|
||||
struct filelist
|
||||
{
|
||||
sem_t fl_sem; /* Manage access to the file list */
|
||||
struct file fl_files[CONFIG_NFILE_DESCRIPTORS];
|
||||
sem_t fl_sem; /* 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 */
|
||||
};
|
||||
|
||||
/* The following structure defines the list of files used for standard C I/O.
|
||||
@@ -713,6 +719,20 @@ void files_initlist(FAR struct filelist *list);
|
||||
|
||||
void files_releaselist(FAR struct filelist *list);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: files_duplist
|
||||
*
|
||||
* Description:
|
||||
* Duplicate parent task's file descriptors.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: file_dup
|
||||
*
|
||||
|
||||
@@ -77,13 +77,6 @@
|
||||
# define _NX_RECVFROM(s,b,l,f,a,n) recvfrom(s,b,l,f,a,n)
|
||||
#endif
|
||||
|
||||
/* Socket descriptors are the index into the TCB sockets list, offset by the
|
||||
* following amount. This offset is used to distinguish file descriptors from
|
||||
* socket descriptors
|
||||
*/
|
||||
|
||||
#define __SOCKFD_OFFSET CONFIG_NFILE_DESCRIPTORS
|
||||
|
||||
/* Capabilities of a socket */
|
||||
|
||||
#define SOCKCAP_NONBLOCKING (1 << 0) /* Bit 0: Socket supports non-blocking
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
/* Get the total number of descriptors that we will have to support */
|
||||
|
||||
#define FD_SETSIZE CONFIG_NFILE_DESCRIPTORS
|
||||
#define FD_SETSIZE 256
|
||||
|
||||
/* We will use a 32-bit bitsets to represent the set of descriptors. How
|
||||
* many uint32_t's do we need to span all descriptors?
|
||||
|
||||
@@ -64,7 +64,7 @@ int posix_spawn_file_actions_addclose(
|
||||
{
|
||||
FAR struct spawn_close_file_action_s *entry;
|
||||
|
||||
DEBUGASSERT(file_actions && fd >= 0 && fd < CONFIG_NFILE_DESCRIPTORS);
|
||||
DEBUGASSERT(file_actions && fd >= 0);
|
||||
|
||||
/* Allocate the action list entry */
|
||||
|
||||
|
||||
@@ -65,9 +65,7 @@ int posix_spawn_file_actions_adddup2(
|
||||
{
|
||||
FAR struct spawn_dup2_file_action_s *entry;
|
||||
|
||||
DEBUGASSERT(file_actions &&
|
||||
fd1 >= 0 && fd1 < CONFIG_NFILE_DESCRIPTORS &&
|
||||
fd2 >= 0 && fd2 < CONFIG_NFILE_DESCRIPTORS);
|
||||
DEBUGASSERT(file_actions && fd1 >= 0 && fd2 >= 0);
|
||||
|
||||
/* Allocate the action list entry */
|
||||
|
||||
|
||||
@@ -79,16 +79,16 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int posix_spawn_file_actions_addopen(FAR posix_spawn_file_actions_t *file_actions,
|
||||
int fd, FAR const char *path, int oflags,
|
||||
mode_t mode)
|
||||
int posix_spawn_file_actions_addopen(
|
||||
FAR posix_spawn_file_actions_t *file_actions,
|
||||
int fd, FAR const char *path, int oflags,
|
||||
mode_t mode)
|
||||
{
|
||||
FAR struct spawn_open_file_action_s *entry;
|
||||
size_t len;
|
||||
size_t alloc;
|
||||
|
||||
DEBUGASSERT(file_actions && path &&
|
||||
fd >= 0 && fd < CONFIG_NFILE_DESCRIPTORS);
|
||||
DEBUGASSERT(file_actions && path && fd >= 0);
|
||||
|
||||
/* Get the size of the action including storage for the path plus its NUL
|
||||
* terminating character.
|
||||
@@ -111,10 +111,11 @@ int posix_spawn_file_actions_addopen(FAR posix_spawn_file_actions_t *file_action
|
||||
entry->fd = fd;
|
||||
entry->oflags = oflags;
|
||||
entry->mode = mode;
|
||||
strncpy(entry->path, path, len+1);
|
||||
strncpy(entry->path, path, len + 1);
|
||||
|
||||
/* And add it to the file action list */
|
||||
|
||||
add_file_action(file_actions, (FAR struct spawn_general_file_action_s *)entry);
|
||||
add_file_action(file_actions,
|
||||
(FAR struct spawn_general_file_action_s *)entry);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ long sysconf(int name)
|
||||
switch (name)
|
||||
{
|
||||
case _SC_OPEN_MAX:
|
||||
return CONFIG_NFILE_DESCRIPTORS;
|
||||
return _POSIX_OPEN_MAX;
|
||||
|
||||
case _SC_ATEXIT_MAX:
|
||||
#ifdef CONFIG_SCHED_EXIT_MAX
|
||||
|
||||
@@ -229,6 +229,7 @@ int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
|
||||
{
|
||||
FAR struct socket *psock = sockfd_socket(sockfd);
|
||||
FAR struct socket *newsock;
|
||||
FAR struct file *filep;
|
||||
int newfd;
|
||||
int errcode;
|
||||
int ret;
|
||||
@@ -246,7 +247,7 @@ int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
|
||||
* used in the wrong context.
|
||||
*/
|
||||
|
||||
if ((unsigned int)sockfd < CONFIG_NFILE_DESCRIPTORS)
|
||||
if (fs_getfilep(sockfd, &filep) == 0)
|
||||
{
|
||||
errcode = ENOTSOCK;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
|
||||
#include "socket/socket.h"
|
||||
|
||||
/****************************************************************************
|
||||
@@ -128,6 +130,7 @@ int psock_listen(FAR struct socket *psock, int backlog)
|
||||
int listen(int sockfd, int backlog)
|
||||
{
|
||||
FAR struct socket *psock = sockfd_socket(sockfd);
|
||||
FAR struct file *filep;
|
||||
int errcode;
|
||||
int ret;
|
||||
|
||||
@@ -140,7 +143,7 @@ int listen(int sockfd, int backlog)
|
||||
* descriptor used in the wrong context.
|
||||
*/
|
||||
|
||||
if ((unsigned int)sockfd < CONFIG_NFILE_DESCRIPTORS)
|
||||
if (fs_getfilep(sockfd, &filep) == 0)
|
||||
{
|
||||
errcode = ENOTSOCK;
|
||||
}
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
/****************************************************************************
|
||||
* net/socket/net_dup.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sched.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "socket/socket.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: psock_dup
|
||||
*
|
||||
* Description:
|
||||
* Clone a socket descriptor to an arbitrary descriptor number.
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, returns the number of new socket. On any error,
|
||||
* a negated errno value is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int psock_dup(FAR struct socket *psock, int minsd)
|
||||
{
|
||||
FAR struct socket *psock2;
|
||||
int sockfd2;
|
||||
int ret;
|
||||
|
||||
/* Make sure that the minimum socket descriptor is within the legal range.
|
||||
* The minimum value we receive is relative to file descriptor 0; we need
|
||||
* map it relative of the first socket descriptor.
|
||||
*/
|
||||
|
||||
if (minsd >= CONFIG_NFILE_DESCRIPTORS)
|
||||
{
|
||||
minsd -= CONFIG_NFILE_DESCRIPTORS;
|
||||
}
|
||||
else
|
||||
{
|
||||
minsd = 0;
|
||||
}
|
||||
|
||||
/* Lock the scheduler throughout the following */
|
||||
|
||||
sched_lock();
|
||||
|
||||
/* Verify that the sockfd corresponds to valid, allocated socket */
|
||||
|
||||
if (!psock || psock->s_crefs <= 0)
|
||||
{
|
||||
ret = -EBADF;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Allocate a new socket descriptor */
|
||||
|
||||
sockfd2 = sockfd_allocate(minsd);
|
||||
if (sockfd2 < 0)
|
||||
{
|
||||
ret = -ENFILE;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Get the socket structure underlying the new descriptor */
|
||||
|
||||
psock2 = sockfd_socket(sockfd2);
|
||||
if (!psock2)
|
||||
{
|
||||
ret = -ENOSYS; /* Should not happen */
|
||||
goto errout_with_sockfd;
|
||||
}
|
||||
|
||||
/* Duplicate the socket state */
|
||||
|
||||
ret = psock_dup2(psock, psock2);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_sockfd;
|
||||
}
|
||||
|
||||
sched_unlock();
|
||||
return sockfd2;
|
||||
|
||||
errout_with_sockfd:
|
||||
sockfd_release(sockfd2);
|
||||
|
||||
errout:
|
||||
sched_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: net_dup
|
||||
*
|
||||
* Description:
|
||||
* Clone a socket descriptor to an arbitrary descriptor number.
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, returns the number of new socket. On any error,
|
||||
* a negated errno value is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int net_dup(int sockfd, int minsd)
|
||||
{
|
||||
return psock_dup(sockfd_socket(sockfd), minsd);
|
||||
}
|
||||
@@ -1058,12 +1058,12 @@ config SDCLONE_DISABLE
|
||||
descriptors by task_create() when a new task is started. If
|
||||
set, all sockets will appear to be closed in the new task.
|
||||
|
||||
config NFILE_DESCRIPTORS
|
||||
int "Maximum number of file descriptors per task"
|
||||
default 16
|
||||
config NFILE_DESCRIPTORS_PER_BLOCK
|
||||
int "The number of file descriptors per block"
|
||||
default 8
|
||||
range 3 99999
|
||||
---help---
|
||||
The maximum number of file descriptors per task (one for each open)
|
||||
The number of file descriptors per block(one for each open)
|
||||
|
||||
config FILE_STREAM
|
||||
bool "Enable FILE stream"
|
||||
|
||||
@@ -25,94 +25,12 @@
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sched.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/net/net.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "group/group.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Determine how many file descriptors to clone. If CONFIG_FDCLONE_DISABLE
|
||||
* is set, no file descriptors will be cloned. If CONFIG_FDCLONE_STDIO is
|
||||
* set, only the first three descriptors (stdin, stdout, and stderr) will
|
||||
* be cloned. Otherwise all file descriptors will be cloned.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_FDCLONE_STDIO) && CONFIG_NFILE_DESCRIPTORS > 3
|
||||
# define NFDS_TOCLONE 3
|
||||
#else
|
||||
# define NFDS_TOCLONE CONFIG_NFILE_DESCRIPTORS
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sched_dupfiles
|
||||
*
|
||||
* Description:
|
||||
* Duplicate parent task's file descriptors.
|
||||
*
|
||||
* Input Parameters:
|
||||
* tcb - tcb of the new task.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_FDCLONE_DISABLE
|
||||
static inline void sched_dupfiles(FAR struct task_tcb_s *tcb)
|
||||
{
|
||||
/* The parent task is the one at the head of the ready-to-run list */
|
||||
|
||||
FAR struct tcb_s *rtcb = this_task();
|
||||
FAR struct file *parent;
|
||||
FAR struct file *child;
|
||||
int i;
|
||||
|
||||
DEBUGASSERT(tcb && tcb->cmn.group && rtcb->group);
|
||||
|
||||
/* Duplicate the file descriptors. This will be either all of the
|
||||
* file descriptors or just the first three (stdin, stdout, and stderr)
|
||||
* if CONFIG_FDCLONE_STDIO is defined. NFSDS_TOCLONE is set
|
||||
* accordingly above.
|
||||
*/
|
||||
|
||||
/* Get pointers to the parent and child task file lists */
|
||||
|
||||
parent = rtcb->group->tg_filelist.fl_files;
|
||||
child = tcb->cmn.group->tg_filelist.fl_files;
|
||||
|
||||
/* Check each file in the parent file list */
|
||||
|
||||
for (i = 0; i < NFDS_TOCLONE; i++)
|
||||
{
|
||||
/* Check if this file is opened by the parent. We can tell if
|
||||
* if the file is open because it contain a reference to a non-NULL
|
||||
* i-node structure.
|
||||
*/
|
||||
|
||||
if (parent[i].f_inode &&
|
||||
(parent[i].f_oflags & O_CLOEXEC) == 0)
|
||||
{
|
||||
/* Yes... duplicate it for the child */
|
||||
|
||||
file_dup2(&parent[i], &child[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else /* !CONFIG_FDCLONE_DISABLE */
|
||||
# define sched_dupfiles(tcb)
|
||||
#endif /* !CONFIG_FDCLONE_DISABLE */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@@ -138,6 +56,10 @@ static inline void sched_dupfiles(FAR struct task_tcb_s *tcb)
|
||||
int group_setuptaskfiles(FAR struct task_tcb_s *tcb)
|
||||
{
|
||||
FAR struct task_group_s *group = tcb->cmn.group;
|
||||
#ifndef CONFIG_FDCLONE_DISABLE
|
||||
FAR struct tcb_s *rtcb = this_task();
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(group);
|
||||
#ifndef CONFIG_DISABLE_PTHREAD
|
||||
@@ -149,9 +71,17 @@ int group_setuptaskfiles(FAR struct task_tcb_s *tcb)
|
||||
|
||||
files_initlist(&group->tg_filelist);
|
||||
|
||||
#ifndef CONFIG_FDCLONE_DISABLE
|
||||
DEBUGASSERT(rtcb->group);
|
||||
|
||||
/* Duplicate the parent task's file descriptors */
|
||||
|
||||
sched_dupfiles(tcb);
|
||||
ret = files_duplist(&rtcb->group->tg_filelist, &group->tg_filelist);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocate file/socket streams for the new TCB */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user