Rev 4419 | Rev 4439 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4419 | Rev 4420 | ||
|---|---|---|---|
| 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_lookup_res_t mr_res; |
|
| 87 | vfs_node_t *mp_node = NULL; |
88 | vfs_node_t *mp_node = NULL; |
| - | 89 | vfs_node_t *mr_node; |
|
| - | 90 | fs_index_t rindex; |
|
| - | 91 | size_t rsize; |
|
| - | 92 | unsigned rlnkcnt; |
|
| 88 | int rc; |
93 | ipcarg_t rc; |
| 89 | int phone; |
94 | int phone; |
| - | 95 | aid_t msg; |
|
| - | 96 | ipc_call_t answer; |
|
| - | 97 | ||
| - | 98 | ||
| - | 99 | /* Resolve the path to the mountpoint. */ |
|
| 90 | futex_down(&rootfs_futex); |
100 | futex_down(&rootfs_futex); |
| 91 | if (rootfs.fs_handle) { |
101 | if (rootfs.fs_handle) { |
| 92 | /* We already have the root FS. */ |
102 | /* We already have the root FS. */ |
| 93 | rwlock_write_lock(&namespace_rwlock); |
103 | rwlock_write_lock(&namespace_rwlock); |
| 94 | if (str_cmp(mp, "/") == 0) { |
104 | if (str_cmp(mp, "/") == 0) { |
| Line 123... | Line 133... | ||
| 123 | */ |
133 | */ |
| 124 | rwlock_write_unlock(&namespace_rwlock); |
134 | rwlock_write_unlock(&namespace_rwlock); |
| 125 | } else { |
135 | } else { |
| 126 | /* We still don't have the root file system mounted. */ |
136 | /* We still don't have the root file system mounted. */ |
| 127 | if (str_cmp(mp, "/") == 0) { |
137 | if (str_cmp(mp, "/") == 0) { |
| 128 | vfs_lookup_res_t mr_res; |
- | |
| 129 | vfs_node_t *mr_node; |
- | |
| 130 | ipcarg_t rindex; |
- | |
| 131 | ipcarg_t rsize; |
- | |
| 132 | ipcarg_t rlnkcnt; |
- | |
| 133 | - | ||
| 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 180... | Line 199... | ||
| 180 | /* |
199 | /* |
| 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 | ||
| - | 204 | int mountee_phone = vfs_grab_phone(fs_handle); |
|
| - | 205 | assert(mountee_phone >= 0); |
|
| - | 206 | vfs_release_phone(mountee_phone); |
|
| - | 207 | ||
| 185 | phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
208 | phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
| 186 | rc = async_req_4_0(phone, VFS_MOUNT, |
209 | msg = async_send_4(phone, VFS_MOUNT, |
| 187 | (ipcarg_t) mp_res.triplet.dev_handle, |
210 | (ipcarg_t) mp_res.triplet.dev_handle, |
| 188 | (ipcarg_t) mp_res.triplet.index, |
211 | (ipcarg_t) mp_res.triplet.index, |
| 189 | (ipcarg_t) fs_handle, |
212 | (ipcarg_t) fs_handle, |
| 190 | (ipcarg_t) dev_handle); |
213 | (ipcarg_t) dev_handle, &answer); |
| - | 214 | ||
| - | 215 | /* send connection */ |
|
| - | 216 | rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone); |
|
| - | 217 | if (rc != EOK) { |
|
| - | 218 | async_wait_for(msg, NULL); |
|
| - | 219 | vfs_release_phone(phone); |
|
| - | 220 | /* Mount failed, drop reference to mp_node. */ |
|
| - | 221 | if (mp_node) |
|
| - | 222 | vfs_node_put(mp_node); |
|
| - | 223 | ipc_answer_0(rid, rc); |
|
| - | 224 | return; |
|
| - | 225 | } |
|
| - | 226 | ||
| - | 227 | /* send the mount options */ |
|
| - | 228 | rc = ipc_data_write_start(phone, (void *)opts, str_size(opts)); |
|
| - | 229 | if (rc != EOK) { |
|
| - | 230 | async_wait_for(msg, NULL); |
|
| - | 231 | vfs_release_phone(phone); |
|
| - | 232 | /* Mount failed, drop reference to mp_node. */ |
|
| - | 233 | if (mp_node) |
|
| - | 234 | vfs_node_put(mp_node); |
|
| - | 235 | ipc_answer_0(rid, rc); |
|
| - | 236 | return; |
|
| - | 237 | } |
|
| - | 238 | async_wait_for(msg, &rc); |
|
| 191 | vfs_release_phone(phone); |
239 | vfs_release_phone(phone); |
| 192 | 240 | ||
| 193 | if (rc != EOK) { |
241 | if (rc != EOK) { |
| 194 | /* Mount failed, drop reference to mp_node. */ |
242 | /* Mount failed, drop reference to mp_node. */ |
| 195 | if (mp_node) |
243 | if (mp_node) |
| 196 | vfs_node_put(mp_node); |
244 | vfs_node_put(mp_node); |
| 197 | } |
245 | } |
| 198 | 246 | ||
| - | 247 | rindex = (fs_index_t) IPC_GET_ARG1(answer); |
|
| - | 248 | rsize = (size_t) IPC_GET_ARG2(answer); |
|
| - | 249 | rlnkcnt = (unsigned) IPC_GET_ARG3(answer); |
|
| - | 250 | ||
| - | 251 | mr_res.triplet.fs_handle = fs_handle; |
|
| - | 252 | mr_res.triplet.dev_handle = dev_handle; |
|
| - | 253 | mr_res.triplet.index = rindex; |
|
| - | 254 | mr_res.size = rsize; |
|
| - | 255 | mr_res.lnkcnt = rlnkcnt; |
|
| - | 256 | mr_res.type = VFS_NODE_DIRECTORY; |
|
| - | 257 | ||
| - | 258 | /* Add reference to the mounted root. */ |
|
| - | 259 | mr_node = vfs_node_get(&mr_res); |
|
| - | 260 | assert(mr_node); |
|
| - | 261 | ||
| 199 | ipc_answer_0(rid, rc); |
262 | ipc_answer_0(rid, rc); |
| 200 | } |
263 | } |
| 201 | 264 | ||
| 202 | /** Process pending mount requests */ |
265 | /** Process pending mount requests */ |
| 203 | void vfs_process_pending_mount() |
266 | void vfs_process_pending_mount() |
| Line 214... | Line 277... | ||
| 214 | 277 | ||
| 215 | /* Acknowledge that we know fs_name. */ |
278 | /* Acknowledge that we know fs_name. */ |
| 216 | ipc_answer_0(pr->callid, EOK); |
279 | ipc_answer_0(pr->callid, EOK); |
| 217 | 280 | ||
| 218 | /* Do the mount */ |
281 | /* Do the mount */ |
| 219 | vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp); |
282 | vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp, |
| - | 283 | pr->opts); |
|
| 220 | 284 | ||
| 221 | free(pr->fs_name); |
285 | free(pr->fs_name); |
| 222 | free(pr->mp); |
286 | free(pr->mp); |
| - | 287 | free(pr->opts); |
|
| 223 | list_remove(cur); |
288 | list_remove(cur); |
| 224 | free(pr); |
289 | free(pr); |
| 225 | goto loop; |
290 | goto loop; |
| 226 | } |
291 | } |
| 227 | } |
292 | } |
| Line 270... | Line 335... | ||
| 270 | } |
335 | } |
| 271 | 336 | ||
| 272 | /* Deliver the mount point. */ |
337 | /* Deliver the mount point. */ |
| 273 | ipcarg_t retval = ipc_data_write_finalize(callid, mp, size); |
338 | ipcarg_t retval = ipc_data_write_finalize(callid, mp, size); |
| 274 | if (retval != EOK) { |
339 | if (retval != EOK) { |
| 275 | ipc_answer_0(rid, EREFUSED); |
340 | ipc_answer_0(rid, retval); |
| 276 | free(mp); |
341 | free(mp); |
| 277 | return; |
342 | return; |
| 278 | } |
343 | } |
| 279 | mp[size] = '\0'; |
344 | mp[size] = '\0'; |
| 280 | 345 | ||
| - | 346 | /* Now we expect to receive the mount options. */ |
|
| - | 347 | if (!ipc_data_write_receive(&callid, &size)) { |
|
| - | 348 | ipc_answer_0(callid, EINVAL); |
|
| - | 349 | ipc_answer_0(rid, EINVAL); |
|
| - | 350 | free(mp); |
|
| - | 351 | return; |
|
| - | 352 | } |
|
| - | 353 | ||
| - | 354 | /* Check the offered options size. */ |
|
| - | 355 | if (size < 0 || size > MAX_MNTOPTS_LEN) { |
|
| - | 356 | ipc_answer_0(callid, EINVAL); |
|
| - | 357 | ipc_answer_0(rid, EINVAL); |
|
| - | 358 | free(mp); |
|
| - | 359 | return; |
|
| - | 360 | } |
|
| - | 361 | ||
| - | 362 | /* Allocate buffer for the mount options. */ |
|
| - | 363 | char *opts = (char *) malloc(size + 1); |
|
| - | 364 | if (!opts) { |
|
| - | 365 | ipc_answer_0(callid, ENOMEM); |
|
| - | 366 | ipc_answer_0(rid, ENOMEM); |
|
| - | 367 | free(mp); |
|
| - | 368 | return; |
|
| - | 369 | } |
|
| - | 370 | ||
| - | 371 | /* Deliver the mount options. */ |
|
| - | 372 | retval = ipc_data_write_finalize(callid, opts, size); |
|
| - | 373 | if (retval != EOK) { |
|
| - | 374 | ipc_answer_0(rid, retval); |
|
| - | 375 | free(mp); |
|
| - | 376 | free(opts); |
|
| - | 377 | return; |
|
| - | 378 | } |
|
| - | 379 | opts[size] = '\0'; |
|
| - | 380 | ||
| 281 | /* |
381 | /* |
| 282 | * Now, we expect the client to send us data with the name of the file |
382 | * Now, we expect the client to send us data with the name of the file |
| 283 | * system. |
383 | * system. |
| 284 | */ |
384 | */ |
| 285 | if (!ipc_data_write_receive(&callid, &size)) { |
385 | if (!ipc_data_write_receive(&callid, &size)) { |
| 286 | ipc_answer_0(callid, EINVAL); |
386 | ipc_answer_0(callid, EINVAL); |
| 287 | ipc_answer_0(rid, EINVAL); |
387 | ipc_answer_0(rid, EINVAL); |
| 288 | free(mp); |
388 | free(mp); |
| - | 389 | free(opts); |
|
| 289 | return; |
390 | return; |
| 290 | } |
391 | } |
| 291 | 392 | ||
| 292 | /* |
393 | /* |
| 293 | * Don't receive more than is necessary for storing a full file system |
394 | * Don't receive more than is necessary for storing a full file system |
| Line 295... | Line 396... | ||
| 295 | */ |
396 | */ |
| 296 | if ((size < 1) || (size > FS_NAME_MAXLEN)) { |
397 | if ((size < 1) || (size > FS_NAME_MAXLEN)) { |
| 297 | ipc_answer_0(callid, EINVAL); |
398 | ipc_answer_0(callid, EINVAL); |
| 298 | ipc_answer_0(rid, EINVAL); |
399 | ipc_answer_0(rid, EINVAL); |
| 299 | free(mp); |
400 | free(mp); |
| - | 401 | free(opts); |
|
| 300 | return; |
402 | return; |
| 301 | } |
403 | } |
| 302 | 404 | ||
| 303 | /* |
405 | /* |
| 304 | * Allocate buffer for file system name. |
406 | * Allocate buffer for file system name. |
| 305 | */ |
407 | */ |
| 306 | char *fs_name = (char *) malloc(size + 1); |
408 | char *fs_name = (char *) malloc(size + 1); |
| 307 | if (fs_name == NULL) { |
409 | if (fs_name == NULL) { |
| 308 | ipc_answer_0(callid, ENOMEM); |
410 | ipc_answer_0(callid, ENOMEM); |
| 309 | ipc_answer_0(rid, EREFUSED); |
411 | ipc_answer_0(rid, ENOMEM); |
| 310 | free(mp); |
412 | free(mp); |
| - | 413 | free(opts); |
|
| 311 | return; |
414 | return; |
| 312 | } |
415 | } |
| 313 | 416 | ||
| 314 | /* Deliver the file system name. */ |
417 | /* Deliver the file system name. */ |
| 315 | retval = ipc_data_write_finalize(callid, fs_name, size); |
418 | retval = ipc_data_write_finalize(callid, fs_name, size); |
| 316 | if (retval != EOK) { |
419 | if (retval != EOK) { |
| 317 | ipc_answer_0(rid, EREFUSED); |
420 | ipc_answer_0(rid, retval); |
| 318 | free(mp); |
421 | free(mp); |
| - | 422 | free(opts); |
|
| 319 | free(fs_name); |
423 | free(fs_name); |
| 320 | return; |
424 | return; |
| 321 | } |
425 | } |
| 322 | fs_name[size] = '\0'; |
426 | fs_name[size] = '\0'; |
| - | 427 | ||
| - | 428 | /* |
|
| - | 429 | * Wait for IPC_M_PING so that we can return an error if we don't know |
|
| - | 430 | * fs_name. |
|
| - | 431 | */ |
|
| - | 432 | ipc_call_t data; |
|
| - | 433 | callid = async_get_call(&data); |
|
| - | 434 | if (IPC_GET_METHOD(data) != IPC_M_PING) { |
|
| - | 435 | ipc_answer_0(callid, ENOTSUP); |
|
| - | 436 | ipc_answer_0(rid, ENOTSUP); |
|
| - | 437 | free(mp); |
|
| - | 438 | free(opts); |
|
| - | 439 | free(fs_name); |
|
| - | 440 | return; |
|
| 323 | 441 | } |
|
| - | 442 | ||
| 324 | /* |
443 | /* |
| 325 | * Check if we know a file system with the same name as is in fs_name. |
444 | * 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. |
445 | * This will also give us its file system handle. |
| 327 | */ |
446 | */ |
| 328 | fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); |
447 | fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); |
| 329 | if (!fs_handle) { |
448 | if (!fs_handle) { |
| 330 | if (flags & IPC_FLAG_BLOCKING) { |
449 | if (flags & IPC_FLAG_BLOCKING) { |
| - | 450 | pending_req_t *pr; |
|
| - | 451 | ||
| 331 | /* Blocking mount, add to pending list */ |
452 | /* Blocking mount, add to pending list */ |
| 332 | pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t)); |
453 | pr = (pending_req_t *) malloc(sizeof(pending_req_t)); |
| 333 | if (!pr) { |
454 | if (!pr) { |
| 334 | ipc_answer_0(callid, ENOMEM); |
455 | ipc_answer_0(callid, ENOMEM); |
| 335 | ipc_answer_0(rid, ENOMEM); |
456 | ipc_answer_0(rid, ENOMEM); |
| 336 | free(mp); |
457 | free(mp); |
| 337 | free(fs_name); |
458 | free(fs_name); |
| - | 459 | free(opts); |
|
| 338 | return; |
460 | return; |
| 339 | } |
461 | } |
| 340 | 462 | ||
| 341 | pr->fs_name = fs_name; |
463 | pr->fs_name = fs_name; |
| 342 | pr->mp = mp; |
464 | pr->mp = mp; |
| - | 465 | pr->opts = opts; |
|
| 343 | pr->callid = callid; |
466 | pr->callid = callid; |
| 344 | pr->rid = rid; |
467 | pr->rid = rid; |
| 345 | pr->dev_handle = dev_handle; |
468 | pr->dev_handle = dev_handle; |
| 346 | link_initialize(&pr->link); |
469 | link_initialize(&pr->link); |
| 347 | list_append(&pr->link, &pending_req); |
470 | list_append(&pr->link, &pending_req); |
| Line 350... | Line 473... | ||
| 350 | 473 | ||
| 351 | ipc_answer_0(callid, ENOENT); |
474 | ipc_answer_0(callid, ENOENT); |
| 352 | ipc_answer_0(rid, ENOENT); |
475 | ipc_answer_0(rid, ENOENT); |
| 353 | free(mp); |
476 | free(mp); |
| 354 | free(fs_name); |
477 | free(fs_name); |
| - | 478 | free(opts); |
|
| 355 | return; |
479 | return; |
| 356 | } |
480 | } |
| 357 | 481 | ||
| 358 | /* Acknowledge that we know fs_name. */ |
482 | /* Acknowledge that we know fs_name. */ |
| 359 | ipc_answer_0(callid, EOK); |
483 | ipc_answer_0(callid, EOK); |
| 360 | 484 | ||
| 361 | /* Do the mount */ |
485 | /* Do the mount */ |
| 362 | vfs_mount_internal(rid, dev_handle, fs_handle, mp); |
486 | vfs_mount_internal(rid, dev_handle, fs_handle, mp, opts); |
| 363 | free(mp); |
487 | free(mp); |
| 364 | free(fs_name); |
488 | free(fs_name); |
| - | 489 | free(opts); |
|
| 365 | } |
490 | } |
| 366 | 491 | ||
| 367 | void vfs_open(ipc_callid_t rid, ipc_call_t *request) |
492 | void vfs_open(ipc_callid_t rid, ipc_call_t *request) |
| 368 | { |
493 | { |
| 369 | if (!vfs_files_init()) { |
494 | if (!vfs_files_init()) { |
| Line 857... | Line 982... | ||
| 857 | free(new); |
982 | free(new); |
| 858 | return; |
983 | return; |
| 859 | } |
984 | } |
| 860 | oldc[olen] = '\0'; |
985 | oldc[olen] = '\0'; |
| 861 | newc[nlen] = '\0'; |
986 | newc[nlen] = '\0'; |
| 862 | if (!str_lcmp(newc, oldc, str_length(oldc))) { |
987 | if ((!str_lcmp(newc, oldc, str_length(oldc))) && |
| - | 988 | ((newc[str_length(oldc)] == '/') || |
|
| - | 989 | (str_length(oldc) == 1) || |
|
| - | 990 | (str_length(oldc) == str_length(newc)))) { |
|
| - | 991 | /* |
|
| 863 | /* oldc is a prefix of newc */ |
992 | * oldc is a prefix of newc and either |
| - | 993 | * - newc continues with a / where oldc ends, or |
|
| - | 994 | * - oldc was / itself, or |
|
| - | 995 | * - oldc and newc are equal. |
|
| - | 996 | */ |
|
| 864 | ipc_answer_0(rid, EINVAL); |
997 | ipc_answer_0(rid, EINVAL); |
| 865 | free(old); |
998 | free(old); |
| 866 | free(new); |
999 | free(new); |
| 867 | return; |
1000 | return; |
| 868 | } |
1001 | } |
| Line 886... | Line 1019... | ||
| 886 | ipc_answer_0(rid, ENOMEM); |
1019 | ipc_answer_0(rid, ENOMEM); |
| 887 | free(old); |
1020 | free(old); |
| 888 | free(new); |
1021 | free(new); |
| 889 | return; |
1022 | return; |
| 890 | } |
1023 | } |
| - | 1024 | /* Determine the path to the parent of the node with the new name. */ |
|
| - | 1025 | char *parentc = str_dup(newc); |
|
| - | 1026 | if (!parentc) { |
|
| - | 1027 | rwlock_write_unlock(&namespace_rwlock); |
|
| - | 1028 | ipc_answer_0(rid, rc); |
|
| - | 1029 | free(old); |
|
| - | 1030 | free(new); |
|
| - | 1031 | return; |
|
| - | 1032 | } |
|
| - | 1033 | char *lastsl = str_rchr(parentc + 1, L'/'); |
|
| - | 1034 | if (lastsl) |
|
| - | 1035 | *lastsl = '\0'; |
|
| - | 1036 | else |
|
| - | 1037 | parentc[1] = '\0'; |
|
| 891 | /* Lookup parent of the new file name. */ |
1038 | /* Lookup parent of the new file name. */ |
| 892 | rc = vfs_lookup_internal(newc, L_PARENT, &new_par_lr, NULL); |
1039 | rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL); |
| - | 1040 | free(parentc); /* not needed anymore */ |
|
| 893 | if (rc != EOK) { |
1041 | if (rc != EOK) { |
| 894 | rwlock_write_unlock(&namespace_rwlock); |
1042 | rwlock_write_unlock(&namespace_rwlock); |
| 895 | ipc_answer_0(rid, rc); |
1043 | ipc_answer_0(rid, rc); |
| 896 | free(old); |
1044 | free(old); |
| 897 | free(new); |
1045 | free(new); |