1 /****************************************************************************
2 * fs/vfs/fs_dupfd.c
3 *
4 * Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved.
5 * Based on NuttX originally written by Gregory Nutt
6 *
7 * Copyright (C) 2007-2009, 2011-2014, 2017 Gregory Nutt. All rights
8 * reserved.
9 * Author: Gregory Nutt <gnutt@nuttx.org>
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 * 3. Neither the name NuttX nor the names of its contributors may be
22 * used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
32 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
33 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 *
38 ****************************************************************************/
39
40 /****************************************************************************
41 * Included Files
42 ****************************************************************************/
43
44 #include "vfs_config.h"
45
46 #include "assert.h"
47 #include "errno.h"
48 #include "sched.h"
49
50 #include "fs/file.h"
51
52 #include "vnode.h"
53 #include "stdlib.h"
54 #include "string.h"
55 #if CONFIG_NFILE_DESCRIPTORS > 0
56
57 /****************************************************************************
58 * Pre-processor Definitions
59 ****************************************************************************/
60
61 /****************************************************************************
62 * Public Functions
63 ****************************************************************************/
64
65 /****************************************************************************
66 * Name: file_dup
67 *
68 * Description:
69 * Equivalent to the non-standard fs_dupfd() function except that it
70 * accepts a struct file instance instead of a file descriptor and does
71 * not set the errno variable.
72 *
73 * Returned Value:
74 * Zero (OK) is returned on success; a negated errno value is returned on
75 * any failure.
76 *
77 ****************************************************************************/
78
file_dup(struct file * filep,int minfd)79 int file_dup(struct file *filep, int minfd)
80 {
81 struct file *filep2 = NULL;
82
83 /* Verify that fd is a valid, open file descriptor */
84
85 if ((filep->f_vnode == NULL) || (filep->f_path == NULL))
86 {
87 set_errno(EBADF);
88 return VFS_ERROR;
89 }
90
91 /* Then allocate a new file descriptor for the vnode */
92
93 filep2 = files_allocate(filep->f_vnode, filep->f_oflags, filep->f_pos, filep->f_priv, minfd);
94 if (filep2 == NULL)
95 {
96 set_errno(EMFILE);
97 return VFS_ERROR;
98 }
99 filep2->f_refcount = filep->f_refcount;
100
101 return filep2->fd;
102 }
103
104 /****************************************************************************
105 * Name: fs_dupfd OR dup
106 *
107 * Description:
108 * Clone a file descriptor 'fd' to an arbitray descriptor number (any value
109 * greater than or equal to 'minfd'). If socket descriptors are
110 * implemented, then this is called by dup() for the case of file
111 * descriptors. If socket descriptors are not implemented, then this
112 * function IS dup().
113 *
114 * Returned Value:
115 * fs_dupfd is sometimes an OS internal function and sometimes is a direct
116 * substitute for dup(). So it must return an errno value as though it
117 * were dup().
118 *
119 ****************************************************************************/
120
fs_dupfd(int fd,int minfd)121 int fs_dupfd(int fd, int minfd)
122 {
123 struct file *filep;
124
125 /* Get the file structure corresponding to the file descriptor. */
126
127 int ret = fs_getfilep(fd, &filep);
128 if (ret < 0)
129 {
130 /* The errno value has already been set */
131 return VFS_ERROR;
132 }
133
134 /* Let file_dup() do the real work */
135
136 return file_dup(filep, minfd);
137 }
138
139 #endif /* CONFIG_NFILE_DESCRIPTORS > 0 */
140