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
);
44 errno_t rc
= vfs_op_clone(oldfd
, newfd
, desc
, &outfd
);
45 async_answer_1(rid
, rc
, outfd
);
48 static void vfs_in_fsprobe(ipc_callid_t rid
, ipc_call_t
*request
)
50 service_id_t service_id
= (service_id_t
) IPC_GET_ARG1(*request
);
53 vfs_fs_probe_info_t info
;
58 * Now we expect the client to send us data with the name of the file
61 rc
= async_data_write_accept((void **) &fs_name
, true, 0,
62 FS_NAME_MAXLEN
, 0, NULL
);
64 async_answer_0(rid
, rc
);
68 rc
= vfs_op_fsprobe(fs_name
, service_id
, &info
);
69 async_answer_0(rid
, rc
);
73 /* Now we should get a read request */
74 if (!async_data_read_receive(&callid
, &len
))
77 if (len
> sizeof(info
))
79 (void) async_data_read_finalize(callid
, &info
, len
);
85 static void vfs_in_fstypes(ipc_callid_t rid
, ipc_call_t
*request
)
89 vfs_fstypes_t fstypes
;
92 rc
= vfs_get_fstypes(&fstypes
);
94 async_answer_0(rid
, ENOMEM
);
98 /* Send size of the data */
99 async_answer_1(rid
, EOK
, fstypes
.size
);
101 /* Now we should get a read request */
102 if (!async_data_read_receive(&callid
, &len
))
105 if (len
> fstypes
.size
)
107 (void) async_data_read_finalize(callid
, fstypes
.buf
, len
);
110 vfs_fstypes_free(&fstypes
);
113 static void vfs_in_mount(ipc_callid_t rid
, ipc_call_t
*request
)
115 int mpfd
= IPC_GET_ARG1(*request
);
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
122 service_id_t service_id
= (service_id_t
) IPC_GET_ARG2(*request
);
124 unsigned int flags
= (unsigned int) IPC_GET_ARG3(*request
);
125 unsigned int instance
= IPC_GET_ARG4(*request
);
128 char *fs_name
= NULL
;
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
);
134 async_answer_0(rid
, rc
);
138 /* Now, we expect the client to send us data with the name of the file
141 rc
= async_data_write_accept((void **) &fs_name
, true, 0,
142 FS_NAME_MAXLEN
, 0, NULL
);
145 async_answer_0(rid
, rc
);
150 rc
= vfs_op_mount(mpfd
, service_id
, flags
, instance
, opts
, fs_name
,
152 async_answer_1(rid
, rc
, outfd
);
158 static void vfs_in_open(ipc_callid_t rid
, ipc_call_t
*request
)
160 int fd
= IPC_GET_ARG1(*request
);
161 int mode
= IPC_GET_ARG2(*request
);
163 errno_t rc
= vfs_op_open(fd
, mode
);
164 async_answer_0(rid
, rc
);
167 static void vfs_in_put(ipc_callid_t rid
, ipc_call_t
*request
)
169 int fd
= IPC_GET_ARG1(*request
);
170 errno_t rc
= vfs_op_put(fd
);
171 async_answer_0(rid
, rc
);
174 static void vfs_in_read(ipc_callid_t rid
, ipc_call_t
*request
)
176 int fd
= IPC_GET_ARG1(*request
);
177 aoff64_t pos
= MERGE_LOUP32(IPC_GET_ARG2(*request
),
178 IPC_GET_ARG3(*request
));
181 errno_t rc
= vfs_op_read(fd
, pos
, &bytes
);
182 async_answer_1(rid
, rc
, bytes
);
185 static void vfs_in_rename(ipc_callid_t rid
, ipc_call_t
*request
)
187 /* The common base directory. */
193 basefd
= IPC_GET_ARG1(*request
);
195 /* Retrieve the old path. */
196 rc
= async_data_write_accept((void **) &old
, true, 0, 0, 0, NULL
);
200 /* Retrieve the new path. */
201 rc
= async_data_write_accept((void **) &new, true, 0, 0, 0, NULL
);
207 char *oldc
= canonify(old
, &olen
);
208 char *newc
= canonify(new, &nlen
);
210 if ((!oldc
) || (!newc
)) {
215 assert(oldc
[olen
] == '\0');
216 assert(newc
[nlen
] == '\0');
218 rc
= vfs_op_rename(basefd
, oldc
, newc
);
221 async_answer_0(rid
, rc
);
229 static void vfs_in_resize(ipc_callid_t rid
, ipc_call_t
*request
)
231 int fd
= IPC_GET_ARG1(*request
);
232 int64_t size
= MERGE_LOUP32(IPC_GET_ARG2(*request
), IPC_GET_ARG3(*request
));
233 errno_t rc
= vfs_op_resize(fd
, size
);
234 async_answer_0(rid
, rc
);
237 static void vfs_in_stat(ipc_callid_t rid
, ipc_call_t
*request
)
239 int fd
= IPC_GET_ARG1(*request
);
240 errno_t rc
= vfs_op_stat(fd
);
241 async_answer_0(rid
, rc
);
244 static void vfs_in_statfs(ipc_callid_t rid
, ipc_call_t
*request
)
246 int fd
= (int) IPC_GET_ARG1(*request
);
248 errno_t rc
= vfs_op_statfs(fd
);
249 async_answer_0(rid
, rc
);
252 static void vfs_in_sync(ipc_callid_t rid
, ipc_call_t
*request
)
254 int fd
= IPC_GET_ARG1(*request
);
255 errno_t rc
= vfs_op_sync(fd
);
256 async_answer_0(rid
, rc
);
259 static void vfs_in_unlink(ipc_callid_t rid
, ipc_call_t
*request
)
261 int parentfd
= IPC_GET_ARG1(*request
);
262 int expectfd
= IPC_GET_ARG2(*request
);
265 errno_t rc
= async_data_write_accept((void **) &path
, true, 0, 0, 0, NULL
);
267 rc
= vfs_op_unlink(parentfd
, expectfd
, path
);
269 async_answer_0(rid
, rc
);
272 static void vfs_in_unmount(ipc_callid_t rid
, ipc_call_t
*request
)
274 int mpfd
= IPC_GET_ARG1(*request
);
275 errno_t rc
= vfs_op_unmount(mpfd
);
276 async_answer_0(rid
, rc
);
279 static void vfs_in_wait_handle(ipc_callid_t rid
, ipc_call_t
*request
)
281 bool high_fd
= IPC_GET_ARG1(*request
);
283 errno_t rc
= vfs_op_wait_handle(high_fd
, &fd
);
284 async_answer_1(rid
, rc
, fd
);
287 static void vfs_in_walk(ipc_callid_t rid
, ipc_call_t
*request
)
290 * Parent is our relative root for file lookup.
291 * For defined flags, see <ipc/vfs.h>.
293 int parentfd
= IPC_GET_ARG1(*request
);
294 int flags
= IPC_GET_ARG2(*request
);
298 errno_t rc
= async_data_write_accept((void **)&path
, true, 0, 0, 0, NULL
);
300 rc
= vfs_op_walk(parentfd
, flags
, path
, &fd
);
303 async_answer_1(rid
, rc
, fd
);
306 static void vfs_in_write(ipc_callid_t rid
, ipc_call_t
*request
)
308 int fd
= IPC_GET_ARG1(*request
);
309 aoff64_t pos
= MERGE_LOUP32(IPC_GET_ARG2(*request
),
310 IPC_GET_ARG3(*request
));
313 errno_t rc
= vfs_op_write(fd
, pos
, &bytes
);
314 async_answer_1(rid
, rc
, bytes
);
317 void vfs_connection(ipc_callid_t iid
, ipc_call_t
*icall
, void *arg
)
322 * The connection was opened via the IPC_CONNECT_ME_TO call.
323 * This call needs to be answered.
325 async_answer_0(iid
, EOK
);
329 ipc_callid_t callid
= async_get_call(&call
);
331 if (!IPC_GET_IMETHOD(call
))
334 switch (IPC_GET_IMETHOD(call
)) {
336 vfs_in_clone(callid
, &call
);
339 vfs_in_fsprobe(callid
, &call
);
342 vfs_in_fstypes(callid
, &call
);
345 vfs_in_mount(callid
, &call
);
348 vfs_in_open(callid
, &call
);
351 vfs_in_put(callid
, &call
);
354 vfs_in_read(callid
, &call
);
356 case VFS_IN_REGISTER
:
357 vfs_register(callid
, &call
);
361 vfs_in_rename(callid
, &call
);
364 vfs_in_resize(callid
, &call
);
367 vfs_in_stat(callid
, &call
);
370 vfs_in_statfs(callid
, &call
);
373 vfs_in_sync(callid
, &call
);
376 vfs_in_unlink(callid
, &call
);
379 vfs_in_unmount(callid
, &call
);
381 case VFS_IN_WAIT_HANDLE
:
382 vfs_in_wait_handle(callid
, &call
);
385 vfs_in_walk(callid
, &call
);
388 vfs_in_write(callid
, &call
);
391 async_answer_0(callid
, ENOTSUP
);
397 * Open files for this client will be cleaned up when its last
398 * connection fibril terminates.