diff --git a/crypto/cryptodev.c b/crypto/cryptodev.c index f5c17632cd8..ce242b87180 100644 --- a/crypto/cryptodev.c +++ b/crypto/cryptodev.c @@ -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); diff --git a/drivers/misc/optee.c b/drivers/misc/optee.c index 04153185668..43ec2a5e470 100644 --- a/drivers/misc/optee.c +++ b/drivers/misc/optee.c @@ -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); diff --git a/fs/inode/fs_files.c b/fs/inode/fs_files.c index 3b17194f86c..a4e027541f9 100644 --- a/fs/inode/fs_files.c +++ b/fs/inode/fs_files.c @@ -59,56 +59,39 @@ ****************************************************************************/ /**************************************************************************** - * Name: files_fget_by_index + * Name: fdlist_get_by_index ****************************************************************************/ -static FAR struct file *files_fget_by_index(FAR struct filelist *list, - int l1, int l2, FAR bool *new) +static void fdlist_get_by_index(FAR struct fdlist *list, + int l1, int l2, + FAR struct file **filep, + FAR struct fd **fdp) { - FAR struct file *filep; + FAR struct fd *fdp1; irqstate_t flags; flags = spin_lock_irqsave_notrace(&list->fl_lock); - filep = &list->fl_files[l1][l2]; + fdp1 = &list->fl_fds[l1][l2]; + *filep = fdp1->f_file; + if (*filep != NULL) + { + atomic_fetch_add(&(*filep)->f_refs, 1); + } + spin_unlock_irqrestore_notrace(&list->fl_lock, flags); - - if (filep->f_inode != NULL) + if (fdp != NULL) { - /* When the reference count is zero but the inode has not yet been - * released, At this point we should return a null pointer - */ - - int32_t refs = atomic_read(&filep->f_refs); - do - { - if (refs == 0) - { - filep = NULL; - break; - } - } - while (!atomic_try_cmpxchg(&filep->f_refs, &refs, refs + 1)); + *fdp = fdp1; } - else if (new == NULL) - { - filep = NULL; - } - else if (atomic_fetch_add(&filep->f_refs, 1) == 0) - { - atomic_fetch_add(&filep->f_refs, 1); - *new = true; - } - - return filep; } /**************************************************************************** - * Name: files_extend + * Name: fdlist_extend ****************************************************************************/ -static int files_extend(FAR struct filelist *list, size_t row) +static int fdlist_extend(FAR struct fdlist *list, size_t row) { - FAR struct file **files; + FAR struct fd **fds; uint8_t orig_rows; FAR void *tmp; int flags; @@ -123,13 +106,13 @@ static int files_extend(FAR struct filelist *list, size_t row) if (CONFIG_NFILE_DESCRIPTORS_PER_BLOCK * orig_rows > OPEN_MAX) { - files_dumplist(list); + fdlist_dump(list); return -EMFILE; } - files = fs_heap_malloc(sizeof(FAR struct file *) * row); - DEBUGASSERT(files); - if (files == NULL) + fds = fs_heap_malloc(sizeof(FAR struct fd *) * row); + DEBUGASSERT(fds); + if (fds == NULL) { return -ENFILE; } @@ -137,16 +120,16 @@ static int files_extend(FAR struct filelist *list, size_t row) i = orig_rows; do { - files[i] = fs_heap_zalloc(sizeof(struct file) * - CONFIG_NFILE_DESCRIPTORS_PER_BLOCK); - if (files[i] == NULL) + fds[i] = fs_heap_zalloc(sizeof(struct fd) * + CONFIG_NFILE_DESCRIPTORS_PER_BLOCK); + if (fds[i] == NULL) { while (--i >= orig_rows) { - fs_heap_free(files[i]); + fs_heap_free(fds[i]); } - fs_heap_free(files); + fs_heap_free(fds); return -ENFILE; } } @@ -165,27 +148,26 @@ static int files_extend(FAR struct filelist *list, size_t row) for (j = orig_rows; j < i; j++) { - fs_heap_free(files[j]); + fs_heap_free(fds[j]); } - fs_heap_free(files); + fs_heap_free(fds); return OK; } - if (list->fl_files != NULL) + if (list->fl_fds != NULL) { - memcpy(files, list->fl_files, - list->fl_rows * sizeof(FAR struct file *)); + memcpy(fds, list->fl_fds, list->fl_rows * sizeof(FAR struct fd *)); } - tmp = list->fl_files; - list->fl_files = files; + tmp = list->fl_fds; + list->fl_fds = fds; list->fl_rows = row; spin_unlock_irqrestore_notrace(&list->fl_lock, flags); - if (tmp != NULL && tmp != &list->fl_prefile) + if (tmp != NULL && tmp != &list->fl_prefd) { fs_heap_free(tmp); } @@ -193,10 +175,65 @@ static int files_extend(FAR struct filelist *list, size_t row) return OK; } +/**************************************************************************** + * Name: fdlist_uninstall + ****************************************************************************/ + +static void fdlist_uninstall(FAR struct fdlist *list, FAR struct fd *fdp) +{ + FAR struct file *filep = NULL; + irqstate_t flags; + + flags = spin_lock_irqsave_notrace(&list->fl_lock); + + if (fdp->f_file != NULL) + { +#ifdef CONFIG_FDSAN + fdp->f_tag_fdsan = 0; +#endif +#ifdef CONFIG_FDCHECK + fdp->f_tag_fdcheck = 0; +#endif + filep = fdp->f_file; + fdp->f_file = NULL; + } + + spin_unlock_irqrestore_notrace(&list->fl_lock, flags); + file_put(filep); +} + +static void fdlist_install(FAR struct fdlist *list, int fd, + FAR struct file *filep, int oflags) +{ + FAR struct file *oldfilep; + FAR struct fd *fdp; + irqstate_t flags; + int l1; + int l2; + + l1 = fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; + l2 = fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; + + flags = spin_lock_irqsave_notrace(&list->fl_lock); + + fdp = &list->fl_fds[l1][l2]; + oldfilep = fdp->f_file; + fdp->f_file = filep; + file_ref(filep); + fdp->f_cloexec = !!(oflags & O_CLOEXEC); + FS_ADD_BACKTRACE(fdp); + + spin_unlock_irqrestore_notrace(&list->fl_lock, flags); + file_put(oldfilep); +} + +/**************************************************************************** + * Name: task_fssync + ****************************************************************************/ + static void task_fssync(FAR struct tcb_s *tcb, FAR void *arg) { FAR struct tcb_s *ctcb; - FAR struct file *filep; int pid = tcb->pid; uint8_t rows; int i; @@ -207,28 +244,25 @@ static void task_fssync(FAR struct tcb_s *tcb, FAR void *arg) return; } - rows = tcb->group->tg_filelist.fl_rows; + rows = tcb->group->tg_fdlist.fl_rows; for (i = 0; i < rows; i++) { for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { + FAR struct file *filep; + ctcb = nxsched_get_tcb(pid); if (ctcb == NULL || ctcb->group == NULL || ctcb != tcb) { return; } - filep = files_fget_by_index(&ctcb->group->tg_filelist, - i, j, NULL); + fdlist_get_by_index(&ctcb->group->tg_fdlist, i, j, &filep, NULL); if (filep != NULL) { file_fsync(filep); - ctcb = nxsched_get_tcb(pid); - if (ctcb != NULL && ctcb->group != NULL && ctcb == tcb) - { - file_put(filep); - } + file_put(filep); } } } @@ -239,14 +273,14 @@ static void task_fssync(FAR struct tcb_s *tcb, FAR void *arg) ****************************************************************************/ /**************************************************************************** - * 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 and @@ -258,70 +292,46 @@ static void task_fssync(FAR struct tcb_s *tcb, FAR void *arg) * ****************************************************************************/ -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) { - FAR struct filelist *list; FAR struct file *filep1; - FAR struct file *filep; - bool new = false; - int count; int ret; if (fd1 == fd2) { - return fd1; + return -EINVAL; } #ifdef CONFIG_FDCHECK - fd1 = fdcheck_restore(fd1); fd2 = fdcheck_restore(fd2); #endif /* Get the file descriptor list. It should not be NULL in this context. */ - list = nxsched_get_files_from_tcb(tcb); - count = files_countlist(list); - - if (fd1 < 0 || fd1 >= count || fd2 < 0) + if (fd2 < 0) { return -EBADF; } - if (fd2 >= count) + if (fd2 >= fdlist_count(list)) { - ret = files_extend(list, fd2 / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + 1); + ret = fdlist_extend(list, + fd2 / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + 1); if (ret < 0) { return ret; } } - filep1 = files_fget(list, fd1); - if (filep1 == NULL) - { - return -EBADF; - } - - filep = files_fget_by_index(list, - fd2 / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK, - fd2 % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK, - &new); - - /* Perform the dup3 operation */ - - ret = file_dup3(filep1, filep, flags); - file_put(filep1); - file_put(filep); + ret = fdlist_get(list, fd1, &filep1); if (ret < 0) { - if (new) - { - file_put(filep); - } - return ret; } + fdlist_install(list, fd2, filep1, flags); + file_put(filep1); + #ifdef CONFIG_FDCHECK return fdcheck_protect(fd2); #else @@ -330,37 +340,37 @@ int nx_dup3_from_tcb(FAR struct tcb_s *tcb, int fd1, int fd2, int flags) } /**************************************************************************** - * Name: files_initlist + * Name: fdlist_init * - * Description: Initializes the list of files for a new task + * Description: Initializes the list of file descriptors for a new task. * ****************************************************************************/ -void files_initlist(FAR struct filelist *list) +void fdlist_init(FAR struct fdlist *list) { /* The first row will reuse pre-allocated files, which will avoid * unnecessary allocator accesses during file initialization. */ list->fl_rows = 1; - list->fl_files = &list->fl_prefile; - list->fl_prefile = list->fl_prefiles; + list->fl_fds = &list->fl_prefd; + list->fl_prefd = list->fl_prefds; spin_lock_init(&list->fl_lock); } /**************************************************************************** - * 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) { FAR char *path; - int count = files_countlist(list); + int count = fdlist_count(list); int i; syslog(LOG_INFO, "%-4s%-4s%-8s%-5s%-10s%-14s" @@ -379,7 +389,8 @@ void files_dumplist(FAR struct filelist *list) for (i = 0; i < count; i++) { - FAR struct file *filep = files_fget(list, i); + FAR struct fd *fdp; + FAR struct file *filep; #if CONFIG_FS_BACKTRACE > 0 char buf[BACKTRACE_BUFFER_SIZE(CONFIG_FS_BACKTRACE)]; @@ -387,7 +398,7 @@ void files_dumplist(FAR struct filelist *list) /* Is there an inode associated with the file descriptor? */ - if (filep == NULL || filep->f_inode == NULL) + if (fdlist_get2(list, i, &filep, &fdp) < 0) { continue; } @@ -398,7 +409,7 @@ void files_dumplist(FAR struct filelist *list) } #if CONFIG_FS_BACKTRACE > 0 - backtrace_format(buf, sizeof(buf), filep->f_backtrace, + backtrace_format(buf, sizeof(buf), fdp->f_backtrace, CONFIG_FS_BACKTRACE); #endif @@ -413,6 +424,7 @@ void files_dumplist(FAR struct filelist *list) , buf #endif ); + file_put(filep); } @@ -421,17 +433,17 @@ void files_dumplist(FAR struct filelist *list) #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) { int i; int j; @@ -445,90 +457,120 @@ void files_putlist(FAR struct filelist *list) { for (j = CONFIG_NFILE_DESCRIPTORS_PER_BLOCK - 1; j >= 0; j--) { - file_close(&list->fl_files[i][j]); + fdlist_close(list, i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j); } if (i != 0) { - fs_heap_free(list->fl_files[i]); + fs_heap_free(list->fl_fds[i]); } } - if (list->fl_files != &list->fl_prefile) + if (list->fl_fds != &list->fl_prefd) { - fs_heap_free(list->fl_files); + fs_heap_free(list->fl_fds); } } /**************************************************************************** - * 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 list structure. + * list - Pointer to the file descriptor list structure. * * Returned Value: * file count of file list. * ****************************************************************************/ -int files_countlist(FAR struct filelist *list) +int fdlist_count(FAR struct fdlist *list) { return list->fl_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; } /**************************************************************************** - * 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, otherwise, 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) { - return files_fget_by_index(list, fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK, - fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK, NULL); + if (list == NULL) + { + return -EINVAL; + } + +#ifdef CONFIG_FDCHECK + fd = fdcheck_restore(fd); +#endif + + if (fd < 0 || fd >= fdlist_count(list)) + { + return -EBADF; + } + + fdlist_get_by_index(list, + fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK, + fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK, + filep, fdp); + if (*filep == NULL) + { + return -EBADF; + } + + return 0; } /**************************************************************************** - * Name: file_allocate_from_tcb + * Name: fdlist_dupfile * * Description: - * Allocate a struct files instance and associate it with an inode - * instance. + * 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. + * Returns the file descriptor == index into the files array on success; + * a negated errno value is returned on any failure. * ****************************************************************************/ -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) +int fdlist_dupfile(FAR struct fdlist *list, int oflags, int minfd, + FAR struct file *filep) { - int i = minfd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; - int j = minfd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; - FAR struct filelist *list; - FAR struct file *filep; + FAR struct fd *fdp; irqstate_t flags; int ret; + int i; + int j; - /* Get the file descriptor list. It should not be NULL in this context. */ + DEBUGASSERT(filep); - list = nxsched_get_files_from_tcb(tcb); +#ifdef CONFIG_FDCHECK + minfd = fdcheck_restore(minfd); +#endif - /* Find free file */ + i = minfd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; + j = minfd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; + + /* Find free file descriptor */ flags = spin_lock_irqsave_notrace(&list->fl_lock); @@ -538,7 +580,7 @@ int file_allocate_from_tcb(FAR struct tcb_s *tcb, FAR struct inode *inode, { spin_unlock_irqrestore_notrace(&list->fl_lock, flags); - ret = files_extend(list, i + 1); + ret = fdlist_extend(list, i + 1); if (ret < 0) { return ret; @@ -549,21 +591,18 @@ int file_allocate_from_tcb(FAR struct tcb_s *tcb, FAR struct inode *inode, do { - filep = &list->fl_files[i][j]; - if (filep->f_inode == NULL) + fdp = &list->fl_fds[i][j]; + if (fdp->f_file == NULL) { - filep->f_oflags = oflags; - filep->f_pos = pos; - filep->f_inode = inode; - filep->f_priv = priv; - atomic_set(&filep->f_refs, 1); -#ifdef CONFIG_FDSAN - filep->f_tag_fdsan = 0; -#endif -#ifdef CONFIG_FDCHECK - filep->f_tag_fdcheck = 0; -#endif - + atomic_fetch_add(&filep->f_refs, 1); + fdp->f_file = filep; + fdp->f_cloexec = !!(oflags & O_CLOEXEC); + #ifdef CONFIG_FDSAN + fdp->f_tag_fdsan = 0; + #endif + #ifdef CONFIG_FDCHECK + fdp->f_tag_fdcheck = 0; + #endif goto found; } } @@ -573,12 +612,7 @@ int file_allocate_from_tcb(FAR struct tcb_s *tcb, FAR struct inode *inode, found: spin_unlock_irqrestore_notrace(&list->fl_lock, flags); - if (addref) - { - inode_addref(inode); - } - - FS_ADD_BACKTRACE(filep); + FS_ADD_BACKTRACE(fdp); #ifdef CONFIG_FDCHECK return fdcheck_protect(i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j); @@ -588,36 +622,134 @@ found: } /**************************************************************************** - * Name: file_allocate + * Name: fdlist_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 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. + * 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 fdlist_allocate(FAR struct fdlist *list, int oflags, + int minfd, FAR struct file **filep) { - return file_allocate_from_tcb(this_task(), inode, oflags, - pos, priv, minfd, addref); + int fd; + + *filep = fs_heap_zalloc(sizeof(struct file)); + if (*filep == NULL) + { + return -ENOMEM; + } + + file_ref(*filep); + fd = fdlist_dupfile(list, oflags, minfd, *filep); + if (fd < 0) + { + file_put(*filep); + } + + return fd; } /**************************************************************************** - * Name: files_duplist + * Name: file_allocate * * Description: - * Duplicate parent task's file descriptors. + * 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. * ****************************************************************************/ -int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist, - FAR const posix_spawn_file_actions_t *actions, - bool cloexec) +int file_allocate(int oflags, int minfd, FAR struct file **filep) +{ + return fdlist_allocate(nxsched_get_fdlist_from_tcb(this_task()), + oflags, minfd, 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) +{ + FAR struct file *filep; + int fd; + + fd = file_allocate(oflags, minfd, &filep); + if (fd < 0) + { + return fd; + } + + inode_addref(inode); + filep->f_inode = inode; + filep->f_pos = pos; + filep->f_oflags = oflags & ~O_CLOEXEC; + filep->f_priv = priv; +#if CONFIG_FS_LOCK_BUCKET_SIZE > 0 + filep->f_locked = false; +#endif + + file_put(filep); + + return fd; +} + +/**************************************************************************** + * Name: fdlist_copy + * + * Description: + * Copy parent task's file descriptors to child task. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +int fdlist_copy(FAR struct fdlist *plist, FAR struct fdlist *clist, + FAR const posix_spawn_file_actions_t *actions, + bool cloexec) { bool fcloexec; int ret; @@ -629,9 +761,8 @@ int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist, { for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - FAR struct file *filep2; FAR struct file *filep; - bool new = false; + FAR struct fd *fdp; fd = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j; #ifdef CONFIG_FDCLONE_STDIO @@ -649,13 +780,13 @@ int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist, } #endif - filep = files_fget_by_index(plist, i, j, NULL); + fdlist_get_by_index(plist, i, j, &filep, &fdp); if (filep == NULL) { continue; } - fcloexec = (cloexec && (filep->f_oflags & O_CLOEXEC)); + fcloexec = cloexec && fdp->f_cloexec; /* Skip file dup if file action is unnecessary to duplicate */ @@ -676,28 +807,17 @@ int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist, continue; } - ret = files_extend(clist, i + 1); + ret = fdlist_extend(clist, i + 1); if (ret < 0) { file_put(filep); return ret; } - /* Yes... duplicate it for the child, include O_CLOEXEC flag. */ + /* Assign filep to the child's descriptor list. Omit the flags */ - filep2 = files_fget_by_index(clist, i, j, &new); - ret = file_dup2(filep, filep2); - file_put(filep2); + fdlist_install(clist, fd, filep, 0); file_put(filep); - if (ret < 0) - { - if (new) - { - file_put(filep2); - } - - return ret; - } } } @@ -705,15 +825,16 @@ int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist, } /**************************************************************************** - * Name: file_get + * Name: file_get2 * * Description: * Given a file descriptor, return the corresponding instance of struct - * file. + * 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 @@ -721,49 +842,9 @@ int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist, * ****************************************************************************/ -int file_get(int fd, FAR struct file **filep) +int file_get2(int fd, FAR struct file **filep, FAR struct fd **fdp) { - FAR struct filelist *list; - -#ifdef CONFIG_FDCHECK - fd = fdcheck_restore(fd); -#endif - - *filep = 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 (fd < 0 || fd >= files_countlist(list)) - { - return -EBADF; - } - - /* The descriptor is in a valid range to file descriptor... Get the - * thread-specific file list. - */ - - *filep = files_fget(list, fd); - - /* if *filep is NULL, fd was closed */ - - if (*filep == NULL) - { - return -EBADF; - } - - return OK; + return fdlist_get2(nxsched_get_fdlist(), fd, filep, fdp); } /**************************************************************************** @@ -804,7 +885,10 @@ int file_put(FAR struct file *filep) { int ret = 0; - DEBUGASSERT(filep); + if (filep == NULL) + { + return ret; + } /* If refs is zero, the close() had called, closing it now. */ @@ -815,20 +899,22 @@ int file_put(FAR struct file *filep) { ferr("ERROR: fs putfilep file_close() failed: %d\n", ret); } + + fs_heap_free(filep); } return ret; } /**************************************************************************** - * 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. @@ -839,20 +925,41 @@ int file_put(FAR struct file *filep) * ****************************************************************************/ -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) { - return nx_dup3_from_tcb(tcb, fd1, fd2, 0); + /* If fd1 is a valid file descriptor, and fd1 == fd2, then dup2() does + * nothing, and returns fd2. + */ + + if (fd1 == fd2) + { + FAR struct file *filep; + int ret; + + ret = file_get(fd1, &filep); + if (ret < 0) + { + return ret; + } + + /* Release the reference */ + + file_put(filep); + return fd2; + } + + return fdlist_dup3(list, fd1, fd2, 0); } /**************************************************************************** - * Name: nx_close_from_tcb + * Name: fdlist_close * * 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) @@ -867,42 +974,26 @@ int nx_dup2_from_tcb(FAR struct tcb_s *tcb, int fd1, int fd2) * ****************************************************************************/ -int nx_close_from_tcb(FAR struct tcb_s *tcb, int fd) +int fdlist_close(FAR struct fdlist *list, int fd) { - FAR struct file *filep; - FAR struct filelist *list; + FAR struct file *filep; + FAR struct fd *fdp; + int ret; -#ifdef CONFIG_FDCHECK - fd = fdcheck_restore(fd); -#endif - - list = nxsched_get_files_from_tcb(tcb); + ret = fdlist_get2(list, fd, &filep, &fdp); + if (ret < 0) + { + return ret; + } /* Perform the protected close operation */ - if (fd < 0 || fd >= files_countlist(list)) - { - return -EBADF; - } + fdlist_uninstall(list, fdp); - filep = files_fget(list, fd); - - /* If the file was properly opened, there should be an inode assigned */ - - if (filep == NULL) - { - return -EBADF; - } - - - /* files_fget will increase the reference count, there call file_put - * reduce reference count. + /* fdlist_get2 will increase the reference count, there call + * file_put reduce reference count. */ - file_put(filep); - - /* Undo the last reference count from file_allocate_from_tcb */ - return file_put(filep); } diff --git a/fs/inode/inode.h b/fs/inode/inode.h index 59dfc1d2d05..178368b7304 100644 --- a/fs/inode/inode.h +++ b/fs/inode/inode.h @@ -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 /**************************************************************************** diff --git a/fs/mqueue/mq_open.c b/fs/mqueue/mq_open.c index 402ed9a5d14..7b270bba1dc 100644 --- a/fs/mqueue/mq_open.c +++ b/fs/mqueue/mq_open.c @@ -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; } /**************************************************************************** diff --git a/fs/notify/inotify.c b/fs/notify/inotify.c index ced0d5467e2..92d0cdd21fb 100644 --- a/fs/notify/inotify.c +++ b/fs/notify/inotify.c @@ -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"); diff --git a/fs/procfs/fs_procfsproc.c b/fs/procfs/fs_procfsproc.c index db29825c9c3..94f30357709 100644 --- a/fs/procfs/fs_procfsproc.c +++ b/fs/procfs/fs_procfsproc.c @@ -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'; diff --git a/fs/shm/shm_open.c b/fs/shm/shm_open.c index 1230585ee6b..cad2b976835 100644 --- a/fs/shm/shm_open.c +++ b/fs/shm/shm_open.c @@ -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; } diff --git a/fs/socket/socket.c b/fs/socket/socket.c index 125bed11091..95252b3ddc3 100644 --- a/fs/socket/socket.c +++ b/fs/socket/socket.c @@ -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); } /**************************************************************************** diff --git a/fs/vfs/fs_close.c b/fs/vfs/fs_close.c index c65c92b00cb..980df65585c 100644 --- a/fs/vfs/fs_close.c +++ b/fs/vfs/fs_close.c @@ -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); } /**************************************************************************** diff --git a/fs/vfs/fs_dup.c b/fs/vfs/fs_dup.c index f00abd412c9..092055ec059 100644 --- a/fs/vfs/fs_dup.c +++ b/fs/vfs/fs_dup.c @@ -33,7 +33,9 @@ #include #include + #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); } /**************************************************************************** diff --git a/fs/vfs/fs_dup2.c b/fs/vfs/fs_dup2.c index d9e1d9e13a2..62d4e267d62 100644 --- a/fs/vfs/fs_dup2.c +++ b/fs/vfs/fs_dup2.c @@ -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); } /**************************************************************************** diff --git a/fs/vfs/fs_dup3.c b/fs/vfs/fs_dup3.c index 947b1542129..ec44b0ab551 100644 --- a/fs/vfs/fs_dup3.c +++ b/fs/vfs/fs_dup3.c @@ -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); diff --git a/fs/vfs/fs_epoll.c b/fs/vfs/fs_epoll.c index 5efbece61c0..91181ea17c5 100644 --- a/fs/vfs/fs_epoll.c +++ b/fs/vfs/fs_epoll.c @@ -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); diff --git a/fs/vfs/fs_eventfd.c b/fs/vfs/fs_eventfd.c index f5f614a7e5f..0f63df25dce 100644 --- a/fs/vfs/fs_eventfd.c +++ b/fs/vfs/fs_eventfd.c @@ -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; diff --git a/fs/vfs/fs_fcntl.c b/fs/vfs/fs_fcntl.c index b923f5fd8f4..406648d2bab 100644 --- a/fs/vfs/fs_fcntl.c +++ b/fs/vfs/fs_fcntl.c @@ -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 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 , 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 * , 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 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 , 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; } diff --git a/fs/vfs/fs_ioctl.c b/fs/vfs/fs_ioctl.c index 7df9733799c..2b199609d8d 100644 --- a/fs/vfs/fs_ioctl.c +++ b/fs/vfs/fs_ioctl.c @@ -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; } diff --git a/fs/vfs/fs_open.c b/fs/vfs/fs_open.c index 83f1eb279b4..1d528899990 100644 --- a/fs/vfs/fs_open.c +++ b/fs/vfs/fs_open.c @@ -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() */ diff --git a/fs/vfs/fs_signalfd.c b/fs/vfs/fs_signalfd.c index dedc3c3cc02..116c653e8ac 100644 --- a/fs/vfs/fs_signalfd.c +++ b/fs/vfs/fs_signalfd.c @@ -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; diff --git a/fs/vfs/fs_timerfd.c b/fs/vfs/fs_timerfd.c index 5760da3eb5a..5720b4f79fd 100644 --- a/fs/vfs/fs_timerfd.c +++ b/fs/vfs/fs_timerfd.c @@ -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; diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index 016fbc06186..992c4c69ff8 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -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 diff --git a/include/nuttx/fs/ioctl.h b/include/nuttx/fs/ioctl.h index ed2d62bb679..469badb6290 100644 --- a/include/nuttx/fs/ioctl.h +++ b/include/nuttx/fs/ioctl.h @@ -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) diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index a84936cd9d0..0ae6d2c7260 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -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 diff --git a/sched/group/group_create.c b/sched/group/group_create.c index ceaf11bf7f6..49a797d1f3c 100644 --- a/sched/group/group_create.c +++ b/sched/group/group_create.c @@ -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 */ diff --git a/sched/group/group_leave.c b/sched/group/group_leave.c index a8e6dc0d057..0ea281250de 100644 --- a/sched/group/group_leave.c +++ b/sched/group/group_leave.c @@ -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 */ diff --git a/sched/group/group_setuptaskfiles.c b/sched/group/group_setuptaskfiles.c index 4189445e264..4af75193e05 100644 --- a/sched/group/group_setuptaskfiles.c +++ b/sched/group/group_setuptaskfiles.c @@ -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) diff --git a/sched/misc/assert.c b/sched/misc/assert.c index 969fbf68fe2..7555d4c0523 100644 --- a/sched/misc/assert.c +++ b/sched/misc/assert.c @@ -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 } diff --git a/sched/sched/sched_getfiles.c b/sched/sched/sched_getfiles.c index 53dabbf4b78..e2125a7ac7b 100644 --- a/sched/sched/sched_getfiles.c +++ b/sched/sched/sched_getfiles.c @@ -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()); } diff --git a/sched/task/task_spawnparms.c b/sched/task/task_spawnparms.c index 3066b32a7db..7022b5d5767 100644 --- a/sched/task/task_spawnparms.c +++ b/sched/task/task_spawnparms.c @@ -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;