• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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