Changes in uspace/srv/vfs/vfs_ops.c [08232ee:ed903174] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/vfs/vfs_ops.c
r08232ee red903174 38 38 #include "vfs.h" 39 39 #include <ipc/ipc.h> 40 #include <macros.h> 41 #include <limits.h> 40 42 #include <async.h> 41 43 #include <errno.h> … … 53 55 54 56 /* Forward declarations of static functions. */ 55 static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, size_t);57 static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, aoff64_t); 56 58 57 59 /** … … 92 94 } 93 95 94 rc = vfs_lookup_internal(mp, L_ DIRECTORY, &mp_res, NULL);96 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL); 95 97 if (rc != EOK) { 96 98 /* The lookup failed for some reason. */ … … 266 268 267 269 /* We want the client to send us the mount point. */ 268 ipc_callid_t callid; 269 size_t size; 270 if (!async_data_write_receive(&callid, &size)) { 271 ipc_answer_0(callid, EINVAL); 272 ipc_answer_0(rid, EINVAL); 273 return; 274 } 275 276 /* Check whether size is reasonable wrt. the mount point. */ 277 if ((size < 1) || (size > MAX_PATH_LEN)) { 278 ipc_answer_0(callid, EINVAL); 279 ipc_answer_0(rid, EINVAL); 280 return; 281 } 282 283 /* Allocate buffer for the mount point data being received. */ 284 char *mp = malloc(size + 1); 285 if (!mp) { 286 ipc_answer_0(callid, ENOMEM); 287 ipc_answer_0(rid, ENOMEM); 288 return; 289 } 290 291 /* Deliver the mount point. */ 292 ipcarg_t retval = async_data_write_finalize(callid, mp, size); 293 if (retval != EOK) { 294 ipc_answer_0(rid, retval); 270 char *mp; 271 int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN, 272 0, NULL); 273 if (rc != EOK) { 274 ipc_answer_0(rid, rc); 275 return; 276 } 277 278 /* Now we expect to receive the mount options. */ 279 char *opts; 280 rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN, 281 0, NULL); 282 if (rc != EOK) { 295 283 free(mp); 296 return; 297 } 298 mp[size] = '\0'; 299 300 /* Now we expect to receive the mount options. */ 301 if (!async_data_write_receive(&callid, &size)) { 302 ipc_answer_0(callid, EINVAL); 303 ipc_answer_0(rid, EINVAL); 304 free(mp); 305 return; 306 } 307 308 /* Check the offered options size. */ 309 if (size > MAX_MNTOPTS_LEN) { 310 ipc_answer_0(callid, EINVAL); 311 ipc_answer_0(rid, EINVAL); 312 free(mp); 313 return; 314 } 315 316 /* Allocate buffer for the mount options. */ 317 char *opts = (char *) malloc(size + 1); 318 if (!opts) { 319 ipc_answer_0(callid, ENOMEM); 320 ipc_answer_0(rid, ENOMEM); 321 free(mp); 322 return; 323 } 324 325 /* Deliver the mount options. */ 326 retval = async_data_write_finalize(callid, opts, size); 327 if (retval != EOK) { 328 ipc_answer_0(rid, retval); 284 ipc_answer_0(rid, rc); 285 return; 286 } 287 288 /* 289 * Now, we expect the client to send us data with the name of the file 290 * system. 291 */ 292 char *fs_name; 293 rc = async_data_write_accept((void **) &fs_name, true, 0, FS_NAME_MAXLEN, 294 0, NULL); 295 if (rc != EOK) { 329 296 free(mp); 330 297 free(opts); 331 return; 332 } 333 opts[size] = '\0'; 334 335 /* 336 * Now, we expect the client to send us data with the name of the file 337 * system. 338 */ 339 if (!async_data_write_receive(&callid, &size)) { 340 ipc_answer_0(callid, EINVAL); 341 ipc_answer_0(rid, EINVAL); 342 free(mp); 343 free(opts); 344 return; 345 } 346 347 /* 348 * Don't receive more than is necessary for storing a full file system 349 * name. 350 */ 351 if ((size < 1) || (size > FS_NAME_MAXLEN)) { 352 ipc_answer_0(callid, EINVAL); 353 ipc_answer_0(rid, EINVAL); 354 free(mp); 355 free(opts); 356 return; 357 } 358 359 /* 360 * Allocate buffer for file system name. 361 */ 362 char *fs_name = (char *) malloc(size + 1); 363 if (fs_name == NULL) { 364 ipc_answer_0(callid, ENOMEM); 365 ipc_answer_0(rid, ENOMEM); 366 free(mp); 367 free(opts); 368 return; 369 } 370 371 /* Deliver the file system name. */ 372 retval = async_data_write_finalize(callid, fs_name, size); 373 if (retval != EOK) { 374 ipc_answer_0(rid, retval); 375 free(mp); 376 free(opts); 377 free(fs_name); 378 return; 379 } 380 fs_name[size] = '\0'; 381 298 ipc_answer_0(rid, rc); 299 return; 300 } 301 382 302 /* 383 303 * Wait for IPC_M_PING so that we can return an error if we don't know … … 385 305 */ 386 306 ipc_call_t data; 387 callid = async_get_call(&data);307 ipc_callid_t callid = async_get_call(&data); 388 308 if (IPC_GET_METHOD(data) != IPC_M_PING) { 389 309 ipc_answer_0(callid, ENOTSUP); … … 429 349 } 430 350 351 void vfs_unmount(ipc_callid_t rid, ipc_call_t *request) 352 { 353 int rc; 354 char *mp; 355 vfs_lookup_res_t mp_res; 356 vfs_lookup_res_t mr_res; 357 vfs_node_t *mr_node; 358 int phone; 359 360 /* 361 * Receive the mount point path. 362 */ 363 rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN, 364 0, NULL); 365 if (rc != EOK) 366 ipc_answer_0(rid, rc); 367 368 /* 369 * Taking the namespace lock will do two things for us. First, it will 370 * prevent races with other lookup operations. Second, it will stop new 371 * references to already existing VFS nodes and creation of new VFS 372 * nodes. This is because new references are added as a result of some 373 * lookup operation or at least of some operation which is protected by 374 * the namespace lock. 375 */ 376 fibril_rwlock_write_lock(&namespace_rwlock); 377 378 /* 379 * Lookup the mounted root and instantiate it. 380 */ 381 rc = vfs_lookup_internal(mp, L_ROOT, &mr_res, NULL); 382 if (rc != EOK) { 383 fibril_rwlock_write_unlock(&namespace_rwlock); 384 free(mp); 385 ipc_answer_0(rid, rc); 386 return; 387 } 388 mr_node = vfs_node_get(&mr_res); 389 if (!mr_node) { 390 fibril_rwlock_write_unlock(&namespace_rwlock); 391 free(mp); 392 ipc_answer_0(rid, ENOMEM); 393 return; 394 } 395 396 /* 397 * Count the total number of references for the mounted file system. We 398 * are expecting at least two. One which we got above and one which we 399 * got when the file system was mounted. If we find more, it means that 400 * the file system cannot be gracefully unmounted at the moment because 401 * someone is working with it. 402 */ 403 if (vfs_nodes_refcount_sum_get(mr_node->fs_handle, 404 mr_node->dev_handle) != 2) { 405 fibril_rwlock_write_unlock(&namespace_rwlock); 406 vfs_node_put(mr_node); 407 free(mp); 408 ipc_answer_0(rid, EBUSY); 409 return; 410 } 411 412 if (str_cmp(mp, "/") == 0) { 413 414 /* 415 * Unmounting the root file system. 416 * 417 * In this case, there is no mount point node and we send 418 * VFS_OUT_UNMOUNTED directly to the mounted file system. 419 */ 420 421 free(mp); 422 phone = vfs_grab_phone(mr_node->fs_handle); 423 rc = async_req_1_0(phone, VFS_OUT_UNMOUNTED, 424 mr_node->dev_handle); 425 vfs_release_phone(phone); 426 if (rc != EOK) { 427 fibril_rwlock_write_unlock(&namespace_rwlock); 428 vfs_node_put(mr_node); 429 ipc_answer_0(rid, rc); 430 return; 431 } 432 rootfs.fs_handle = 0; 433 rootfs.dev_handle = 0; 434 } else { 435 436 /* 437 * Unmounting a non-root file system. 438 * 439 * We have a regular mount point node representing the parent 440 * file system, so we delegate the operation to it. 441 */ 442 443 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL); 444 free(mp); 445 if (rc != EOK) { 446 fibril_rwlock_write_unlock(&namespace_rwlock); 447 vfs_node_put(mr_node); 448 ipc_answer_0(rid, rc); 449 return; 450 } 451 vfs_node_t *mp_node = vfs_node_get(&mp_res); 452 if (!mp_node) { 453 fibril_rwlock_write_unlock(&namespace_rwlock); 454 vfs_node_put(mr_node); 455 ipc_answer_0(rid, ENOMEM); 456 return; 457 } 458 459 phone = vfs_grab_phone(mp_node->fs_handle); 460 rc = async_req_2_0(phone, VFS_OUT_UNMOUNT, mp_node->dev_handle, 461 mp_node->index); 462 vfs_release_phone(phone); 463 if (rc != EOK) { 464 fibril_rwlock_write_unlock(&namespace_rwlock); 465 vfs_node_put(mp_node); 466 vfs_node_put(mr_node); 467 ipc_answer_0(rid, rc); 468 return; 469 } 470 471 /* Drop the reference we got above. */ 472 vfs_node_put(mp_node); 473 /* Drop the reference from when the file system was mounted. */ 474 vfs_node_put(mp_node); 475 } 476 477 478 /* 479 * All went well, the mounted file system was successfully unmounted. 480 * The only thing left is to forget the unmounted root VFS node. 481 */ 482 vfs_node_forget(mr_node); 483 484 fibril_rwlock_write_unlock(&namespace_rwlock); 485 ipc_answer_0(rid, EOK); 486 } 487 431 488 void vfs_open(ipc_callid_t rid, ipc_call_t *request) 432 489 { … … 447 504 int oflag = IPC_GET_ARG2(*request); 448 505 int mode = IPC_GET_ARG3(*request); 449 size_t len;450 506 451 507 /* Ignore mode for now. */ … … 454 510 /* 455 511 * Make sure that we are called with exactly one of L_FILE and 456 * L_DIRECTORY. Make sure that the user does not pass L_OPEN. 512 * L_DIRECTORY. Make sure that the user does not pass L_OPEN, 513 * L_ROOT or L_MP. 457 514 */ 458 515 if (((lflag & (L_FILE | L_DIRECTORY)) == 0) || 459 516 ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) || 460 ( (lflag & L_OPEN) != 0)) {517 (lflag & (L_OPEN | L_ROOT | L_MP))) { 461 518 ipc_answer_0(rid, EINVAL); 462 519 return; … … 468 525 lflag |= L_EXCLUSIVE; 469 526 470 ipc_callid_t callid; 471 if (!async_data_write_receive(&callid, &len)) { 472 ipc_answer_0(callid, EINVAL); 473 ipc_answer_0(rid, EINVAL); 474 return; 475 } 476 477 char *path = malloc(len + 1); 478 if (!path) { 479 ipc_answer_0(callid, ENOMEM); 480 ipc_answer_0(rid, ENOMEM); 481 return; 482 } 483 484 int rc; 485 if ((rc = async_data_write_finalize(callid, path, len))) { 486 ipc_answer_0(rid, rc); 487 free(path); 488 return; 489 } 490 path[len] = '\0'; 527 char *path; 528 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL); 529 if (rc != EOK) { 530 ipc_answer_0(rid, rc); 531 return; 532 } 491 533 492 534 /* … … 679 721 } 680 722 681 staticint vfs_close_internal(vfs_file_t *file)723 int vfs_close_internal(vfs_file_t *file) 682 724 { 683 725 /* … … 756 798 757 799 /* 758 * Now we need to receive a call with client's759 * IPC_M_DATA_READ/IPC_M_DATA_WRITE request.760 */761 ipc_callid_t callid;762 int res;763 if (read)764 res = async_data_read_receive(&callid, NULL);765 else766 res = async_data_write_receive(&callid, NULL);767 if (!res) {768 ipc_answer_0(callid, EINVAL);769 ipc_answer_0(rid, EINVAL);770 return;771 }772 773 /*774 800 * Lock the open file structure so that no other thread can manipulate 775 801 * the same open file at a time. … … 795 821 } 796 822 797 int fs_phone = vfs_grab_phone(file->node->fs_handle); 798 799 /* Make a VFS_READ/VFS_WRITE request at the destination FS server. */ 800 aid_t msg; 801 ipc_call_t answer; 802 if (!read && file->append) 803 file->pos = file->node->size; 804 msg = async_send_3(fs_phone, read ? VFS_OUT_READ : VFS_OUT_WRITE, 805 file->node->dev_handle, file->node->index, file->pos, &answer); 806 807 /* 808 * Forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the 823 int fs_phone = vfs_grab_phone(file->node->fs_handle); 824 825 /* 826 * Make a VFS_READ/VFS_WRITE request at the destination FS server 827 * and forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the 809 828 * destination FS server. The call will be routed as if sent by 810 829 * ourselves. Note that call arguments are immutable in this case so we 811 830 * don't have to bother. 812 831 */ 813 ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);814 815 /* Wait for reply from the FS server. */816 832 ipcarg_t rc; 817 async_wait_for(msg, &rc); 833 ipc_call_t answer; 834 if (read) { 835 if (file->append) 836 file->pos = file->node->size; 837 838 rc = async_data_read_forward_3_1(fs_phone, VFS_OUT_READ, 839 file->node->dev_handle, file->node->index, file->pos, 840 &answer); 841 } else { 842 rc = async_data_write_forward_3_1(fs_phone, VFS_OUT_WRITE, 843 file->node->dev_handle, file->node->index, file->pos, 844 &answer); 845 } 818 846 819 847 vfs_release_phone(fs_phone); 820 848 821 849 size_t bytes = IPC_GET_ARG1(answer); 822 850 823 851 if (file->node->type == VFS_NODE_DIRECTORY) 824 852 fibril_rwlock_read_unlock(&namespace_rwlock); … … 859 887 { 860 888 int fd = (int) IPC_GET_ARG1(*request); 861 off _t off = (off_t) IPC_GET_ARG2(*request);862 int whence = (int) IPC_GET_ARG3(*request);863 864 889 off64_t off = 890 (off64_t) MERGE_LOUP32(IPC_GET_ARG2(*request), IPC_GET_ARG3(*request)); 891 int whence = (int) IPC_GET_ARG4(*request); 892 865 893 /* Lookup the file structure corresponding to the file descriptor. */ 866 894 vfs_file_t *file = vfs_file_get(fd); … … 869 897 return; 870 898 } 871 872 off_t newpos; 899 873 900 fibril_mutex_lock(&file->lock); 874 if (whence == SEEK_SET) { 875 file->pos = off; 876 fibril_mutex_unlock(&file->lock); 877 ipc_answer_1(rid, EOK, off); 878 return; 879 } 880 if (whence == SEEK_CUR) { 881 if (file->pos + off < file->pos) { 901 902 off64_t newoff; 903 switch (whence) { 904 case SEEK_SET: 905 if (off >= 0) { 906 file->pos = (aoff64_t) off; 907 fibril_mutex_unlock(&file->lock); 908 ipc_answer_1(rid, EOK, off); 909 return; 910 } 911 break; 912 case SEEK_CUR: 913 if ((off >= 0) && (file->pos + off < file->pos)) { 914 fibril_mutex_unlock(&file->lock); 915 ipc_answer_0(rid, EOVERFLOW); 916 return; 917 } 918 919 if ((off < 0) && (file->pos < (aoff64_t) -off)) { 920 fibril_mutex_unlock(&file->lock); 921 ipc_answer_0(rid, EOVERFLOW); 922 return; 923 } 924 925 file->pos += off; 926 newoff = (file->pos > OFF64_MAX) ? OFF64_MAX : file->pos; 927 882 928 fibril_mutex_unlock(&file->lock); 883 ipc_answer_ 0(rid, EOVERFLOW);929 ipc_answer_2(rid, EOK, LOWER32(newoff), UPPER32(newoff)); 884 930 return; 885 } 886 file->pos += off; 887 newpos = file->pos; 888 fibril_mutex_unlock(&file->lock); 889 ipc_answer_1(rid, EOK, newpos); 890 return; 891 } 892 if (whence == SEEK_END) { 893 fibril_rwlock_read_lock(&file->node->contents_rwlock); 894 size_t size = file->node->size; 895 fibril_rwlock_read_unlock(&file->node->contents_rwlock); 896 if (size + off < size) { 931 case SEEK_END: 932 fibril_rwlock_read_lock(&file->node->contents_rwlock); 933 aoff64_t size = file->node->size; 934 935 if ((off >= 0) && (size + off < size)) { 936 fibril_rwlock_read_unlock(&file->node->contents_rwlock); 937 fibril_mutex_unlock(&file->lock); 938 ipc_answer_0(rid, EOVERFLOW); 939 return; 940 } 941 942 if ((off < 0) && (size < (aoff64_t) -off)) { 943 fibril_rwlock_read_unlock(&file->node->contents_rwlock); 944 fibril_mutex_unlock(&file->lock); 945 ipc_answer_0(rid, EOVERFLOW); 946 return; 947 } 948 949 file->pos = size + off; 950 newoff = (file->pos > OFF64_MAX) ? OFF64_MAX : file->pos; 951 952 fibril_rwlock_read_unlock(&file->node->contents_rwlock); 897 953 fibril_mutex_unlock(&file->lock); 898 ipc_answer_ 0(rid, EOVERFLOW);954 ipc_answer_2(rid, EOK, LOWER32(newoff), UPPER32(newoff)); 899 955 return; 900 } 901 newpos = size + off; 902 file->pos = newpos; 903 fibril_mutex_unlock(&file->lock); 904 ipc_answer_1(rid, EOK, newpos); 905 return; 906 } 956 } 957 907 958 fibril_mutex_unlock(&file->lock); 908 959 ipc_answer_0(rid, EINVAL); 909 960 } 910 961 911 int 912 vfs_truncate_internal(fs_handle_t fs_handle, dev_handle_t dev_handle, 913 fs_index_t index, size_t size) 962 int vfs_truncate_internal(fs_handle_t fs_handle, dev_handle_t dev_handle, 963 fs_index_t index, aoff64_t size) 914 964 { 915 965 ipcarg_t rc; … … 917 967 918 968 fs_phone = vfs_grab_phone(fs_handle); 919 rc = async_req_ 3_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t)dev_handle,920 (ipcarg_t) index, (ipcarg_t)size);969 rc = async_req_4_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t) dev_handle, 970 (ipcarg_t) index, LOWER32(size), UPPER32(size)); 921 971 vfs_release_phone(fs_phone); 922 972 return (int)rc; … … 926 976 { 927 977 int fd = IPC_GET_ARG1(*request); 928 size_t size = IPC_GET_ARG2(*request); 978 aoff64_t size = 979 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(*request), IPC_GET_ARG3(*request)); 929 980 int rc; 930 981 … … 982 1033 void vfs_stat(ipc_callid_t rid, ipc_call_t *request) 983 1034 { 984 size_t len; 1035 char *path; 1036 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL); 1037 if (rc != EOK) { 1038 ipc_answer_0(rid, rc); 1039 return; 1040 } 1041 985 1042 ipc_callid_t callid; 986 987 if (!async_data_write_receive(&callid, &len)) {988 ipc_answer_0(callid, EINVAL);989 ipc_answer_0(rid, EINVAL);990 return;991 }992 char *path = malloc(len + 1);993 if (!path) {994 ipc_answer_0(callid, ENOMEM);995 ipc_answer_0(rid, ENOMEM);996 return;997 }998 int rc;999 if ((rc = async_data_write_finalize(callid, path, len))) {1000 ipc_answer_0(rid, rc);1001 free(path);1002 return;1003 }1004 path[len] = '\0';1005 1006 1043 if (!async_data_read_receive(&callid, NULL)) { 1007 1044 free(path); … … 1049 1086 { 1050 1087 int mode = IPC_GET_ARG1(*request); 1051 1052 size_t len; 1053 ipc_callid_t callid; 1054 1055 if (!async_data_write_receive(&callid, &len)) { 1056 ipc_answer_0(callid, EINVAL); 1057 ipc_answer_0(rid, EINVAL); 1058 return; 1059 } 1060 char *path = malloc(len + 1); 1061 if (!path) { 1062 ipc_answer_0(callid, ENOMEM); 1063 ipc_answer_0(rid, ENOMEM); 1064 return; 1065 } 1066 int rc; 1067 if ((rc = async_data_write_finalize(callid, path, len))) { 1068 ipc_answer_0(rid, rc); 1069 free(path); 1070 return; 1071 } 1072 path[len] = '\0'; 1073 1088 1089 char *path; 1090 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL); 1091 if (rc != EOK) { 1092 ipc_answer_0(rid, rc); 1093 return; 1094 } 1095 1074 1096 /* Ignore mode for now. */ 1075 1097 (void) mode; … … 1086 1108 { 1087 1109 int lflag = IPC_GET_ARG1(*request); 1088 1089 size_t len; 1090 ipc_callid_t callid; 1091 1092 if (!async_data_write_receive(&callid, &len)) { 1093 ipc_answer_0(callid, EINVAL); 1094 ipc_answer_0(rid, EINVAL); 1095 return; 1096 } 1097 char *path = malloc(len + 1); 1098 if (!path) { 1099 ipc_answer_0(callid, ENOMEM); 1100 ipc_answer_0(rid, ENOMEM); 1101 return; 1102 } 1103 int rc; 1104 if ((rc = async_data_write_finalize(callid, path, len))) { 1105 ipc_answer_0(rid, rc); 1106 free(path); 1107 return; 1108 } 1109 path[len] = '\0'; 1110 1111 char *path; 1112 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL); 1113 if (rc != EOK) { 1114 ipc_answer_0(rid, rc); 1115 return; 1116 } 1110 1117 1111 1118 fibril_rwlock_write_lock(&namespace_rwlock); … … 1136 1143 void vfs_rename(ipc_callid_t rid, ipc_call_t *request) 1137 1144 { 1138 size_t olen, nlen;1139 ipc_callid_t callid;1140 int rc;1141 1142 1145 /* Retrieve the old path. */ 1143 if (!async_data_write_receive(&callid, &olen)) { 1144 ipc_answer_0(callid, EINVAL); 1145 ipc_answer_0(rid, EINVAL); 1146 return; 1147 } 1148 char *old = malloc(olen + 1); 1149 if (!old) { 1150 ipc_answer_0(callid, ENOMEM); 1151 ipc_answer_0(rid, ENOMEM); 1152 return; 1153 } 1154 if ((rc = async_data_write_finalize(callid, old, olen))) { 1155 ipc_answer_0(rid, rc); 1146 char *old; 1147 int rc = async_data_write_accept((void **) &old, true, 0, 0, 0, NULL); 1148 if (rc != EOK) { 1149 ipc_answer_0(rid, rc); 1150 return; 1151 } 1152 1153 /* Retrieve the new path. */ 1154 char *new; 1155 rc = async_data_write_accept((void **) &new, true, 0, 0, 0, NULL); 1156 if (rc != EOK) { 1156 1157 free(old); 1157 return; 1158 } 1159 old[olen] = '\0'; 1160 1161 /* Retrieve the new path. */ 1162 if (!async_data_write_receive(&callid, &nlen)) { 1163 ipc_answer_0(callid, EINVAL); 1164 ipc_answer_0(rid, EINVAL); 1165 free(old); 1166 return; 1167 } 1168 char *new = malloc(nlen + 1); 1169 if (!new) { 1170 ipc_answer_0(callid, ENOMEM); 1171 ipc_answer_0(rid, ENOMEM); 1172 free(old); 1173 return; 1174 } 1175 if ((rc = async_data_write_finalize(callid, new, nlen))) { 1176 ipc_answer_0(rid, rc); 1177 free(old); 1178 free(new); 1179 return; 1180 } 1181 new[nlen] = '\0'; 1182 1158 ipc_answer_0(rid, rc); 1159 return; 1160 } 1161 1162 size_t olen; 1163 size_t nlen; 1183 1164 char *oldc = canonify(old, &olen); 1184 1165 char *newc = canonify(new, &nlen); 1185 if (!oldc || !newc) { 1166 1167 if ((!oldc) || (!newc)) { 1186 1168 ipc_answer_0(rid, EINVAL); 1187 1169 free(old); … … 1189 1171 return; 1190 1172 } 1173 1191 1174 oldc[olen] = '\0'; 1192 1175 newc[nlen] = '\0'; 1176 1193 1177 if ((!str_lcmp(newc, oldc, str_length(oldc))) && 1194 1178 ((newc[str_length(oldc)] == '/') || … … 1211 1195 vfs_lookup_res_t new_par_lr; 1212 1196 fibril_rwlock_write_lock(&namespace_rwlock); 1197 1213 1198 /* Lookup the node belonging to the old file name. */ 1214 1199 rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL); … … 1220 1205 return; 1221 1206 } 1207 1222 1208 vfs_node_t *old_node = vfs_node_get(&old_lr); 1223 1209 if (!old_node) { … … 1228 1214 return; 1229 1215 } 1216 1230 1217 /* Determine the path to the parent of the node with the new name. */ 1231 1218 char *parentc = str_dup(newc); … … 1237 1224 return; 1238 1225 } 1226 1239 1227 char *lastsl = str_rchr(parentc + 1, '/'); 1240 1228 if (lastsl) … … 1242 1230 else 1243 1231 parentc[1] = '\0'; 1232 1244 1233 /* Lookup parent of the new file name. */ 1245 1234 rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL); … … 1252 1241 return; 1253 1242 } 1243 1254 1244 /* Check whether linking to the same file system instance. */ 1255 1245 if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) || … … 1261 1251 return; 1262 1252 } 1253 1263 1254 /* Destroy the old link for the new name. */ 1264 1255 vfs_node_t *new_node = NULL; 1265 1256 rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL); 1257 1266 1258 switch (rc) { 1267 1259 case ENOENT: … … 1288 1280 return; 1289 1281 } 1282 1290 1283 /* Create the new link for the new name. */ 1291 1284 rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index); … … 1299 1292 return; 1300 1293 } 1294 1301 1295 fibril_mutex_lock(&nodes_mutex); 1302 1296 old_node->lnkcnt++; 1303 1297 fibril_mutex_unlock(&nodes_mutex); 1298 1304 1299 /* Destroy the link for the old name. */ 1305 1300 rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL); … … 1314 1309 return; 1315 1310 } 1311 1316 1312 fibril_mutex_lock(&nodes_mutex); 1317 1313 old_node->lnkcnt--; … … 1319 1315 fibril_rwlock_write_unlock(&namespace_rwlock); 1320 1316 vfs_node_put(old_node); 1317 1321 1318 if (new_node) 1322 1319 vfs_node_put(new_node); 1320 1323 1321 free(old); 1324 1322 free(new);
Note:
See TracChangeset
for help on using the changeset viewer.