2 * Copyright (c) 2008 Jakub Jermar
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
35 #include <vfs/canonify.h>
37 static void vfs_in_clone(ipc_callid_t rid
, ipc_call_t
*request
)
39 int oldfd
= IPC_GET_ARG1(*request
);
40 int newfd
= IPC_GET_ARG2(*request
);
41 bool desc
= IPC_GET_ARG3(*request
);
43 int ret
= vfs_op_clone(oldfd
, newfd
, desc
);
44 async_answer_0(rid
, ret
);
47 static void vfs_in_fsprobe(ipc_callid_t rid
, ipc_call_t
*request
)
49 service_id_t service_id
= (service_id_t
) IPC_GET_ARG1(*request
);
52 vfs_fs_probe_info_t info
;
57 * Now we expect the client to send us data with the name of the file
60 rc
= async_data_write_accept((void **) &fs_name
, true, 0,
61 FS_NAME_MAXLEN
, 0, NULL
);
63 async_answer_0(rid
, rc
);
67 rc
= vfs_op_fsprobe(fs_name
, service_id
, &info
);
68 async_answer_0(rid
, rc
);
72 /* Now we should get a read request */
73 if (!async_data_read_receive(&callid
, &len
))
76 if (len
> sizeof(info
))
78 (void) async_data_read_finalize(callid
, &info
, len
);
84 static void vfs_in_fstypes(ipc_callid_t rid
, ipc_call_t
*request
)
88 vfs_fstypes_t fstypes
;
91 rc
= vfs_get_fstypes(&fstypes
);
93 async_answer_0(rid
, ENOMEM
);
97 /* Send size of the data */
98 async_answer_1(rid
, EOK
, fstypes
.size
);
100 /* Now we should get a read request */
101 if (!async_data_read_receive(&callid
, &len
))
104 if (len
> fstypes
.size
)
106 (void) async_data_read_finalize(callid
, fstypes
.buf
, len
);
109 vfs_fstypes_free(&fstypes
);
112 static void vfs_in_mount(ipc_callid_t rid
, ipc_call_t
*request
)
114 int mpfd
= IPC_GET_ARG1(*request
);
117 * We expect the library to do the device-name to device-handle
118 * translation for us, thus the device handle will arrive as ARG1
121 service_id_t service_id
= (service_id_t
) IPC_GET_ARG2(*request
);
123 unsigned int flags
= (unsigned int) IPC_GET_ARG3(*request
);
124 unsigned int instance
= IPC_GET_ARG4(*request
);
127 char *fs_name
= NULL
;
129 /* Now we expect to receive the mount options. */
130 int rc
= async_data_write_accept((void **) &opts
, true, 0,
131 MAX_MNTOPTS_LEN
, 0, NULL
);
133 async_answer_0(rid
, rc
);
137 /* Now, we expect the client to send us data with the name of the file
140 rc
= async_data_write_accept((void **) &fs_name
, true, 0,
141 FS_NAME_MAXLEN
, 0, NULL
);
144 async_answer_0(rid
, rc
);
149 rc
= vfs_op_mount(mpfd
, service_id
, flags
, instance
, opts
, fs_name
,
151 async_answer_1(rid
, rc
, outfd
);
157 static void vfs_in_open(ipc_callid_t rid
, ipc_call_t
*request
)
159 int fd
= IPC_GET_ARG1(*request
);
160 int mode
= IPC_GET_ARG2(*request
);
162 int rc
= vfs_op_open(fd
, mode
);
163 async_answer_0(rid
, rc
);
166 static void vfs_in_put(ipc_callid_t rid
, ipc_call_t
*request
)
168 int fd
= IPC_GET_ARG1(*request
);
169 int rc
= vfs_op_put(fd
);
170 async_answer_0(rid
, rc
);
173 static void vfs_in_read(ipc_callid_t rid
, ipc_call_t
*request
)
175 int fd
= IPC_GET_ARG1(*request
);
176 aoff64_t pos
= MERGE_LOUP32(IPC_GET_ARG2(*request
),
177 IPC_GET_ARG3(*request
));
180 int rc
= vfs_op_read(fd
, pos
, &bytes
);
181 async_answer_1(rid
, rc
, bytes
);
184 static void vfs_in_rename(ipc_callid_t rid
, ipc_call_t
*request
)
186 /* The common base directory. */
192 basefd
= IPC_GET_ARG1(*request
);
194 /* Retrieve the old path. */
195 rc
= async_data_write_accept((void **) &old
, true, 0, 0, 0, NULL
);
199 /* Retrieve the new path. */
200 rc
= async_data_write_accept((void **) &new, true, 0, 0, 0, NULL
);
206 char *oldc
= canonify(old
, &olen
);
207 char *newc
= canonify(new, &nlen
);
209 if ((!oldc
) || (!newc
)) {
214 assert(oldc
[olen
] == '\0');
215 assert(newc
[nlen
] == '\0');
217 rc
= vfs_op_rename(basefd
, oldc
, newc
);
220 async_answer_0(rid
, rc
);
228 static void vfs_in_resize(ipc_callid_t rid
, ipc_call_t
*request
)
230 int fd
= IPC_GET_ARG1(*request
);
231 int64_t size
= MERGE_LOUP32(IPC_GET_ARG2(*request
), IPC_GET_ARG3(*request
));
232 int rc
= vfs_op_resize(fd
, size
);
233 async_answer_0(rid
, rc
);
236 static void vfs_in_stat(ipc_callid_t rid
, ipc_call_t
*request
)
238 int fd
= IPC_GET_ARG1(*request
);
239 int rc
= vfs_op_stat(fd
);
240 async_answer_0(rid
, rc
);
243 static void vfs_in_statfs(ipc_callid_t rid
, ipc_call_t
*request
)
245 int fd
= (int) IPC_GET_ARG1(*request
);
247 int rc
= vfs_op_statfs(fd
);
248 async_answer_0(rid
, rc
);
251 static void vfs_in_sync(ipc_callid_t rid
, ipc_call_t
*request
)
253 int fd
= IPC_GET_ARG1(*request
);
254 int rc
= vfs_op_sync(fd
);
255 async_answer_0(rid
, rc
);
258 static void vfs_in_unlink(ipc_callid_t rid
, ipc_call_t
*request
)
260 int parentfd
= IPC_GET_ARG1(*request
);
261 int expectfd
= IPC_GET_ARG2(*request
);
264 int rc
= async_data_write_accept((void **) &path
, true, 0, 0, 0, NULL
);
266 rc
= vfs_op_unlink(parentfd
, expectfd
, path
);
268 async_answer_0(rid
, rc
);
271 static void vfs_in_unmount(ipc_callid_t rid
, ipc_call_t
*request
)
273 int mpfd
= IPC_GET_ARG1(*request
);
274 int rc
= vfs_op_unmount(mpfd
);
275 async_answer_0(rid
, rc
);
278 static void vfs_in_wait_handle(ipc_callid_t rid
, ipc_call_t
*request
)
280 bool high_fd
= IPC_GET_ARG1(*request
);
281 int fd
= vfs_op_wait_handle(high_fd
);
282 async_answer_1(rid
, EOK
, fd
);
285 static void vfs_in_walk(ipc_callid_t rid
, ipc_call_t
*request
)
288 * Parent is our relative root for file lookup.
289 * For defined flags, see <ipc/vfs.h>.
291 int parentfd
= IPC_GET_ARG1(*request
);
292 int flags
= IPC_GET_ARG2(*request
);
296 int rc
= async_data_write_accept((void **)&path
, true, 0, 0, 0, NULL
);
298 rc
= vfs_op_walk(parentfd
, flags
, path
, &fd
);
301 async_answer_1(rid
, rc
, fd
);
304 static void vfs_in_write(ipc_callid_t rid
, ipc_call_t
*request
)
306 int fd
= IPC_GET_ARG1(*request
);
307 aoff64_t pos
= MERGE_LOUP32(IPC_GET_ARG2(*request
),
308 IPC_GET_ARG3(*request
));
311 int rc
= vfs_op_write(fd
, pos
, &bytes
);
312 async_answer_1(rid
, rc
, bytes
);
315 void vfs_connection(ipc_callid_t iid
, ipc_call_t
*icall
, void *arg
)
320 * The connection was opened via the IPC_CONNECT_ME_TO call.
321 * This call needs to be answered.
323 async_answer_0(iid
, EOK
);
327 ipc_callid_t callid
= async_get_call(&call
);
329 if (!IPC_GET_IMETHOD(call
))
332 switch (IPC_GET_IMETHOD(call
)) {
334 vfs_in_clone(callid
, &call
);
337 vfs_in_fsprobe(callid
, &call
);
340 vfs_in_fstypes(callid
, &call
);
343 vfs_in_mount(callid
, &call
);
346 vfs_in_open(callid
, &call
);
349 vfs_in_put(callid
, &call
);
352 vfs_in_read(callid
, &call
);
354 case VFS_IN_REGISTER
:
355 vfs_register(callid
, &call
);
359 vfs_in_rename(callid
, &call
);
362 vfs_in_resize(callid
, &call
);
365 vfs_in_stat(callid
, &call
);
368 vfs_in_statfs(callid
, &call
);
371 vfs_in_sync(callid
, &call
);
374 vfs_in_unlink(callid
, &call
);
377 vfs_in_unmount(callid
, &call
);
379 case VFS_IN_WAIT_HANDLE
:
380 vfs_in_wait_handle(callid
, &call
);
383 vfs_in_walk(callid
, &call
);
386 vfs_in_write(callid
, &call
);
389 async_answer_0(callid
, ENOTSUP
);
395 * Open files for this client will be cleaned up when its last
396 * connection fibril terminates.