* @brief System call to duplicate a file descriptor to a specific descriptor number * * @param[in] oldfd The file descriptor to duplicate * @param[in] newfd The desired file descriptor number * * @return rt_err_t The new file descriptor number if successful (>=0), * -RT_ENOSYS if filesystem lock failed, * -1 if operation failed (invalid descriptors or allocation failed) */
| 843 | * -1 if operation failed (invalid descriptors or allocation failed) |
| 844 | */ |
| 845 | rt_err_t sys_dup2(int oldfd, int newfd) |
| 846 | { |
| 847 | struct dfs_fdtable *fdt = NULL; |
| 848 | int ret = 0; |
| 849 | int retfd = -1; |
| 850 | |
| 851 | if (dfs_file_lock() != RT_EOK) |
| 852 | { |
| 853 | return -RT_ENOSYS; |
| 854 | } |
| 855 | |
| 856 | /* check old fd */ |
| 857 | fdt = dfs_fdtable_get(); |
| 858 | if ((oldfd < 0) || (oldfd >= fdt->maxfd)) |
| 859 | { |
| 860 | goto exit; |
| 861 | } |
| 862 | if (!fdt->fds[oldfd]) |
| 863 | { |
| 864 | goto exit; |
| 865 | } |
| 866 | if (newfd < 0) |
| 867 | { |
| 868 | goto exit; |
| 869 | } |
| 870 | if (newfd >= fdt->maxfd) |
| 871 | { |
| 872 | newfd = _fdt_slot_expand(fdt, newfd); |
| 873 | if (newfd < 0) |
| 874 | { |
| 875 | goto exit; |
| 876 | } |
| 877 | } |
| 878 | if (fdt->fds[newfd] == fdt->fds[oldfd]) |
| 879 | { |
| 880 | /* ok, return newfd */ |
| 881 | retfd = newfd; |
| 882 | goto exit; |
| 883 | } |
| 884 | |
| 885 | if (fdt->fds[newfd]) |
| 886 | { |
| 887 | ret = dfs_file_close(fdt->fds[newfd]); |
| 888 | if (ret < 0) |
| 889 | { |
| 890 | goto exit; |
| 891 | } |
| 892 | fd_release(newfd); |
| 893 | } |
| 894 | |
| 895 | fdt->fds[newfd] = fdt->fds[oldfd]; |
| 896 | /* inc ref_count */ |
| 897 | rt_atomic_add(&(fdt->fds[newfd]->ref_count), 1); |
| 898 | retfd = newfd; |
| 899 | exit: |
| 900 | dfs_file_unlock(); |
| 901 | return retfd; |
| 902 | } |
nothing calls this directly
no test coverage detected