source: mainline/uspace/srv/vfs/vfs_ipc.c@ 984a9ba

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 984a9ba was 984a9ba, checked in by Martin Decky <martin@…>, 7 years ago

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

  • Property mode set to 100644
File size: 8.8 KB
Line 
1/*
2 * Copyright (c) 2008 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <vfs/vfs.h>
30#include "vfs.h"
31
32#include <errno.h>
33#include <stdlib.h>
34#include <str.h>
35#include <vfs/canonify.h>
36
37static void vfs_in_clone(ipc_call_t *req)
38{
39 int oldfd = IPC_GET_ARG1(*req);
40 int newfd = IPC_GET_ARG2(*req);
41 bool desc = IPC_GET_ARG3(*req);
42
43 int outfd = -1;
44 errno_t rc = vfs_op_clone(oldfd, newfd, desc, &outfd);
45 async_answer_1(req, rc, outfd);
46}
47
48static void vfs_in_fsprobe(ipc_call_t *req)
49{
50 service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
51 char *fs_name = NULL;
52 vfs_fs_probe_info_t info;
53 errno_t rc;
54
55 /*
56 * Now we expect the client to send us data with the name of the file
57 * system.
58 */
59 rc = async_data_write_accept((void **) &fs_name, true, 0,
60 FS_NAME_MAXLEN, 0, NULL);
61 if (rc != EOK) {
62 async_answer_0(req, rc);
63 return;
64 }
65
66 rc = vfs_op_fsprobe(fs_name, service_id, &info);
67 async_answer_0(req, rc);
68 if (rc != EOK)
69 goto out;
70
71 /* Now we should get a read request */
72 ipc_call_t call;
73 size_t len;
74 if (!async_data_read_receive(&call, &len))
75 goto out;
76
77 if (len > sizeof(info))
78 len = sizeof(info);
79 (void) async_data_read_finalize(&call, &info, len);
80
81out:
82 free(fs_name);
83}
84
85static void vfs_in_fstypes(ipc_call_t *req)
86{
87 vfs_fstypes_t fstypes;
88 errno_t rc;
89
90 rc = vfs_get_fstypes(&fstypes);
91 if (rc != EOK) {
92 async_answer_0(req, ENOMEM);
93 return;
94 }
95
96 /* Send size of the data */
97 async_answer_1(req, EOK, fstypes.size);
98
99 /* Now we should get a read request */
100 ipc_call_t call;
101 size_t len;
102 if (!async_data_read_receive(&call, &len))
103 goto out;
104
105 if (len > fstypes.size)
106 len = fstypes.size;
107 (void) async_data_read_finalize(&call, fstypes.buf, len);
108
109out:
110 vfs_fstypes_free(&fstypes);
111}
112
113static void vfs_in_mount(ipc_call_t *req)
114{
115 int mpfd = IPC_GET_ARG1(*req);
116
117 /*
118 * We expect the library to do the device-name to device-handle
119 * translation for us, thus the device handle will arrive as ARG1
120 * in the request.
121 */
122 service_id_t service_id = (service_id_t) IPC_GET_ARG2(*req);
123
124 unsigned int flags = (unsigned int) IPC_GET_ARG3(*req);
125 unsigned int instance = IPC_GET_ARG4(*req);
126
127 char *opts = NULL;
128 char *fs_name = NULL;
129
130 /* Now we expect to receive the mount options. */
131 errno_t rc = async_data_write_accept((void **) &opts, true, 0,
132 MAX_MNTOPTS_LEN, 0, NULL);
133 if (rc != EOK) {
134 async_answer_0(req, rc);
135 return;
136 }
137
138 /*
139 * Now we expect the client to send us data with the name of the file
140 * system.
141 */
142 rc = async_data_write_accept((void **) &fs_name, true, 0,
143 FS_NAME_MAXLEN, 0, NULL);
144 if (rc != EOK) {
145 free(opts);
146 async_answer_0(req, rc);
147 return;
148 }
149
150 int outfd = 0;
151 rc = vfs_op_mount(mpfd, service_id, flags, instance, opts, fs_name,
152 &outfd);
153 async_answer_1(req, rc, outfd);
154
155 free(opts);
156 free(fs_name);
157}
158
159static void vfs_in_open(ipc_call_t *req)
160{
161 int fd = IPC_GET_ARG1(*req);
162 int mode = IPC_GET_ARG2(*req);
163
164 errno_t rc = vfs_op_open(fd, mode);
165 async_answer_0(req, rc);
166}
167
168static void vfs_in_put(ipc_call_t *req)
169{
170 int fd = IPC_GET_ARG1(*req);
171 errno_t rc = vfs_op_put(fd);
172 async_answer_0(req, rc);
173}
174
175static void vfs_in_read(ipc_call_t *req)
176{
177 int fd = IPC_GET_ARG1(*req);
178 aoff64_t pos = MERGE_LOUP32(IPC_GET_ARG2(*req),
179 IPC_GET_ARG3(*req));
180
181 size_t bytes = 0;
182 errno_t rc = vfs_op_read(fd, pos, &bytes);
183 async_answer_1(req, rc, bytes);
184}
185
186static void vfs_in_rename(ipc_call_t *req)
187{
188 /* The common base directory. */
189 int basefd;
190 char *old = NULL;
191 char *new = NULL;
192 errno_t rc;
193
194 basefd = IPC_GET_ARG1(*req);
195
196 /* Retrieve the old path. */
197 rc = async_data_write_accept((void **) &old, true, 0, 0, 0, NULL);
198 if (rc != EOK)
199 goto out;
200
201 /* Retrieve the new path. */
202 rc = async_data_write_accept((void **) &new, true, 0, 0, 0, NULL);
203 if (rc != EOK)
204 goto out;
205
206 size_t olen;
207 size_t nlen;
208 char *oldc = canonify(old, &olen);
209 char *newc = canonify(new, &nlen);
210
211 if ((!oldc) || (!newc)) {
212 rc = EINVAL;
213 goto out;
214 }
215
216 assert(oldc[olen] == '\0');
217 assert(newc[nlen] == '\0');
218
219 rc = vfs_op_rename(basefd, oldc, newc);
220
221out:
222 async_answer_0(req, rc);
223
224 if (old)
225 free(old);
226 if (new)
227 free(new);
228}
229
230static void vfs_in_resize(ipc_call_t *req)
231{
232 int fd = IPC_GET_ARG1(*req);
233 int64_t size = MERGE_LOUP32(IPC_GET_ARG2(*req), IPC_GET_ARG3(*req));
234 errno_t rc = vfs_op_resize(fd, size);
235 async_answer_0(req, rc);
236}
237
238static void vfs_in_stat(ipc_call_t *req)
239{
240 int fd = IPC_GET_ARG1(*req);
241 errno_t rc = vfs_op_stat(fd);
242 async_answer_0(req, rc);
243}
244
245static void vfs_in_statfs(ipc_call_t *req)
246{
247 int fd = (int) IPC_GET_ARG1(*req);
248
249 errno_t rc = vfs_op_statfs(fd);
250 async_answer_0(req, rc);
251}
252
253static void vfs_in_sync(ipc_call_t *req)
254{
255 int fd = IPC_GET_ARG1(*req);
256 errno_t rc = vfs_op_sync(fd);
257 async_answer_0(req, rc);
258}
259
260static void vfs_in_unlink(ipc_call_t *req)
261{
262 int parentfd = IPC_GET_ARG1(*req);
263 int expectfd = IPC_GET_ARG2(*req);
264
265 char *path;
266 errno_t rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
267 if (rc == EOK)
268 rc = vfs_op_unlink(parentfd, expectfd, path);
269
270 async_answer_0(req, rc);
271}
272
273static void vfs_in_unmount(ipc_call_t *req)
274{
275 int mpfd = IPC_GET_ARG1(*req);
276 errno_t rc = vfs_op_unmount(mpfd);
277 async_answer_0(req, rc);
278}
279
280static void vfs_in_wait_handle(ipc_call_t *req)
281{
282 bool high_fd = IPC_GET_ARG1(*req);
283 int fd = -1;
284 errno_t rc = vfs_op_wait_handle(high_fd, &fd);
285 async_answer_1(req, rc, fd);
286}
287
288static void vfs_in_walk(ipc_call_t *req)
289{
290 /*
291 * Parent is our relative root for file lookup.
292 * For defined flags, see <ipc/vfs.h>.
293 */
294 int parentfd = IPC_GET_ARG1(*req);
295 int flags = IPC_GET_ARG2(*req);
296
297 int fd = 0;
298 char *path;
299 errno_t rc = async_data_write_accept((void **)&path, true, 0, 0, 0, NULL);
300 if (rc == EOK) {
301 rc = vfs_op_walk(parentfd, flags, path, &fd);
302 free(path);
303 }
304 async_answer_1(req, rc, fd);
305}
306
307static void vfs_in_write(ipc_call_t *req)
308{
309 int fd = IPC_GET_ARG1(*req);
310 aoff64_t pos = MERGE_LOUP32(IPC_GET_ARG2(*req),
311 IPC_GET_ARG3(*req));
312
313 size_t bytes = 0;
314 errno_t rc = vfs_op_write(fd, pos, &bytes);
315 async_answer_1(req, rc, bytes);
316}
317
318void vfs_connection(ipc_call_t *icall, void *arg)
319{
320 bool cont = true;
321
322 /*
323 * The connection was opened via the IPC_CONNECT_ME_TO call.
324 * This call needs to be answered.
325 */
326 async_answer_0(icall, EOK);
327
328 while (cont) {
329 ipc_call_t call;
330 async_get_call(&call);
331
332 if (!IPC_GET_IMETHOD(call))
333 break;
334
335 switch (IPC_GET_IMETHOD(call)) {
336 case VFS_IN_CLONE:
337 vfs_in_clone(&call);
338 break;
339 case VFS_IN_FSPROBE:
340 vfs_in_fsprobe(&call);
341 break;
342 case VFS_IN_FSTYPES:
343 vfs_in_fstypes(&call);
344 break;
345 case VFS_IN_MOUNT:
346 vfs_in_mount(&call);
347 break;
348 case VFS_IN_OPEN:
349 vfs_in_open(&call);
350 break;
351 case VFS_IN_PUT:
352 vfs_in_put(&call);
353 break;
354 case VFS_IN_READ:
355 vfs_in_read(&call);
356 break;
357 case VFS_IN_REGISTER:
358 vfs_register(&call);
359 cont = false;
360 break;
361 case VFS_IN_RENAME:
362 vfs_in_rename(&call);
363 break;
364 case VFS_IN_RESIZE:
365 vfs_in_resize(&call);
366 break;
367 case VFS_IN_STAT:
368 vfs_in_stat(&call);
369 break;
370 case VFS_IN_STATFS:
371 vfs_in_statfs(&call);
372 break;
373 case VFS_IN_SYNC:
374 vfs_in_sync(&call);
375 break;
376 case VFS_IN_UNLINK:
377 vfs_in_unlink(&call);
378 break;
379 case VFS_IN_UNMOUNT:
380 vfs_in_unmount(&call);
381 break;
382 case VFS_IN_WAIT_HANDLE:
383 vfs_in_wait_handle(&call);
384 break;
385 case VFS_IN_WALK:
386 vfs_in_walk(&call);
387 break;
388 case VFS_IN_WRITE:
389 vfs_in_write(&call);
390 break;
391 default:
392 async_answer_0(&call, ENOTSUP);
393 break;
394 }
395 }
396
397 /*
398 * Open files for this client will be cleaned up when its last
399 * connection fibril terminates.
400 */
401}
Note: See TracBrowser for help on using the repository browser.