Rev 4263 | Rev 4581 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4263 | Rev 4327 | ||
---|---|---|---|
Line 58... | Line 58... | ||
58 | /** Pending mount structure. */ |
58 | /** Pending mount structure. */ |
59 | typedef struct { |
59 | typedef struct { |
60 | link_t link; |
60 | link_t link; |
61 | char *fs_name; /**< File system name */ |
61 | char *fs_name; /**< File system name */ |
62 | char *mp; /**< Mount point */ |
62 | char *mp; /**< Mount point */ |
- | 63 | char *opts; /**< Mount options. */ |
|
63 | ipc_callid_t callid; /**< Call ID waiting for the mount */ |
64 | ipc_callid_t callid; /**< Call ID waiting for the mount */ |
64 | ipc_callid_t rid; /**< Request ID */ |
65 | ipc_callid_t rid; /**< Request ID */ |
65 | dev_handle_t dev_handle; /**< Device handle */ |
66 | dev_handle_t dev_handle; /**< Device handle */ |
66 | } pending_req_t; |
67 | } pending_req_t; |
67 | 68 | ||
Line 78... | Line 79... | ||
78 | .fs_handle = 0, |
79 | .fs_handle = 0, |
79 | .dev_handle = 0 |
80 | .dev_handle = 0 |
80 | }; |
81 | }; |
81 | 82 | ||
82 | static void vfs_mount_internal(ipc_callid_t rid, dev_handle_t dev_handle, |
83 | static void vfs_mount_internal(ipc_callid_t rid, dev_handle_t dev_handle, |
83 | fs_handle_t fs_handle, char *mp) |
84 | fs_handle_t fs_handle, char *mp, char *opts) |
84 | { |
85 | { |
85 | /* Resolve the path to the mountpoint. */ |
- | |
86 | vfs_lookup_res_t mp_res; |
86 | vfs_lookup_res_t mp_res; |
87 | vfs_node_t *mp_node = NULL; |
87 | vfs_node_t *mp_node = NULL; |
88 | int rc; |
88 | ipcarg_t rc; |
89 | int phone; |
89 | int phone; |
- | 90 | aid_t msg; |
|
- | 91 | ipc_call_t answer; |
|
- | 92 | ||
- | 93 | /* Resolve the path to the mountpoint. */ |
|
90 | futex_down(&rootfs_futex); |
94 | futex_down(&rootfs_futex); |
91 | if (rootfs.fs_handle) { |
95 | if (rootfs.fs_handle) { |
92 | /* We already have the root FS. */ |
96 | /* We already have the root FS. */ |
93 | rwlock_write_lock(&namespace_rwlock); |
97 | rwlock_write_lock(&namespace_rwlock); |
94 | if ((strlen(mp) == 1) && (mp[0] == '/')) { |
98 | if (str_cmp(mp, "/") == 0) { |
95 | /* Trying to mount root FS over root FS */ |
99 | /* Trying to mount root FS over root FS */ |
96 | rwlock_write_unlock(&namespace_rwlock); |
100 | rwlock_write_unlock(&namespace_rwlock); |
97 | futex_up(&rootfs_futex); |
101 | futex_up(&rootfs_futex); |
98 | ipc_answer_0(rid, EBUSY); |
102 | ipc_answer_0(rid, EBUSY); |
99 | return; |
103 | return; |
Line 122... | Line 126... | ||
122 | * This prevents the mount point from being deleted. |
126 | * This prevents the mount point from being deleted. |
123 | */ |
127 | */ |
124 | rwlock_write_unlock(&namespace_rwlock); |
128 | rwlock_write_unlock(&namespace_rwlock); |
125 | } else { |
129 | } else { |
126 | /* We still don't have the root file system mounted. */ |
130 | /* We still don't have the root file system mounted. */ |
127 | if ((strlen(mp) == 1) && (mp[0] == '/')) { |
131 | if (str_cmp(mp, "/") == 0) { |
128 | vfs_lookup_res_t mr_res; |
132 | vfs_lookup_res_t mr_res; |
129 | vfs_node_t *mr_node; |
133 | vfs_node_t *mr_node; |
130 | ipcarg_t rindex; |
134 | fs_index_t rindex; |
131 | ipcarg_t rsize; |
135 | size_t rsize; |
132 | ipcarg_t rlnkcnt; |
136 | unsigned rlnkcnt; |
133 | 137 | ||
134 | /* |
138 | /* |
135 | * For this simple, but important case, |
139 | * For this simple, but important case, |
136 | * we are almost done. |
140 | * we are almost done. |
137 | */ |
141 | */ |
138 | 142 | ||
139 | /* Tell the mountee that it is being mounted. */ |
143 | /* Tell the mountee that it is being mounted. */ |
140 | phone = vfs_grab_phone(fs_handle); |
144 | phone = vfs_grab_phone(fs_handle); |
141 | rc = async_req_1_3(phone, VFS_MOUNTED, |
145 | msg = async_send_1(phone, VFS_MOUNTED, |
142 | (ipcarg_t) dev_handle, &rindex, &rsize, &rlnkcnt); |
146 | (ipcarg_t) dev_handle, &answer); |
- | 147 | /* send the mount options */ |
|
- | 148 | rc = ipc_data_write_start(phone, (void *)opts, |
|
- | 149 | str_size(opts)); |
|
- | 150 | if (rc != EOK) { |
|
- | 151 | async_wait_for(msg, NULL); |
|
- | 152 | vfs_release_phone(phone); |
|
- | 153 | futex_up(&rootfs_futex); |
|
- | 154 | ipc_answer_0(rid, rc); |
|
- | 155 | return; |
|
- | 156 | } |
|
- | 157 | async_wait_for(msg, &rc); |
|
143 | vfs_release_phone(phone); |
158 | vfs_release_phone(phone); |
144 | 159 | ||
145 | if (rc != EOK) { |
160 | if (rc != EOK) { |
146 | futex_up(&rootfs_futex); |
161 | futex_up(&rootfs_futex); |
147 | ipc_answer_0(rid, rc); |
162 | ipc_answer_0(rid, rc); |
148 | return; |
163 | return; |
149 | } |
164 | } |
- | 165 | ||
- | 166 | rindex = (fs_index_t) IPC_GET_ARG1(answer); |
|
- | 167 | rsize = (size_t) IPC_GET_ARG2(answer); |
|
- | 168 | rlnkcnt = (unsigned) IPC_GET_ARG3(answer); |
|
150 | 169 | ||
151 | mr_res.triplet.fs_handle = fs_handle; |
170 | mr_res.triplet.fs_handle = fs_handle; |
152 | mr_res.triplet.dev_handle = dev_handle; |
171 | mr_res.triplet.dev_handle = dev_handle; |
153 | mr_res.triplet.index = (fs_index_t) rindex; |
172 | mr_res.triplet.index = rindex; |
154 | mr_res.size = (size_t) rsize; |
173 | mr_res.size = rsize; |
155 | mr_res.lnkcnt = (unsigned) rlnkcnt; |
174 | mr_res.lnkcnt = rlnkcnt; |
156 | mr_res.type = VFS_NODE_DIRECTORY; |
175 | mr_res.type = VFS_NODE_DIRECTORY; |
157 | 176 | ||
158 | rootfs.fs_handle = fs_handle; |
177 | rootfs.fs_handle = fs_handle; |
159 | rootfs.dev_handle = dev_handle; |
178 | rootfs.dev_handle = dev_handle; |
160 | futex_up(&rootfs_futex); |
179 | futex_up(&rootfs_futex); |
Line 181... | Line 200... | ||
181 | * At this point, we have all necessary pieces: file system and device |
200 | * At this point, we have all necessary pieces: file system and device |
182 | * handles, and we know the mount point VFS node. |
201 | * handles, and we know the mount point VFS node. |
183 | */ |
202 | */ |
184 | 203 | ||
185 | phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
204 | phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
186 | rc = async_req_4_0(phone, VFS_MOUNT, |
205 | msg = async_send_4(phone, VFS_MOUNT, |
187 | (ipcarg_t) mp_res.triplet.dev_handle, |
206 | (ipcarg_t) mp_res.triplet.dev_handle, |
188 | (ipcarg_t) mp_res.triplet.index, |
207 | (ipcarg_t) mp_res.triplet.index, |
189 | (ipcarg_t) fs_handle, |
208 | (ipcarg_t) fs_handle, |
190 | (ipcarg_t) dev_handle); |
209 | (ipcarg_t) dev_handle, &answer); |
- | 210 | /* send the mount options */ |
|
- | 211 | rc = ipc_data_write_start(phone, (void *)opts, str_size(opts)); |
|
- | 212 | if (rc != EOK) { |
|
- | 213 | async_wait_for(msg, NULL); |
|
- | 214 | vfs_release_phone(phone); |
|
- | 215 | /* Mount failed, drop reference to mp_node. */ |
|
- | 216 | if (mp_node) |
|
- | 217 | vfs_node_put(mp_node); |
|
- | 218 | ipc_answer_0(rid, rc); |
|
- | 219 | return; |
|
- | 220 | } |
|
- | 221 | async_wait_for(msg, &rc); |
|
191 | vfs_release_phone(phone); |
222 | vfs_release_phone(phone); |
192 | 223 | ||
193 | if (rc != EOK) { |
224 | if (rc != EOK) { |
194 | /* Mount failed, drop reference to mp_node. */ |
225 | /* Mount failed, drop reference to mp_node. */ |
195 | if (mp_node) |
226 | if (mp_node) |
Line 214... | Line 245... | ||
214 | 245 | ||
215 | /* Acknowledge that we know fs_name. */ |
246 | /* Acknowledge that we know fs_name. */ |
216 | ipc_answer_0(pr->callid, EOK); |
247 | ipc_answer_0(pr->callid, EOK); |
217 | 248 | ||
218 | /* Do the mount */ |
249 | /* Do the mount */ |
219 | vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp); |
250 | vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp, |
- | 251 | pr->opts); |
|
220 | 252 | ||
221 | free(pr->fs_name); |
253 | free(pr->fs_name); |
222 | free(pr->mp); |
254 | free(pr->mp); |
- | 255 | free(pr->opts); |
|
223 | list_remove(cur); |
256 | list_remove(cur); |
224 | free(pr); |
257 | free(pr); |
225 | goto loop; |
258 | goto loop; |
226 | } |
259 | } |
227 | } |
260 | } |
Line 270... | Line 303... | ||
270 | } |
303 | } |
271 | 304 | ||
272 | /* Deliver the mount point. */ |
305 | /* Deliver the mount point. */ |
273 | ipcarg_t retval = ipc_data_write_finalize(callid, mp, size); |
306 | ipcarg_t retval = ipc_data_write_finalize(callid, mp, size); |
274 | if (retval != EOK) { |
307 | if (retval != EOK) { |
275 | ipc_answer_0(rid, EREFUSED); |
308 | ipc_answer_0(rid, retval); |
276 | free(mp); |
309 | free(mp); |
277 | return; |
310 | return; |
278 | } |
311 | } |
279 | mp[size] = '\0'; |
312 | mp[size] = '\0'; |
280 | 313 | ||
- | 314 | /* Now we expect to receive the mount options. */ |
|
- | 315 | if (!ipc_data_write_receive(&callid, &size)) { |
|
- | 316 | ipc_answer_0(callid, EINVAL); |
|
- | 317 | ipc_answer_0(rid, EINVAL); |
|
- | 318 | free(mp); |
|
- | 319 | return; |
|
- | 320 | } |
|
- | 321 | ||
- | 322 | /* Check the offered options size. */ |
|
- | 323 | if (size < 0 || size > MAX_MNTOPTS_LEN) { |
|
- | 324 | ipc_answer_0(callid, EINVAL); |
|
- | 325 | ipc_answer_0(rid, EINVAL); |
|
- | 326 | free(mp); |
|
- | 327 | return; |
|
- | 328 | } |
|
- | 329 | ||
- | 330 | /* Allocate buffer for the mount options. */ |
|
- | 331 | char *opts = (char *) malloc(size + 1); |
|
- | 332 | if (!opts) { |
|
- | 333 | ipc_answer_0(callid, ENOMEM); |
|
- | 334 | ipc_answer_0(rid, ENOMEM); |
|
- | 335 | free(mp); |
|
- | 336 | return; |
|
- | 337 | } |
|
- | 338 | ||
- | 339 | /* Deliver the mount options. */ |
|
- | 340 | retval = ipc_data_write_finalize(callid, opts, size); |
|
- | 341 | if (retval != EOK) { |
|
- | 342 | ipc_answer_0(rid, retval); |
|
- | 343 | free(mp); |
|
- | 344 | free(opts); |
|
- | 345 | return; |
|
- | 346 | } |
|
- | 347 | opts[size] = '\0'; |
|
- | 348 | ||
281 | /* |
349 | /* |
282 | * Now, we expect the client to send us data with the name of the file |
350 | * Now, we expect the client to send us data with the name of the file |
283 | * system. |
351 | * system. |
284 | */ |
352 | */ |
285 | if (!ipc_data_write_receive(&callid, &size)) { |
353 | if (!ipc_data_write_receive(&callid, &size)) { |
286 | ipc_answer_0(callid, EINVAL); |
354 | ipc_answer_0(callid, EINVAL); |
287 | ipc_answer_0(rid, EINVAL); |
355 | ipc_answer_0(rid, EINVAL); |
288 | free(mp); |
356 | free(mp); |
- | 357 | free(opts); |
|
289 | return; |
358 | return; |
290 | } |
359 | } |
291 | 360 | ||
292 | /* |
361 | /* |
293 | * Don't receive more than is necessary for storing a full file system |
362 | * Don't receive more than is necessary for storing a full file system |
Line 295... | Line 364... | ||
295 | */ |
364 | */ |
296 | if ((size < 1) || (size > FS_NAME_MAXLEN)) { |
365 | if ((size < 1) || (size > FS_NAME_MAXLEN)) { |
297 | ipc_answer_0(callid, EINVAL); |
366 | ipc_answer_0(callid, EINVAL); |
298 | ipc_answer_0(rid, EINVAL); |
367 | ipc_answer_0(rid, EINVAL); |
299 | free(mp); |
368 | free(mp); |
- | 369 | free(opts); |
|
300 | return; |
370 | return; |
301 | } |
371 | } |
302 | 372 | ||
303 | /* |
373 | /* |
304 | * Allocate buffer for file system name. |
374 | * Allocate buffer for file system name. |
305 | */ |
375 | */ |
306 | char *fs_name = (char *) malloc(size + 1); |
376 | char *fs_name = (char *) malloc(size + 1); |
307 | if (fs_name == NULL) { |
377 | if (fs_name == NULL) { |
308 | ipc_answer_0(callid, ENOMEM); |
378 | ipc_answer_0(callid, ENOMEM); |
309 | ipc_answer_0(rid, EREFUSED); |
379 | ipc_answer_0(rid, ENOMEM); |
310 | free(mp); |
380 | free(mp); |
- | 381 | free(opts); |
|
311 | return; |
382 | return; |
312 | } |
383 | } |
313 | 384 | ||
314 | /* Deliver the file system name. */ |
385 | /* Deliver the file system name. */ |
315 | retval = ipc_data_write_finalize(callid, fs_name, size); |
386 | retval = ipc_data_write_finalize(callid, fs_name, size); |
316 | if (retval != EOK) { |
387 | if (retval != EOK) { |
317 | ipc_answer_0(rid, EREFUSED); |
388 | ipc_answer_0(rid, retval); |
318 | free(mp); |
389 | free(mp); |
- | 390 | free(opts); |
|
319 | free(fs_name); |
391 | free(fs_name); |
320 | return; |
392 | return; |
321 | } |
393 | } |
322 | fs_name[size] = '\0'; |
394 | fs_name[size] = '\0'; |
- | 395 | ||
- | 396 | /* |
|
- | 397 | * Wait for IPC_M_PING so that we can return an error if we don't know |
|
- | 398 | * fs_name. |
|
- | 399 | */ |
|
- | 400 | ipc_call_t data; |
|
- | 401 | callid = async_get_call(&data); |
|
- | 402 | if (IPC_GET_METHOD(data) != IPC_M_PING) { |
|
- | 403 | ipc_answer_0(callid, ENOTSUP); |
|
- | 404 | ipc_answer_0(rid, ENOTSUP); |
|
- | 405 | free(mp); |
|
- | 406 | free(opts); |
|
- | 407 | free(fs_name); |
|
- | 408 | return; |
|
323 | 409 | } |
|
- | 410 | ||
324 | /* |
411 | /* |
325 | * Check if we know a file system with the same name as is in fs_name. |
412 | * Check if we know a file system with the same name as is in fs_name. |
326 | * This will also give us its file system handle. |
413 | * This will also give us its file system handle. |
327 | */ |
414 | */ |
328 | fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); |
415 | fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); |
329 | if (!fs_handle) { |
416 | if (!fs_handle) { |
330 | if (flags & IPC_FLAG_BLOCKING) { |
417 | if (flags & IPC_FLAG_BLOCKING) { |
- | 418 | pending_req_t *pr; |
|
- | 419 | ||
331 | /* Blocking mount, add to pending list */ |
420 | /* Blocking mount, add to pending list */ |
332 | pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t)); |
421 | pr = (pending_req_t *) malloc(sizeof(pending_req_t)); |
333 | if (!pr) { |
422 | if (!pr) { |
334 | ipc_answer_0(callid, ENOMEM); |
423 | ipc_answer_0(callid, ENOMEM); |
335 | ipc_answer_0(rid, ENOMEM); |
424 | ipc_answer_0(rid, ENOMEM); |
336 | free(mp); |
425 | free(mp); |
337 | free(fs_name); |
426 | free(fs_name); |
- | 427 | free(opts); |
|
338 | return; |
428 | return; |
339 | } |
429 | } |
340 | 430 | ||
341 | pr->fs_name = fs_name; |
431 | pr->fs_name = fs_name; |
342 | pr->mp = mp; |
432 | pr->mp = mp; |
- | 433 | pr->opts = opts; |
|
343 | pr->callid = callid; |
434 | pr->callid = callid; |
344 | pr->rid = rid; |
435 | pr->rid = rid; |
345 | pr->dev_handle = dev_handle; |
436 | pr->dev_handle = dev_handle; |
346 | link_initialize(&pr->link); |
437 | link_initialize(&pr->link); |
347 | list_append(&pr->link, &pending_req); |
438 | list_append(&pr->link, &pending_req); |
Line 350... | Line 441... | ||
350 | 441 | ||
351 | ipc_answer_0(callid, ENOENT); |
442 | ipc_answer_0(callid, ENOENT); |
352 | ipc_answer_0(rid, ENOENT); |
443 | ipc_answer_0(rid, ENOENT); |
353 | free(mp); |
444 | free(mp); |
354 | free(fs_name); |
445 | free(fs_name); |
- | 446 | free(opts); |
|
355 | return; |
447 | return; |
356 | } |
448 | } |
357 | 449 | ||
358 | /* Acknowledge that we know fs_name. */ |
450 | /* Acknowledge that we know fs_name. */ |
359 | ipc_answer_0(callid, EOK); |
451 | ipc_answer_0(callid, EOK); |
360 | 452 | ||
361 | /* Do the mount */ |
453 | /* Do the mount */ |
362 | vfs_mount_internal(rid, dev_handle, fs_handle, mp); |
454 | vfs_mount_internal(rid, dev_handle, fs_handle, mp, opts); |
363 | free(mp); |
455 | free(mp); |
364 | free(fs_name); |
456 | free(fs_name); |
- | 457 | free(opts); |
|
365 | } |
458 | } |
366 | 459 | ||
367 | void vfs_open(ipc_callid_t rid, ipc_call_t *request) |
460 | void vfs_open(ipc_callid_t rid, ipc_call_t *request) |
368 | { |
461 | { |
369 | if (!vfs_files_init()) { |
462 | if (!vfs_files_init()) { |
Line 802... | Line 895... | ||
802 | ipc_answer_0(rid, EOK); |
895 | ipc_answer_0(rid, EOK); |
803 | } |
896 | } |
804 | 897 | ||
805 | void vfs_rename(ipc_callid_t rid, ipc_call_t *request) |
898 | void vfs_rename(ipc_callid_t rid, ipc_call_t *request) |
806 | { |
899 | { |
807 | size_t len; |
900 | size_t olen, nlen; |
808 | ipc_callid_t callid; |
901 | ipc_callid_t callid; |
809 | int rc; |
902 | int rc; |
810 | 903 | ||
811 | /* Retrieve the old path. */ |
904 | /* Retrieve the old path. */ |
812 | if (!ipc_data_write_receive(&callid, &len)) { |
905 | if (!ipc_data_write_receive(&callid, &olen)) { |
813 | ipc_answer_0(callid, EINVAL); |
906 | ipc_answer_0(callid, EINVAL); |
814 | ipc_answer_0(rid, EINVAL); |
907 | ipc_answer_0(rid, EINVAL); |
815 | return; |
908 | return; |
816 | } |
909 | } |
817 | char *old = malloc(len + 1); |
910 | char *old = malloc(olen + 1); |
818 | if (!old) { |
911 | if (!old) { |
819 | ipc_answer_0(callid, ENOMEM); |
912 | ipc_answer_0(callid, ENOMEM); |
820 | ipc_answer_0(rid, ENOMEM); |
913 | ipc_answer_0(rid, ENOMEM); |
821 | return; |
914 | return; |
822 | } |
915 | } |
823 | if ((rc = ipc_data_write_finalize(callid, old, len))) { |
916 | if ((rc = ipc_data_write_finalize(callid, old, olen))) { |
824 | ipc_answer_0(rid, rc); |
917 | ipc_answer_0(rid, rc); |
825 | free(old); |
918 | free(old); |
826 | return; |
919 | return; |
827 | } |
920 | } |
828 | old[len] = '\0'; |
921 | old[olen] = '\0'; |
829 | 922 | ||
830 | /* Retrieve the new path. */ |
923 | /* Retrieve the new path. */ |
831 | if (!ipc_data_write_receive(&callid, &len)) { |
924 | if (!ipc_data_write_receive(&callid, &nlen)) { |
832 | ipc_answer_0(callid, EINVAL); |
925 | ipc_answer_0(callid, EINVAL); |
833 | ipc_answer_0(rid, EINVAL); |
926 | ipc_answer_0(rid, EINVAL); |
834 | free(old); |
927 | free(old); |
835 | return; |
928 | return; |
836 | } |
929 | } |
837 | char *new = malloc(len + 1); |
930 | char *new = malloc(nlen + 1); |
838 | if (!new) { |
931 | if (!new) { |
839 | ipc_answer_0(callid, ENOMEM); |
932 | ipc_answer_0(callid, ENOMEM); |
840 | ipc_answer_0(rid, ENOMEM); |
933 | ipc_answer_0(rid, ENOMEM); |
841 | free(old); |
934 | free(old); |
842 | return; |
935 | return; |
843 | } |
936 | } |
844 | if ((rc = ipc_data_write_finalize(callid, new, len))) { |
937 | if ((rc = ipc_data_write_finalize(callid, new, nlen))) { |
845 | ipc_answer_0(rid, rc); |
938 | ipc_answer_0(rid, rc); |
846 | free(old); |
939 | free(old); |
847 | free(new); |
940 | free(new); |
848 | return; |
941 | return; |
849 | } |
942 | } |
850 | new[len] = '\0'; |
943 | new[nlen] = '\0'; |
851 | 944 | ||
852 | char *oldc = canonify(old, &len); |
945 | char *oldc = canonify(old, &olen); |
853 | char *newc = canonify(new, NULL); |
946 | char *newc = canonify(new, &nlen); |
854 | if (!oldc || !newc) { |
947 | if (!oldc || !newc) { |
855 | ipc_answer_0(rid, EINVAL); |
948 | ipc_answer_0(rid, EINVAL); |
856 | free(old); |
949 | free(old); |
857 | free(new); |
950 | free(new); |
858 | return; |
951 | return; |
859 | } |
952 | } |
- | 953 | oldc[olen] = '\0'; |
|
- | 954 | newc[nlen] = '\0'; |
|
860 | if (!strncmp(newc, oldc, len)) { |
955 | if (!str_lcmp(newc, oldc, str_length(oldc))) { |
861 | /* oldc is a prefix of newc */ |
956 | /* oldc is a prefix of newc */ |
862 | ipc_answer_0(rid, EINVAL); |
957 | ipc_answer_0(rid, EINVAL); |
863 | free(old); |
958 | free(old); |
864 | free(new); |
959 | free(new); |
865 | return; |
960 | return; |