int file_dup(FAR struct file *filep, int minfd) { int fd2; /* Verify that fd is a valid, open file descriptor */ if (!DUP_ISOPEN(filep)) { return -EBADF; } /* Increment the reference count on the contained inode */ inode_addref(filep->f_inode); /* Then allocate a new file descriptor for the inode */ fd2 = files_allocate(filep->f_inode, filep->f_oflags, filep->f_pos, minfd); if (fd2 < 0) { inode_release(filep->f_inode); return -EMFILE; } return fd2; }
int files_dup(FAR struct file *filep1, FAR struct file *filep2) { FAR struct filelist *list; FAR struct inode *inode; int err; int ret; if (!filep1 || !filep1->f_inode || !filep2) { err = EBADF; goto errout; } list = sched_getfiles(); DEBUGASSERT(list); _files_semtake(list); /* If there is already an inode contained in the new file structure, * close the file and release the inode. */ ret = _files_close(filep2); if (ret < 0) { /* An error occurred while closing the driver */ goto errout_with_ret; } /* Increment the reference count on the contained inode */ inode = filep1->f_inode; inode_addref(inode); /* Then clone the file structure */ filep2->f_oflags = filep1->f_oflags; filep2->f_pos = filep1->f_pos; filep2->f_inode = inode; /* Call the open method on the file, driver, mountpoint so that it * can maintain the correct open counts. */ if (inode->u.i_ops && inode->u.i_ops->open) { #ifndef CONFIG_DISABLE_MOUNTPOINT if (INODE_IS_MOUNTPT(inode)) { /* Dup the open file on the in the new file structure */ ret = inode->u.i_mops->dup(filep1, filep2); } else #endif { /* (Re-)open the pseudo file or device driver */ ret = inode->u.i_ops->open(filep2); } /* Handle open failures */ if (ret < 0) { goto errout_with_inode; } } _files_semgive(list); return OK; /* Handler various error conditions */ errout_with_inode: inode_release(filep2->f_inode); filep2->f_oflags = 0; filep2->f_pos = 0; filep2->f_inode = NULL; errout_with_ret: err = -ret; _files_semgive(list); errout: set_errno(err); return ERROR; }