Changes in uspace/srv/vfs/vfs_ops.c [27b76ca:ffa2c8ef] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/vfs/vfs_ops.c
r27b76ca rffa2c8ef 76 76 vfs_node_t *mr_node; 77 77 fs_index_t rindex; 78 aoff64_t rsize;78 size_t rsize; 79 79 unsigned rlnkcnt; 80 async_exch_t *exch;81 80 sysarg_t rc; 81 int phone; 82 82 aid_t msg; 83 83 ipc_call_t answer; … … 123 123 124 124 /* Tell the mountee that it is being mounted. */ 125 exch = vfs_exchange_grab(fs_handle);126 msg = async_send_1( exch, VFS_OUT_MOUNTED,125 phone = vfs_grab_phone(fs_handle); 126 msg = async_send_1(phone, VFS_OUT_MOUNTED, 127 127 (sysarg_t) devmap_handle, &answer); 128 /* Send the mount options */129 rc = async_data_write_start( exch, (void *)opts,128 /* send the mount options */ 129 rc = async_data_write_start(phone, (void *)opts, 130 130 str_size(opts)); 131 vfs_exchange_release(exch);132 133 131 if (rc != EOK) { 134 132 async_wait_for(msg, NULL); 133 vfs_release_phone(fs_handle, phone); 135 134 fibril_rwlock_write_unlock(&namespace_rwlock); 136 135 async_answer_0(rid, rc); … … 138 137 } 139 138 async_wait_for(msg, &rc); 139 vfs_release_phone(fs_handle, phone); 140 140 141 141 if (rc != EOK) { … … 146 146 147 147 rindex = (fs_index_t) IPC_GET_ARG1(answer); 148 rsize = ( aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer), IPC_GET_ARG3(answer));149 rlnkcnt = (unsigned) IPC_GET_ARG 4(answer);148 rsize = (size_t) IPC_GET_ARG2(answer); 149 rlnkcnt = (unsigned) IPC_GET_ARG3(answer); 150 150 151 151 mr_res.triplet.fs_handle = fs_handle; … … 182 182 */ 183 183 184 async_exch_t *mountee_exch = vfs_exchange_grab(fs_handle);185 assert(mountee_ exch);186 187 exch = vfs_exchange_grab(mp_res.triplet.fs_handle);188 msg = async_send_4( exch, VFS_OUT_MOUNT,184 int mountee_phone = vfs_grab_phone(fs_handle); 185 assert(mountee_phone >= 0); 186 187 phone = vfs_grab_phone(mp_res.triplet.fs_handle); 188 msg = async_send_4(phone, VFS_OUT_MOUNT, 189 189 (sysarg_t) mp_res.triplet.devmap_handle, 190 190 (sysarg_t) mp_res.triplet.index, … … 192 192 (sysarg_t) devmap_handle, &answer); 193 193 194 /* Send connection */ 195 rc = async_exchange_clone(exch, mountee_exch); 196 vfs_exchange_release(mountee_exch); 197 198 if (rc != EOK) { 199 vfs_exchange_release(exch); 194 /* send connection */ 195 rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone); 196 if (rc != EOK) { 200 197 async_wait_for(msg, NULL); 201 198 vfs_release_phone(fs_handle, mountee_phone); 199 vfs_release_phone(mp_res.triplet.fs_handle, phone); 202 200 /* Mount failed, drop reference to mp_node. */ 203 201 if (mp_node) 204 202 vfs_node_put(mp_node); 205 206 203 async_answer_0(rid, rc); 207 204 fibril_rwlock_write_unlock(&namespace_rwlock); 208 205 return; 209 206 } 207 208 vfs_release_phone(fs_handle, mountee_phone); 210 209 211 210 /* send the mount options */ 212 rc = async_data_write_start(exch, (void *) opts, str_size(opts)); 213 if (rc != EOK) { 214 vfs_exchange_release(exch); 211 rc = async_data_write_start(phone, (void *)opts, str_size(opts)); 212 if (rc != EOK) { 215 213 async_wait_for(msg, NULL); 216 214 vfs_release_phone(mp_res.triplet.fs_handle, phone); 217 215 /* Mount failed, drop reference to mp_node. */ 218 216 if (mp_node) 219 217 vfs_node_put(mp_node); 220 221 218 fibril_rwlock_write_unlock(&namespace_rwlock); 222 219 async_answer_0(rid, rc); 223 220 return; 224 221 } 225 226 vfs_exchange_release(exch);227 222 async_wait_for(msg, &rc); 223 vfs_release_phone(mp_res.triplet.fs_handle, phone); 228 224 229 225 if (rc == EOK) { 230 226 rindex = (fs_index_t) IPC_GET_ARG1(answer); 231 rsize = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer), 232 IPC_GET_ARG3(answer)); 233 rlnkcnt = (unsigned) IPC_GET_ARG4(answer); 234 227 rsize = (size_t) IPC_GET_ARG2(answer); 228 rlnkcnt = (unsigned) IPC_GET_ARG3(answer); 229 235 230 mr_res.triplet.fs_handle = fs_handle; 236 231 mr_res.triplet.devmap_handle = devmap_handle; … … 239 234 mr_res.lnkcnt = rlnkcnt; 240 235 mr_res.type = VFS_NODE_DIRECTORY; 241 236 242 237 /* Add reference to the mounted root. */ 243 238 mr_node = vfs_node_get(&mr_res); … … 248 243 vfs_node_put(mp_node); 249 244 } 250 245 251 246 async_answer_0(rid, rc); 252 247 fibril_rwlock_write_unlock(&namespace_rwlock); … … 308 303 309 304 /* 310 * Wait for VFS_IN_PING so that we can return an error if we don't know305 * Wait for IPC_M_PING so that we can return an error if we don't know 311 306 * fs_name. 312 307 */ 313 308 ipc_call_t data; 314 309 ipc_callid_t callid = async_get_call(&data); 315 if (IPC_GET_IMETHOD(data) != VFS_IN_PING) {310 if (IPC_GET_IMETHOD(data) != IPC_M_PING) { 316 311 async_answer_0(callid, ENOTSUP); 317 312 async_answer_0(rid, ENOTSUP); … … 326 321 * This will also give us its file system handle. 327 322 */ 328 fibril_mutex_lock(&fs_ list_lock);323 fibril_mutex_lock(&fs_head_lock); 329 324 fs_handle_t fs_handle; 330 325 recheck: … … 332 327 if (!fs_handle) { 333 328 if (flags & IPC_FLAG_BLOCKING) { 334 fibril_condvar_wait(&fs_ list_cv, &fs_list_lock);329 fibril_condvar_wait(&fs_head_cv, &fs_head_lock); 335 330 goto recheck; 336 331 } 337 332 338 fibril_mutex_unlock(&fs_ list_lock);333 fibril_mutex_unlock(&fs_head_lock); 339 334 async_answer_0(callid, ENOENT); 340 335 async_answer_0(rid, ENOENT); … … 344 339 return; 345 340 } 346 fibril_mutex_unlock(&fs_ list_lock);341 fibril_mutex_unlock(&fs_head_lock); 347 342 348 343 /* Acknowledge that we know fs_name. */ … … 363 358 vfs_lookup_res_t mr_res; 364 359 vfs_node_t *mr_node; 365 async_exch_t *exch;366 360 int phone; 361 367 362 /* 368 363 * Receive the mount point path. … … 372 367 if (rc != EOK) 373 368 async_answer_0(rid, rc); 374 369 375 370 /* 376 371 * Taking the namespace lock will do two things for us. First, it will … … 400 395 return; 401 396 } 402 397 403 398 /* 404 399 * Count the total number of references for the mounted file system. We … … 416 411 return; 417 412 } 418 413 419 414 if (str_cmp(mp, "/") == 0) { 420 415 421 416 /* 422 417 * Unmounting the root file system. … … 425 420 * VFS_OUT_UNMOUNTED directly to the mounted file system. 426 421 */ 427 422 428 423 free(mp); 429 430 exch = vfs_exchange_grab(mr_node->fs_handle); 431 rc = async_req_1_0(exch, VFS_OUT_UNMOUNTED, 424 phone = vfs_grab_phone(mr_node->fs_handle); 425 rc = async_req_1_0(phone, VFS_OUT_UNMOUNTED, 432 426 mr_node->devmap_handle); 433 vfs_exchange_release(exch); 434 427 vfs_release_phone(mr_node->fs_handle, phone); 435 428 if (rc != EOK) { 436 429 fibril_rwlock_write_unlock(&namespace_rwlock); … … 439 432 return; 440 433 } 441 442 434 rootfs.fs_handle = 0; 443 435 rootfs.devmap_handle = 0; 444 436 } else { 445 437 446 438 /* 447 439 * Unmounting a non-root file system. … … 450 442 * file system, so we delegate the operation to it. 451 443 */ 452 444 453 445 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL); 454 446 free(mp); … … 459 451 return; 460 452 } 461 462 453 vfs_node_t *mp_node = vfs_node_get(&mp_res); 463 454 if (!mp_node) { … … 467 458 return; 468 459 } 469 470 exch = vfs_exchange_grab(mp_node->fs_handle);471 rc = async_req_2_0( exch, VFS_OUT_UNMOUNT,460 461 phone = vfs_grab_phone(mp_node->fs_handle); 462 rc = async_req_2_0(phone, VFS_OUT_UNMOUNT, 472 463 mp_node->devmap_handle, mp_node->index); 473 vfs_exchange_release(exch); 474 464 vfs_release_phone(mp_node->fs_handle, phone); 475 465 if (rc != EOK) { 476 466 fibril_rwlock_write_unlock(&namespace_rwlock); … … 480 470 return; 481 471 } 482 472 483 473 /* Drop the reference we got above. */ 484 474 vfs_node_put(mp_node); … … 486 476 vfs_node_put(mp_node); 487 477 } 488 478 479 489 480 /* 490 481 * All went well, the mounted file system was successfully unmounted. … … 492 483 */ 493 484 vfs_node_forget(mr_node); 494 485 495 486 fibril_rwlock_write_unlock(&namespace_rwlock); 496 487 async_answer_0(rid, EOK); … … 618 609 } 619 610 611 void vfs_open_node(ipc_callid_t rid, ipc_call_t *request) 612 { 613 // FIXME: check for sanity of the supplied fs, dev and index 614 615 /* 616 * The interface is open_node(fs, dev, index, oflag). 617 */ 618 vfs_lookup_res_t lr; 619 620 lr.triplet.fs_handle = IPC_GET_ARG1(*request); 621 lr.triplet.devmap_handle = IPC_GET_ARG2(*request); 622 lr.triplet.index = IPC_GET_ARG3(*request); 623 int oflag = IPC_GET_ARG4(*request); 624 625 fibril_rwlock_read_lock(&namespace_rwlock); 626 627 int rc = vfs_open_node_internal(&lr); 628 if (rc != EOK) { 629 fibril_rwlock_read_unlock(&namespace_rwlock); 630 async_answer_0(rid, rc); 631 return; 632 } 633 634 vfs_node_t *node = vfs_node_get(&lr); 635 fibril_rwlock_read_unlock(&namespace_rwlock); 636 637 /* Truncate the file if requested and if necessary. */ 638 if (oflag & O_TRUNC) { 639 fibril_rwlock_write_lock(&node->contents_rwlock); 640 if (node->size) { 641 rc = vfs_truncate_internal(node->fs_handle, 642 node->devmap_handle, node->index, 0); 643 if (rc) { 644 fibril_rwlock_write_unlock(&node->contents_rwlock); 645 vfs_node_put(node); 646 async_answer_0(rid, rc); 647 return; 648 } 649 node->size = 0; 650 } 651 fibril_rwlock_write_unlock(&node->contents_rwlock); 652 } 653 654 /* 655 * Get ourselves a file descriptor and the corresponding vfs_file_t 656 * structure. 657 */ 658 int fd = vfs_fd_alloc((oflag & O_DESC) != 0); 659 if (fd < 0) { 660 vfs_node_put(node); 661 async_answer_0(rid, fd); 662 return; 663 } 664 vfs_file_t *file = vfs_file_get(fd); 665 file->node = node; 666 if (oflag & O_APPEND) 667 file->append = true; 668 669 /* 670 * The following increase in reference count is for the fact that the 671 * file is being opened and that a file structure is pointing to it. 672 * It is necessary so that the file will not disappear when 673 * vfs_node_put() is called. The reference will be dropped by the 674 * respective VFS_IN_CLOSE. 675 */ 676 vfs_node_addref(node); 677 vfs_node_put(node); 678 vfs_file_put(file); 679 680 /* Success! Return the new file descriptor to the client. */ 681 async_answer_1(rid, EOK, fd); 682 } 683 620 684 void vfs_sync(ipc_callid_t rid, ipc_call_t *request) 621 685 { … … 634 698 */ 635 699 fibril_mutex_lock(&file->lock); 636 async_exch_t *fs_exch = vfs_exchange_grab(file->node->fs_handle);700 int fs_phone = vfs_grab_phone(file->node->fs_handle); 637 701 638 702 /* Make a VFS_OUT_SYMC request at the destination FS server. */ 639 703 aid_t msg; 640 704 ipc_call_t answer; 641 msg = async_send_2(fs_ exch, VFS_OUT_SYNC, file->node->devmap_handle,705 msg = async_send_2(fs_phone, VFS_OUT_SYNC, file->node->devmap_handle, 642 706 file->node->index, &answer); 643 644 vfs_exchange_release(fs_exch); 645 707 646 708 /* Wait for reply from the FS server. */ 647 709 sysarg_t rc; 648 710 async_wait_for(msg, &rc); 649 711 712 vfs_release_phone(file->node->fs_handle, fs_phone); 650 713 fibril_mutex_unlock(&file->lock); 651 714 652 715 vfs_file_put(file); 653 716 async_answer_0(rid, rc); 654 717 } 655 718 719 int vfs_close_internal(vfs_file_t *file) 720 { 721 /* 722 * Lock the open file structure so that no other thread can manipulate 723 * the same open file at a time. 724 */ 725 fibril_mutex_lock(&file->lock); 726 727 if (file->refcnt <= 1) { 728 /* Only close the file on the destination FS server 729 if there are no more file descriptors (except the 730 present one) pointing to this file. */ 731 732 int fs_phone = vfs_grab_phone(file->node->fs_handle); 733 734 /* Make a VFS_OUT_CLOSE request at the destination FS server. */ 735 aid_t msg; 736 ipc_call_t answer; 737 msg = async_send_2(fs_phone, VFS_OUT_CLOSE, 738 file->node->devmap_handle, file->node->index, &answer); 739 740 /* Wait for reply from the FS server. */ 741 sysarg_t rc; 742 async_wait_for(msg, &rc); 743 744 vfs_release_phone(file->node->fs_handle, fs_phone); 745 fibril_mutex_unlock(&file->lock); 746 747 return IPC_GET_ARG1(answer); 748 } 749 750 fibril_mutex_unlock(&file->lock); 751 return EOK; 752 } 753 656 754 void vfs_close(ipc_callid_t rid, ipc_call_t *request) 657 755 { 658 756 int fd = IPC_GET_ARG1(*request); 659 int ret = vfs_fd_free(fd); 757 758 /* Lookup the file structure corresponding to the file descriptor. */ 759 vfs_file_t *file = vfs_file_get(fd); 760 if (!file) { 761 async_answer_0(rid, ENOENT); 762 return; 763 } 764 765 int ret = vfs_close_internal(file); 766 if (ret != EOK) 767 async_answer_0(rid, ret); 768 769 vfs_file_put(file); 770 ret = vfs_fd_free(fd); 660 771 async_answer_0(rid, ret); 661 772 } … … 663 774 static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read) 664 775 { 776 vfs_info_t *vi; 777 665 778 /* 666 779 * The following code strongly depends on the fact that the files data … … 672 785 * open files supports parallel access! 673 786 */ 674 787 675 788 int fd = IPC_GET_ARG1(*request); 676 789 … … 687 800 */ 688 801 fibril_mutex_lock(&file->lock); 689 690 v fs_info_t *fs_info= fs_handle_to_info(file->node->fs_handle);691 assert( fs_info);692 802 803 vi = fs_handle_to_info(file->node->fs_handle); 804 assert(vi); 805 693 806 /* 694 807 * Lock the file's node so that no other client can read/write to it at … … 696 809 * write implementation does not modify the file size. 697 810 */ 698 if ((read) || 699 ((fs_info->concurrent_read_write) && (fs_info->write_retains_size))) 811 if (read || (vi->concurrent_read_write && vi->write_retains_size)) 700 812 fibril_rwlock_read_lock(&file->node->contents_rwlock); 701 813 else 702 814 fibril_rwlock_write_lock(&file->node->contents_rwlock); 703 815 704 816 if (file->node->type == VFS_NODE_DIRECTORY) { 705 817 /* … … 711 823 } 712 824 713 async_exch_t *fs_exch = vfs_exchange_grab(file->node->fs_handle);825 int fs_phone = vfs_grab_phone(file->node->fs_handle); 714 826 715 827 /* … … 723 835 ipc_call_t answer; 724 836 if (read) { 725 rc = async_data_read_forward_ 4_1(fs_exch, VFS_OUT_READ,726 file->node->devmap_handle, file->node->index, 727 LOWER32(file->pos), UPPER32(file->pos),&answer);837 rc = async_data_read_forward_3_1(fs_phone, VFS_OUT_READ, 838 file->node->devmap_handle, file->node->index, file->pos, 839 &answer); 728 840 } else { 729 841 if (file->append) 730 842 file->pos = file->node->size; 731 843 732 rc = async_data_write_forward_ 4_1(fs_exch, VFS_OUT_WRITE,733 file->node->devmap_handle, file->node->index, 734 LOWER32(file->pos), UPPER32(file->pos),&answer);735 } 736 737 vfs_ exchange_release(fs_exch);844 rc = async_data_write_forward_3_1(fs_phone, VFS_OUT_WRITE, 845 file->node->devmap_handle, file->node->index, file->pos, 846 &answer); 847 } 848 849 vfs_release_phone(file->node->fs_handle, fs_phone); 738 850 739 851 size_t bytes = IPC_GET_ARG1(answer); … … 743 855 744 856 /* Unlock the VFS node. */ 745 if ((read) || 746 ((fs_info->concurrent_read_write) && (fs_info->write_retains_size))) 857 if (read || (vi->concurrent_read_write && vi->write_retains_size)) 747 858 fibril_rwlock_read_unlock(&file->node->contents_rwlock); 748 859 else { 749 860 /* Update the cached version of node's size. */ 750 861 if (rc == EOK) 751 file->node->size = MERGE_LOUP32(IPC_GET_ARG2(answer), 752 IPC_GET_ARG3(answer)); 862 file->node->size = IPC_GET_ARG2(answer); 753 863 fibril_rwlock_write_unlock(&file->node->contents_rwlock); 754 864 } … … 865 975 fs_index_t index, aoff64_t size) 866 976 { 867 async_exch_t *exch = vfs_exchange_grab(fs_handle); 868 sysarg_t rc = async_req_4_0(exch, VFS_OUT_TRUNCATE, 869 (sysarg_t) devmap_handle, (sysarg_t) index, LOWER32(size), 870 UPPER32(size)); 871 vfs_exchange_release(exch); 872 873 return (int) rc; 977 sysarg_t rc; 978 int fs_phone; 979 980 fs_phone = vfs_grab_phone(fs_handle); 981 rc = async_req_4_0(fs_phone, VFS_OUT_TRUNCATE, (sysarg_t) devmap_handle, 982 (sysarg_t) index, LOWER32(size), UPPER32(size)); 983 vfs_release_phone(fs_handle, fs_phone); 984 return (int)rc; 874 985 } 875 986 … … 921 1032 fibril_mutex_lock(&file->lock); 922 1033 923 async_exch_t *exch = vfs_exchange_grab(file->node->fs_handle);1034 int fs_phone = vfs_grab_phone(file->node->fs_handle); 924 1035 925 1036 aid_t msg; 926 msg = async_send_3( exch, VFS_OUT_STAT, file->node->devmap_handle,1037 msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->devmap_handle, 927 1038 file->node->index, true, NULL); 928 async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); 929 930 vfs_exchange_release(exch); 931 1039 async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); 932 1040 async_wait_for(msg, &rc); 933 1041 vfs_release_phone(file->node->fs_handle, fs_phone); 1042 934 1043 fibril_mutex_unlock(&file->lock); 935 1044 vfs_file_put(file); … … 974 1083 fibril_rwlock_read_unlock(&namespace_rwlock); 975 1084 976 async_exch_t *exch = vfs_exchange_grab(node->fs_handle); 977 1085 int fs_phone = vfs_grab_phone(node->fs_handle); 978 1086 aid_t msg; 979 msg = async_send_3( exch, VFS_OUT_STAT, node->devmap_handle,1087 msg = async_send_3(fs_phone, VFS_OUT_STAT, node->devmap_handle, 980 1088 node->index, false, NULL); 981 async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); 982 983 vfs_exchange_release(exch); 1089 async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); 984 1090 985 1091 sysarg_t rv; 986 1092 async_wait_for(msg, &rv); 1093 vfs_release_phone(node->fs_handle, fs_phone); 987 1094 988 1095 async_answer_0(rid, rv); … … 1127 1234 if (!parentc) { 1128 1235 fibril_rwlock_write_unlock(&namespace_rwlock); 1129 vfs_node_put(old_node);1130 1236 async_answer_0(rid, rc); 1131 1237 free(old); … … 1145 1251 if (rc != EOK) { 1146 1252 fibril_rwlock_write_unlock(&namespace_rwlock); 1147 vfs_node_put(old_node);1148 1253 async_answer_0(rid, rc); 1149 1254 free(old); … … 1156 1261 (old_node->devmap_handle != new_par_lr.triplet.devmap_handle)) { 1157 1262 fibril_rwlock_write_unlock(&namespace_rwlock); 1158 vfs_node_put(old_node);1159 1263 async_answer_0(rid, EXDEV); /* different file systems */ 1160 1264 free(old); … … 1175 1279 if (!new_node) { 1176 1280 fibril_rwlock_write_unlock(&namespace_rwlock); 1177 vfs_node_put(old_node);1178 1281 async_answer_0(rid, ENOMEM); 1179 1282 free(old); … … 1187 1290 default: 1188 1291 fibril_rwlock_write_unlock(&namespace_rwlock); 1189 vfs_node_put(old_node);1190 1292 async_answer_0(rid, ENOTEMPTY); 1191 1293 free(old); … … 1198 1300 if (rc != EOK) { 1199 1301 fibril_rwlock_write_unlock(&namespace_rwlock); 1200 vfs_node_put(old_node);1201 1302 if (new_node) 1202 1303 vfs_node_put(new_node); … … 1262 1363 fibril_mutex_lock(&oldfile->lock); 1263 1364 1264 /* Make sure newfd is closed. */ 1265 (void) vfs_fd_free(newfd); 1365 /* Lookup an open file structure possibly corresponding to newfd. */ 1366 vfs_file_t *newfile = vfs_file_get(newfd); 1367 if (newfile) { 1368 /* Close the originally opened file. */ 1369 int ret = vfs_close_internal(newfile); 1370 if (ret != EOK) { 1371 fibril_mutex_unlock(&oldfile->lock); 1372 vfs_file_put(oldfile); 1373 vfs_file_put(newfile); 1374 async_answer_0(rid, ret); 1375 return; 1376 } 1377 1378 ret = vfs_fd_free(newfd); 1379 if (ret != EOK) { 1380 fibril_mutex_unlock(&oldfile->lock); 1381 vfs_file_put(oldfile); 1382 vfs_file_put(newfile); 1383 async_answer_0(rid, ret); 1384 return; 1385 } 1386 vfs_file_put(newfile); 1387 } 1266 1388 1267 1389 /* Assign the old file to newfd. */ … … 1276 1398 } 1277 1399 1278 void vfs_wait_handle(ipc_callid_t rid, ipc_call_t *request)1279 {1280 int fd = vfs_wait_handle_internal();1281 async_answer_1(rid, EOK, fd);1282 }1283 1284 1400 /** 1285 1401 * @}
Note:
See TracChangeset
for help on using the changeset viewer.