1 /****************************************************************************
2 * fs/vfs/fs_read.c
3 *
4 * Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved.
5 * Based on NuttX originally from nuttx source (nuttx/fs/ and nuttx/drivers/)
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * 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,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ****************************************************************************/
20
21 /****************************************************************************
22 * Included Files
23 ****************************************************************************/
24
25 #include "vfs_config.h"
26 #include "sys/types.h"
27 #include "sys/socket.h"
28 #include "console.h"
29 #include "unistd.h"
30 #include "fcntl.h"
31 #include "sched.h"
32 #include "assert.h"
33 #include "errno.h"
34 #include "user_copy.h"
35 #include "vnode.h"
36
37 /****************************************************************************
38 * Public Functions
39 ****************************************************************************/
40
41 /****************************************************************************
42 * Name: file_read
43 *
44 * Description:
45 * file_read() is an interanl OS interface. It is functionally similar to
46 * the standard read() interface except:
47 *
48 * - It does not modify the errno variable,
49 * - It is not a cancellation point,
50 * - It does not handle socket descriptors, and
51 * - It accepts a file structure instance instead of file descriptor.
52 *
53 * Input Parameters:
54 * filep - File structure instance
55 * buf - User-provided to save the data
56 * nbytes - The maximum size of the user-provided buffer
57 *
58 * Returned Value:
59 * The positive non-zero number of bytes read on success, 0 on if an
60 * end-of-file condition, or a negated errno value on any failure.
61 *
62 ****************************************************************************/
63
file_read(struct file * filep,void * buf,size_t nbytes)64 ssize_t file_read(struct file *filep, void *buf, size_t nbytes)
65 {
66 int ret = -EBADF;
67
68 if (buf == NULL)
69 {
70 ret = -EFAULT;
71 }
72
73 /* Was this file opened for read access? */
74
75 else if (((unsigned int)(filep->f_oflags) & O_ACCMODE) == O_WRONLY)
76 {
77 /* No.. File is not read-able */
78
79 ret = -EACCES;
80 }
81
82 /* Is a driver or mountpoint registered? If so, does it support the read
83 * method?
84 */
85
86 else if (filep->ops && filep->ops->read)
87 {
88 /* Yes.. then let it perform the read. NOTE that for the case of the
89 * mountpoint, we depend on the read methods being identical in
90 * signature and position in the operations vtable.
91 */
92
93 ret = (int)filep->ops->read(filep, (char *)buf, (size_t)nbytes);
94 }
95
96 /* If an error occurred, set errno and return -1 (ERROR) */
97
98 if (ret < 0)
99 {
100 set_errno(-ret);
101 return VFS_ERROR;
102 }
103
104 /* Otherwise, return the number of bytes read */
105
106 return ret;
107 }
108
109 /****************************************************************************
110 * Name: read
111 *
112 * Description:
113 * The standard, POSIX read interface.
114 *
115 * Input Parameters:
116 * fd - File descriptor to read from
117 * buf - User-provided to save the data
118 * nbytes - The maximum size of the user-provided buffer
119 *
120 * Returned Value:
121 * The positive non-zero number of bytes read on success, 0 on if an
122 * end-of-file condition, or -1 on failure with errno set appropriately.
123 *
124 ****************************************************************************/
125
read(int fd,void * buf,size_t nbytes)126 ssize_t read(int fd, void *buf, size_t nbytes)
127 {
128 if (buf == NULL || nbytes < 0)
129 {
130 set_errno(EINVAL);
131 return VFS_ERROR;
132 }
133 /* Did we get a valid file descriptor? */
134
135 #if CONFIG_NFILE_DESCRIPTORS > 0
136 struct file *filep = NULL;
137
138 if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
139 #endif
140 {
141 /* No.. If networking is enabled, read() is the same as recv() with
142 * the flags parameter set to zero.
143 */
144
145 #if defined(LOSCFG_NET_LWIP_SACK)
146 void *bufbak = buf;
147 ssize_t ret;
148 if (LOS_IsUserAddress((VADDR_T)(uintptr_t)buf))
149 {
150 if (buf != NULL && nbytes > 0)
151 {
152 buf = malloc(nbytes);
153 if (buf == NULL)
154 {
155 set_errno(ENOMEM);
156 return VFS_ERROR;
157 }
158 }
159 }
160 ret = recv(fd, buf, nbytes, 0);
161 if (ret > 0 && buf != bufbak)
162 {
163 if (LOS_ArchCopyToUser(bufbak, buf, ret) != 0)
164 {
165 /* data lost here */
166 set_errno(EFAULT);
167 ret = VFS_ERROR;
168 }
169 }
170 if (buf != bufbak)
171 {
172 free(buf);
173 }
174 return ret;
175 #else
176 /* No networking... it is a bad descriptor in any event */
177
178 set_errno(EBADF);
179 return VFS_ERROR;
180 #endif
181 }
182
183 #if CONFIG_NFILE_DESCRIPTORS > 0
184 else
185 {
186 if (fd <= STDERR_FILENO && fd >= STDIN_FILENO) /* fd : [0,2] */
187 {
188 fd = ConsoleUpdateFd();
189 if (fd < 0)
190 {
191 set_errno(EBADF);
192 return VFS_ERROR;
193 }
194 }
195
196 /* The descriptor is in a valid range to file descriptor... do the
197 * read. First, get the file structure.
198 */
199
200 int ret = fs_getfilep(fd, &filep);
201 if (ret < 0)
202 {
203 /* The errno value has already been set */
204 return VFS_ERROR;
205 }
206
207 if (filep->f_oflags & O_DIRECTORY)
208 {
209 set_errno(EBADF);
210 return VFS_ERROR;
211 }
212
213 /* Then let file_read do all of the work */
214
215 return file_read(filep, buf, nbytes);
216 }
217 #endif
218 }
219