• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * fs/vfs/fs_ioctl.c
3  *
4  * Licensed to the Apache Software Foundation (ASF) under one or more
5  * contributor license agreements.  See the NOTICE file distributed with
6  * this work for additional information regarding copyright ownership.  The
7  * ASF licenses this file to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance with the
9  * License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
16  * License for the specific language governing permissions and limitations
17  * under the License.
18  *
19  ****************************************************************************/
20 
21 /****************************************************************************
22  * Included Files
23  ****************************************************************************/
24 
25 #include "vfs_config.h"
26 #include "sched.h"
27 #include "assert.h"
28 #include "errno.h"
29 #include "unistd.h"
30 #include "console.h"
31 
32 #if defined(LOSCFG_NET_LWIP_SACK)
33 #include "lwip/sockets.h"
34 #endif
35 
36 #include "vnode.h"
37 
38 /****************************************************************************
39  * Public Functions
40  ****************************************************************************/
41 
42 /****************************************************************************
43  * Name: ioctl/fs_ioctl
44  *
45  * Description:
46  *   Perform device specific operations.
47  *
48  * Input Parameters:
49  *   fd       File/socket descriptor of device
50  *   req      The ioctl command
51  *   arg      The argument of the ioctl cmd
52  *
53  * Returned Value:
54  *   >=0 on success (positive non-zero values are cmd-specific)
55  *   -1 on failure with errno set properly:
56  *
57  *   EBADF
58  *     'fd' is not a valid descriptor.
59  *   EFAULT
60  *     'arg' references an inaccessible memory area.
61  *   EINVAL
62  *     'cmd' or 'arg' is not valid.
63  *   ENOTTY
64  *     'fd' is not associated with a character special device.
65  *   ENOTTY
66  *      The specified request does not apply to the kind of object that the
67  *      descriptor 'fd' references.
68  *
69  ****************************************************************************/
70 
71 #ifdef CONFIG_LIBC_IOCTL_VARIADIC
fs_ioctl(int fd,int req,...)72 int fs_ioctl(int fd, int req, ...)
73 #else
74 int ioctl(int fd, int req, ...)
75 #endif
76 {
77   int err;
78   UINTPTR arg = 0;
79   va_list ap;
80 #if CONFIG_NFILE_DESCRIPTORS > 0
81   struct file     *filep;
82   int                  ret = OK;
83 #endif
84 
85   va_start(ap, req);
86   arg = va_arg(ap, UINTPTR);
87   va_end(ap);
88 #if CONFIG_NFILE_DESCRIPTORS > 0
89 
90   /* Did we get a valid file descriptor? */
91 
92   if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
93 #endif
94     {
95       /* Perform the socket ioctl */
96 
97 #if defined(LOSCFG_NET_LWIP_SACK)
98       if ((unsigned int)fd < (unsigned int)(CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS))
99         {
100           return socks_ioctl(fd, (long)req, (void *)arg);
101         }
102       else
103 #endif
104         {
105           err = EBADF;
106           ret = VFS_ERROR;
107           goto errout;
108         }
109     }
110 
111 #if CONFIG_NFILE_DESCRIPTORS > 0
112 
113   if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) /* fd : [0,2] */
114     {
115       fd = ConsoleUpdateFd();
116       if (fd < 0)
117         {
118           err = EBADF;
119           ret = VFS_ERROR;
120           goto errout;
121         }
122     }
123 
124   /* Get the file structure corresponding to the file descriptor. */
125 
126   ret = fs_getfilep(fd, &filep);
127   if (ret < 0)
128     {
129       /* The errno value has already been set */
130       return VFS_ERROR;
131     }
132 
133   /* Is a driver registered? Does it support the ioctl method? */
134 
135   if (filep->ops && filep->ops->ioctl)
136     {
137       /* Yes, then let it perform the ioctl */
138 
139       ret = (int) filep->ops->ioctl(filep, req, arg);
140       if (ret < 0)
141         {
142           err = -ret;
143           goto errout;
144         }
145     }
146   else
147     {
148       err = ENOSYS;
149       ret = VFS_ERROR;
150       goto errout;
151     }
152 
153   return ret;
154 #endif
155 
156 errout:
157   set_errno(err);
158   return VFS_ERROR;
159 }
160