1 /****************************************************************************
2 * fs/vfs/fs_write.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 "sys/types.h"
27 #include "unistd.h"
28 #include "fcntl.h"
29 #include "sched.h"
30 #include "assert.h"
31 #include "errno.h"
32 #include "sys/socket.h"
33 #include "console.h"
34 #include "user_copy.h"
35 #include "vnode.h"
36
37 /****************************************************************************
38 * Public Functions
39 ****************************************************************************/
40
41 /****************************************************************************
42 * Name: file_write
43 *
44 * Description:
45 * Equivalent to the standard write() function except that is accepts a
46 * struct file instance instead of a file descriptor. It is functionally
47 * equivalent to write() except that in addition to the differences in
48 * input paramters:
49 *
50 * - It does not modify the errno variable,
51 * - It is not a cancellation point, and
52 * - It does not handle socket descriptors.
53 *
54 * Input Parameters:
55 * filep - Instance of struct file to use with the write
56 * buf - Data to write
57 * nbytes - Length of data to write
58 *
59 * Returned Value:
60 * On success, the number of bytes written are returned (zero indicates
61 * nothing was written). On any failure, a negated errno value is returned
62 * (see comments withwrite() for a description of the appropriate errno
63 * values).
64 *
65 ****************************************************************************/
file_write(struct file * filep,const void * buf,size_t nbytes)66 ssize_t file_write(struct file *filep, const void *buf, size_t nbytes)
67 {
68 int ret;
69 int err;
70
71 if (buf == NULL)
72 {
73 err = EFAULT;
74 goto errout;
75 }
76
77 /* Was this file opened for write access? */
78
79 if ((((unsigned int)(filep->f_oflags)) & O_ACCMODE) == O_RDONLY)
80 {
81 err = EACCES;
82 goto errout;
83 }
84
85 /* Is a driver registered? Does it support the write method? */
86
87 if (!filep->ops || !filep->ops->write)
88 {
89 err = EBADF;
90 goto errout;
91 }
92
93 /* Yes, then let the driver perform the write */
94
95 ret = filep->ops->write(filep, (const char *)buf, nbytes);
96 if (ret < 0)
97 {
98 err = -ret;
99 goto errout;
100 }
101
102 return ret;
103
104 errout:
105 set_errno(err);
106 return VFS_ERROR;
107 }
108
109 /****************************************************************************
110 * Name: write
111 *
112 * Description:
113 * write() writes up to nytes bytes to the file referenced by the file
114 * descriptor fd from the buffer starting at buf.
115 *
116 * Input Parameters:
117 * fd - file descriptor (or socket descriptor) to write to
118 * buf - Data to write
119 * nbytes - Length of data to write
120 *
121 * Returned Value:
122 * On success, the number of bytes written are returned (zero indicates
123 * nothing was written). On error, -1 is returned, and errno is set appro-
124 * priately:
125 *
126 * EAGAIN
127 * Non-blocking I/O has been selected using O_NONBLOCK and the write
128 * would block.
129 * EBADF
130 * fd is not a valid file descriptor or is not open for writing.
131 * EFAULT
132 * buf is outside your accessible address space.
133 * EFBIG
134 * An attempt was made to write a file that exceeds the implementation
135 * defined maximum file size or the process' file size limit, or
136 * to write at a position past the maximum allowed offset.
137 * EINTR
138 * The call was interrupted by a signal before any data was written.
139 * EINVAL
140 * fd is attached to an object which is unsuitable for writing; or
141 * the file was opened with the O_DIRECT flag, and either the address
142 * specified in buf, the value specified in count, or the current
143 * file offset is not suitably aligned.
144 * EIO
145 * A low-level I/O error occurred while modifying the vnode.
146 * ENOSPC
147 * The device containing the file referred to by fd has no room for
148 * the data.
149 * EPIPE
150 * fd is connected to a pipe or socket whose reading end is closed.
151 * When this happens the writing process will also receive a SIGPIPE
152 * signal. (Thus, the write return value is seen only if the program
153 * catches, blocks or ignores this signal.)
154 *
155 ****************************************************************************/
156
write(int fd,const void * buf,size_t nbytes)157 ssize_t write(int fd, const void *buf, size_t nbytes)
158 {
159 #if CONFIG_NFILE_DESCRIPTORS > 0
160 struct file *filep;
161 #endif
162
163 /* Did we get a valid file descriptor? */
164
165 #if CONFIG_NFILE_DESCRIPTORS > 0
166 if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
167 #endif
168 {
169 /* Write to a socket descriptor is equivalent to send with flags == 0 */
170
171 #if defined(LOSCFG_NET_LWIP_SACK)
172 const void *bufbak = buf;
173 ssize_t ret;
174 if (LOS_IsUserAddress((VADDR_T)(uintptr_t)buf))
175 {
176 if (buf != NULL && nbytes > 0)
177 {
178 buf = malloc(nbytes);
179 if (buf == NULL)
180 {
181 set_errno(ENOMEM);
182 return VFS_ERROR;
183 }
184 if (LOS_ArchCopyFromUser((void*)buf, bufbak, nbytes) != 0)
185 {
186 free((void*)buf);
187 set_errno(EFAULT);
188 return VFS_ERROR;
189 }
190 }
191 }
192 ret = send(fd, buf, nbytes, 0);
193 if (buf != bufbak)
194 {
195 free((void*)buf);
196 }
197 return ret;
198 #else
199 set_errno(EBADF);
200 return VFS_ERROR;
201 #endif
202 }
203
204 #if CONFIG_NFILE_DESCRIPTORS > 0
205 /* The descriptor is in the right range to be a file descriptor... write
206 * to the file.
207 */
208
209 if (fd <= STDERR_FILENO && fd >= STDIN_FILENO) /* fd : [0,2] */
210 {
211 fd = ConsoleUpdateFd();
212 if (fd < 0)
213 {
214 set_errno(EBADF);
215 return VFS_ERROR;
216 }
217 }
218
219 int ret = fs_getfilep(fd, &filep);
220 if (ret < 0)
221 {
222 /* The errno value has already been set */
223 return VFS_ERROR;
224 }
225
226 if (filep->f_oflags & O_DIRECTORY)
227 {
228 set_errno(EBADF);
229 return VFS_ERROR;
230 }
231
232 if (filep->f_oflags & O_APPEND)
233 {
234 if (file_seek64(filep, 0, SEEK_END) == -1)
235 {
236 return VFS_ERROR;
237 }
238 }
239
240 /* Perform the write operation using the file descriptor as an index */
241
242 return file_write(filep, buf, nbytes);
243 #endif
244 }
245