1 /****************************************************************************
2 * fs/vfs/fs_ioctl.c
3 *
4 * Copyright (C) 2007-2010, 2012-2014, 2016-2017 Gregory Nutt. All rights
5 * reserved.
6 * Author: Gregory Nutt <gnutt@nuttx.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * 3. Neither the name NuttX nor the names of its contributors may be
19 * used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 ****************************************************************************/
36
37 /****************************************************************************
38 * Included Files
39 ****************************************************************************/
40
41 #include "vfs_config.h"
42 #include "sched.h"
43 #include "assert.h"
44 #include "errno.h"
45 #include "unistd.h"
46 #include "console.h"
47
48 #if defined(LOSCFG_NET_LWIP_SACK)
49 #include "lwip/sockets.h"
50 #endif
51
52 #include "vnode.h"
53
54 /****************************************************************************
55 * Public Functions
56 ****************************************************************************/
57
58 /****************************************************************************
59 * Name: ioctl/fs_ioctl
60 *
61 * Description:
62 * Perform device specific operations.
63 *
64 * Input Parameters:
65 * fd File/socket descriptor of device
66 * req The ioctl command
67 * arg The argument of the ioctl cmd
68 *
69 * Returned Value:
70 * >=0 on success (positive non-zero values are cmd-specific)
71 * -1 on failure with errno set properly:
72 *
73 * EBADF
74 * 'fd' is not a valid descriptor.
75 * EFAULT
76 * 'arg' references an inaccessible memory area.
77 * EINVAL
78 * 'cmd' or 'arg' is not valid.
79 * ENOTTY
80 * 'fd' is not associated with a character special device.
81 * ENOTTY
82 * The specified request does not apply to the kind of object that the
83 * descriptor 'fd' references.
84 *
85 ****************************************************************************/
86
87 #ifdef CONFIG_LIBC_IOCTL_VARIADIC
fs_ioctl(int fd,int req,...)88 int fs_ioctl(int fd, int req, ...)
89 #else
90 int ioctl(int fd, int req, ...)
91 #endif
92 {
93 int err;
94 UINTPTR arg = 0;
95 va_list ap;
96 #if CONFIG_NFILE_DESCRIPTORS > 0
97 struct file *filep;
98 int ret = OK;
99 #endif
100
101 va_start(ap, req);
102 arg = va_arg(ap, UINTPTR);
103 va_end(ap);
104 #if CONFIG_NFILE_DESCRIPTORS > 0
105
106 /* Did we get a valid file descriptor? */
107
108 if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
109 #endif
110 {
111 /* Perform the socket ioctl */
112
113 #if defined(LOSCFG_NET_LWIP_SACK)
114 if ((unsigned int)fd < (unsigned int)(CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
115 {
116 return socks_ioctl(fd, (long)req, (void *)arg);
117 }
118 else
119 #endif
120 {
121 err = EBADF;
122 ret = VFS_ERROR;
123 goto errout;
124 }
125 }
126
127 #if CONFIG_NFILE_DESCRIPTORS > 0
128
129 if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) /* fd : [0,2] */
130 {
131 fd = ConsoleUpdateFd();
132 if (fd < 0)
133 {
134 err = EBADF;
135 ret = VFS_ERROR;
136 goto errout;
137 }
138 }
139
140 /* Get the file structure corresponding to the file descriptor. */
141
142 ret = fs_getfilep(fd, &filep);
143 if (ret < 0)
144 {
145 /* The errno value has already been set */
146 return VFS_ERROR;
147 }
148
149 /* Is a driver registered? Does it support the ioctl method? */
150
151 if (filep->ops && filep->ops->ioctl)
152 {
153 /* Yes, then let it perform the ioctl */
154
155 ret = (int) filep->ops->ioctl(filep, req, arg);
156 if (ret < 0)
157 {
158 err = -ret;
159 goto errout;
160 }
161 }
162 else
163 {
164 err = ENOSYS;
165 ret = VFS_ERROR;
166 goto errout;
167 }
168
169 return ret;
170 #endif
171
172 errout:
173 set_errno(err);
174 return VFS_ERROR;
175 }
176