Rev 4445 | Rev 4509 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4445 | Rev 4463 | ||
|---|---|---|---|
| Line 91... | Line 91... | ||
| 91 | unsigned rlnkcnt; |
91 | unsigned rlnkcnt; |
| 92 | ipcarg_t rc; |
92 | ipcarg_t rc; |
| 93 | int phone; |
93 | int phone; |
| 94 | aid_t msg; |
94 | aid_t msg; |
| 95 | ipc_call_t answer; |
95 | ipc_call_t answer; |
| 96 | 96 | ||
| 97 | /* Resolve the path to the mountpoint. */ |
97 | /* Resolve the path to the mountpoint. */ |
| 98 | rwlock_write_lock(&namespace_rwlock); |
98 | rwlock_write_lock(&namespace_rwlock); |
| 99 | if (rootfs.fs_handle) { |
99 | if (rootfs.fs_handle) { |
| 100 | /* We already have the root FS. */ |
100 | /* We already have the root FS. */ |
| 101 | if (str_cmp(mp, "/") == 0) { |
101 | if (str_cmp(mp, "/") == 0) { |
| Line 488... | Line 488... | ||
| 488 | { |
488 | { |
| 489 | if (!vfs_files_init()) { |
489 | if (!vfs_files_init()) { |
| 490 | ipc_answer_0(rid, ENOMEM); |
490 | ipc_answer_0(rid, ENOMEM); |
| 491 | return; |
491 | return; |
| 492 | } |
492 | } |
| 493 | 493 | ||
| 494 | /* |
494 | /* |
| 495 | * The POSIX interface is open(path, oflag, mode). |
495 | * The POSIX interface is open(path, oflag, mode). |
| 496 | * We can receive oflags and mode along with the VFS_OPEN call; the path |
496 | * We can receive oflags and mode along with the VFS_OPEN call; the path |
| 497 | * will need to arrive in another call. |
497 | * will need to arrive in another call. |
| 498 | * |
498 | * |
| Line 501... | Line 501... | ||
| 501 | */ |
501 | */ |
| 502 | int lflag = IPC_GET_ARG1(*request); |
502 | int lflag = IPC_GET_ARG1(*request); |
| 503 | int oflag = IPC_GET_ARG2(*request); |
503 | int oflag = IPC_GET_ARG2(*request); |
| 504 | int mode = IPC_GET_ARG3(*request); |
504 | int mode = IPC_GET_ARG3(*request); |
| 505 | size_t len; |
505 | size_t len; |
| 506 | 506 | ||
| 507 | /* |
507 | /* |
| 508 | * Make sure that we are called with exactly one of L_FILE and |
508 | * Make sure that we are called with exactly one of L_FILE and |
| 509 | * L_DIRECTORY. |
509 | * L_DIRECTORY. Make sure that the user does not pass L_OPEN. |
| 510 | */ |
510 | */ |
| 511 | if ((lflag & (L_FILE | L_DIRECTORY)) == 0 || |
511 | if (((lflag & (L_FILE | L_DIRECTORY)) == 0) |
| 512 | (lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) { |
512 | || ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) |
| - | 513 | || ((lflag & L_OPEN) != 0)) { |
|
| 513 | ipc_answer_0(rid, EINVAL); |
514 | ipc_answer_0(rid, EINVAL); |
| 514 | return; |
515 | return; |
| 515 | } |
516 | } |
| 516 | 517 | ||
| 517 | if (oflag & O_CREAT) |
518 | if (oflag & O_CREAT) |
| 518 | lflag |= L_CREATE; |
519 | lflag |= L_CREATE; |
| 519 | if (oflag & O_EXCL) |
520 | if (oflag & O_EXCL) |
| 520 | lflag |= L_EXCLUSIVE; |
521 | lflag |= L_EXCLUSIVE; |
| 521 | 522 | ||
| 522 | ipc_callid_t callid; |
523 | ipc_callid_t callid; |
| 523 | - | ||
| 524 | if (!ipc_data_write_receive(&callid, &len)) { |
524 | if (!ipc_data_write_receive(&callid, &len)) { |
| 525 | ipc_answer_0(callid, EINVAL); |
525 | ipc_answer_0(callid, EINVAL); |
| 526 | ipc_answer_0(rid, EINVAL); |
526 | ipc_answer_0(rid, EINVAL); |
| 527 | return; |
527 | return; |
| 528 | } |
528 | } |
| - | 529 | ||
| 529 | char *path = malloc(len + 1); |
530 | char *path = malloc(len + 1); |
| 530 | if (!path) { |
531 | if (!path) { |
| 531 | ipc_answer_0(callid, ENOMEM); |
532 | ipc_answer_0(callid, ENOMEM); |
| 532 | ipc_answer_0(rid, ENOMEM); |
533 | ipc_answer_0(rid, ENOMEM); |
| 533 | return; |
534 | return; |
| 534 | } |
535 | } |
| - | 536 | ||
| 535 | int rc; |
537 | int rc; |
| 536 | if ((rc = ipc_data_write_finalize(callid, path, len))) { |
538 | if ((rc = ipc_data_write_finalize(callid, path, len))) { |
| 537 | ipc_answer_0(rid, rc); |
539 | ipc_answer_0(rid, rc); |
| 538 | free(path); |
540 | free(path); |
| 539 | return; |
541 | return; |
| Line 547... | Line 549... | ||
| 547 | */ |
549 | */ |
| 548 | if (lflag & L_CREATE) |
550 | if (lflag & L_CREATE) |
| 549 | rwlock_write_lock(&namespace_rwlock); |
551 | rwlock_write_lock(&namespace_rwlock); |
| 550 | else |
552 | else |
| 551 | rwlock_read_lock(&namespace_rwlock); |
553 | rwlock_read_lock(&namespace_rwlock); |
| 552 | 554 | ||
| 553 | /* The path is now populated and we can call vfs_lookup_internal(). */ |
555 | /* The path is now populated and we can call vfs_lookup_internal(). */ |
| 554 | vfs_lookup_res_t lr; |
556 | vfs_lookup_res_t lr; |
| 555 | rc = vfs_lookup_internal(path, lflag, &lr, NULL); |
557 | rc = vfs_lookup_internal(path, lflag | L_OPEN, &lr, NULL); |
| 556 | if (rc) { |
558 | if (rc != EOK) { |
| 557 | if (lflag & L_CREATE) |
559 | if (lflag & L_CREATE) |
| 558 | rwlock_write_unlock(&namespace_rwlock); |
560 | rwlock_write_unlock(&namespace_rwlock); |
| 559 | else |
561 | else |
| 560 | rwlock_read_unlock(&namespace_rwlock); |
562 | rwlock_read_unlock(&namespace_rwlock); |
| 561 | ipc_answer_0(rid, rc); |
563 | ipc_answer_0(rid, rc); |
| 562 | free(path); |
564 | free(path); |
| 563 | return; |
565 | return; |
| 564 | } |
566 | } |
| 565 | 567 | ||
| 566 | /* Path is no longer needed. */ |
568 | /* Path is no longer needed. */ |
| 567 | free(path); |
569 | free(path); |
| 568 | 570 | ||
| 569 | vfs_node_t *node = vfs_node_get(&lr); |
571 | vfs_node_t *node = vfs_node_get(&lr); |
| 570 | if (lflag & L_CREATE) |
572 | if (lflag & L_CREATE) |
| 571 | rwlock_write_unlock(&namespace_rwlock); |
573 | rwlock_write_unlock(&namespace_rwlock); |
| 572 | else |
574 | else |
| 573 | rwlock_read_unlock(&namespace_rwlock); |
575 | rwlock_read_unlock(&namespace_rwlock); |
| 574 | 576 | ||
| 575 | /* Truncate the file if requested and if necessary. */ |
577 | /* Truncate the file if requested and if necessary. */ |
| 576 | if (oflag & O_TRUNC) { |
578 | if (oflag & O_TRUNC) { |
| 577 | rwlock_write_lock(&node->contents_rwlock); |
579 | rwlock_write_lock(&node->contents_rwlock); |
| 578 | if (node->size) { |
580 | if (node->size) { |
| 579 | rc = vfs_truncate_internal(node->fs_handle, |
581 | rc = vfs_truncate_internal(node->fs_handle, |
| Line 586... | Line 588... | ||
| 586 | } |
588 | } |
| 587 | node->size = 0; |
589 | node->size = 0; |
| 588 | } |
590 | } |
| 589 | rwlock_write_unlock(&node->contents_rwlock); |
591 | rwlock_write_unlock(&node->contents_rwlock); |
| 590 | } |
592 | } |
| 591 | 593 | ||
| 592 | /* |
594 | /* |
| 593 | * Get ourselves a file descriptor and the corresponding vfs_file_t |
595 | * Get ourselves a file descriptor and the corresponding vfs_file_t |
| 594 | * structure. |
596 | * structure. |
| 595 | */ |
597 | */ |
| 596 | int fd = vfs_fd_alloc(); |
598 | int fd = vfs_fd_alloc(); |
| Line 599... | Line 601... | ||
| 599 | ipc_answer_0(rid, fd); |
601 | ipc_answer_0(rid, fd); |
| 600 | return; |
602 | return; |
| 601 | } |
603 | } |
| 602 | vfs_file_t *file = vfs_file_get(fd); |
604 | vfs_file_t *file = vfs_file_get(fd); |
| 603 | file->node = node; |
605 | file->node = node; |
| 604 | if (oflag & O_APPEND) |
606 | if (oflag & O_APPEND) |
| 605 | file->append = true; |
607 | file->append = true; |
| 606 | 608 | ||
| 607 | /* |
609 | /* |
| 608 | * The following increase in reference count is for the fact that the |
610 | * The following increase in reference count is for the fact that the |
| 609 | * file is being opened and that a file structure is pointing to it. |
611 | * file is being opened and that a file structure is pointing to it. |
| 610 | * It is necessary so that the file will not disappear when |
612 | * It is necessary so that the file will not disappear when |
| 611 | * vfs_node_put() is called. The reference will be dropped by the |
613 | * vfs_node_put() is called. The reference will be dropped by the |
| 612 | * respective VFS_CLOSE. |
614 | * respective VFS_CLOSE. |
| 613 | */ |
615 | */ |
| 614 | vfs_node_addref(node); |
616 | vfs_node_addref(node); |
| 615 | vfs_node_put(node); |
617 | vfs_node_put(node); |
| - | 618 | ||
| - | 619 | /* Success! Return the new file descriptor to the client. */ |
|
| - | 620 | ipc_answer_1(rid, EOK, fd); |
|
| - | 621 | } |
|
| 616 | 622 | ||
| - | 623 | void vfs_open_node(ipc_callid_t rid, ipc_call_t *request) |
|
| - | 624 | { |
|
| - | 625 | // FIXME: check for sanity of the supplied fs, dev and index |
|
| - | 626 | ||
| - | 627 | if (!vfs_files_init()) { |
|
| - | 628 | ipc_answer_0(rid, ENOMEM); |
|
| - | 629 | return; |
|
| - | 630 | } |
|
| - | 631 | ||
| - | 632 | /* |
|
| - | 633 | * The interface is open_node(fs, dev, index, oflag). |
|
| - | 634 | */ |
|
| - | 635 | vfs_lookup_res_t lr; |
|
| - | 636 | ||
| - | 637 | lr.triplet.fs_handle = IPC_GET_ARG1(*request); |
|
| - | 638 | lr.triplet.dev_handle = IPC_GET_ARG2(*request); |
|
| - | 639 | lr.triplet.index = IPC_GET_ARG3(*request); |
|
| - | 640 | int oflag = IPC_GET_ARG4(*request); |
|
| - | 641 | ||
| - | 642 | rwlock_read_lock(&namespace_rwlock); |
|
| - | 643 | ||
| - | 644 | int rc = vfs_open_node_internal(&lr); |
|
| - | 645 | if (rc != EOK) { |
|
| - | 646 | rwlock_read_unlock(&namespace_rwlock); |
|
| - | 647 | ipc_answer_0(rid, rc); |
|
| - | 648 | return; |
|
| - | 649 | } |
|
| - | 650 | ||
| - | 651 | vfs_node_t *node = vfs_node_get(&lr); |
|
| - | 652 | rwlock_read_unlock(&namespace_rwlock); |
|
| - | 653 | ||
| - | 654 | /* Truncate the file if requested and if necessary. */ |
|
| - | 655 | if (oflag & O_TRUNC) { |
|
| - | 656 | rwlock_write_lock(&node->contents_rwlock); |
|
| - | 657 | if (node->size) { |
|
| - | 658 | rc = vfs_truncate_internal(node->fs_handle, |
|
| - | 659 | node->dev_handle, node->index, 0); |
|
| - | 660 | if (rc) { |
|
| - | 661 | rwlock_write_unlock(&node->contents_rwlock); |
|
| - | 662 | vfs_node_put(node); |
|
| - | 663 | ipc_answer_0(rid, rc); |
|
| - | 664 | return; |
|
| - | 665 | } |
|
| - | 666 | node->size = 0; |
|
| - | 667 | } |
|
| - | 668 | rwlock_write_unlock(&node->contents_rwlock); |
|
| - | 669 | } |
|
| - | 670 | ||
| - | 671 | /* |
|
| - | 672 | * Get ourselves a file descriptor and the corresponding vfs_file_t |
|
| - | 673 | * structure. |
|
| - | 674 | */ |
|
| - | 675 | int fd = vfs_fd_alloc(); |
|
| - | 676 | if (fd < 0) { |
|
| - | 677 | vfs_node_put(node); |
|
| - | 678 | ipc_answer_0(rid, fd); |
|
| - | 679 | return; |
|
| - | 680 | } |
|
| - | 681 | vfs_file_t *file = vfs_file_get(fd); |
|
| - | 682 | file->node = node; |
|
| - | 683 | if (oflag & O_APPEND) |
|
| - | 684 | file->append = true; |
|
| - | 685 | ||
| - | 686 | /* |
|
| - | 687 | * The following increase in reference count is for the fact that the |
|
| - | 688 | * file is being opened and that a file structure is pointing to it. |
|
| - | 689 | * It is necessary so that the file will not disappear when |
|
| - | 690 | * vfs_node_put() is called. The reference will be dropped by the |
|
| - | 691 | * respective VFS_CLOSE. |
|
| - | 692 | */ |
|
| - | 693 | vfs_node_addref(node); |
|
| - | 694 | vfs_node_put(node); |
|
| - | 695 | ||
| 617 | /* Success! Return the new file descriptor to the client. */ |
696 | /* Success! Return the new file descriptor to the client. */ |
| 618 | ipc_answer_1(rid, EOK, fd); |
697 | ipc_answer_1(rid, EOK, fd); |
| 619 | } |
698 | } |
| 620 | 699 | ||
| 621 | void vfs_close(ipc_callid_t rid, ipc_call_t *request) |
700 | void vfs_node(ipc_callid_t rid, ipc_call_t *request) |
| - | 701 | { |
|
| - | 702 | int fd = IPC_GET_ARG1(*request); |
|
| - | 703 | ||
| - | 704 | /* Lookup the file structure corresponding to the file descriptor. */ |
|
| - | 705 | vfs_file_t *file = vfs_file_get(fd); |
|
| - | 706 | if (!file) { |
|
| - | 707 | ipc_answer_0(rid, ENOENT); |
|
| - | 708 | return; |
|
| - | 709 | } |
|
| - | 710 | ||
| - | 711 | ipc_answer_3(rid, EOK, file->node->fs_handle, |
|
| - | 712 | file->node->dev_handle, file->node->index); |
|
| - | 713 | } |
|
| - | 714 | ||
| - | 715 | void vfs_device(ipc_callid_t rid, ipc_call_t *request) |
|
| 622 | { |
716 | { |
| 623 | int fd = IPC_GET_ARG1(*request); |
717 | int fd = IPC_GET_ARG1(*request); |
| - | 718 | ||
| - | 719 | /* Lookup the file structure corresponding to the file descriptor. */ |
|
| 624 | int rc = vfs_fd_free(fd); |
720 | vfs_file_t *file = vfs_file_get(fd); |
| - | 721 | if (!file) { |
|
| - | 722 | ipc_answer_0(rid, ENOENT); |
|
| - | 723 | return; |
|
| - | 724 | } |
|
| - | 725 | ||
| - | 726 | /* |
|
| - | 727 | * Lock the open file structure so that no other thread can manipulate |
|
| - | 728 | * the same open file at a time. |
|
| - | 729 | */ |
|
| - | 730 | futex_down(&file->lock); |
|
| - | 731 | int fs_phone = vfs_grab_phone(file->node->fs_handle); |
|
| - | 732 | ||
| - | 733 | /* Make a VFS_DEVICE request at the destination FS server. */ |
|
| - | 734 | aid_t msg; |
|
| - | 735 | ipc_call_t answer; |
|
| - | 736 | msg = async_send_2(fs_phone, IPC_GET_METHOD(*request), |
|
| - | 737 | file->node->dev_handle, file->node->index, &answer); |
|
| - | 738 | ||
| - | 739 | /* Wait for reply from the FS server. */ |
|
| - | 740 | ipcarg_t rc; |
|
| - | 741 | async_wait_for(msg, &rc); |
|
| - | 742 | ||
| - | 743 | vfs_release_phone(fs_phone); |
|
| - | 744 | futex_up(&file->lock); |
|
| - | 745 | ||
| - | 746 | ipc_answer_1(rid, EOK, IPC_GET_ARG1(answer)); |
|
| - | 747 | } |
|
| - | 748 | ||
| - | 749 | void vfs_sync(ipc_callid_t rid, ipc_call_t *request) |
|
| - | 750 | { |
|
| - | 751 | int fd = IPC_GET_ARG1(*request); |
|
| - | 752 | ||
| - | 753 | /* Lookup the file structure corresponding to the file descriptor. */ |
|
| - | 754 | vfs_file_t *file = vfs_file_get(fd); |
|
| - | 755 | if (!file) { |
|
| - | 756 | ipc_answer_0(rid, ENOENT); |
|
| - | 757 | return; |
|
| - | 758 | } |
|
| - | 759 | ||
| - | 760 | /* |
|
| - | 761 | * Lock the open file structure so that no other thread can manipulate |
|
| - | 762 | * the same open file at a time. |
|
| - | 763 | */ |
|
| - | 764 | futex_down(&file->lock); |
|
| - | 765 | int fs_phone = vfs_grab_phone(file->node->fs_handle); |
|
| - | 766 | ||
| - | 767 | /* Make a VFS_SYMC request at the destination FS server. */ |
|
| - | 768 | aid_t msg; |
|
| - | 769 | ipc_call_t answer; |
|
| - | 770 | msg = async_send_2(fs_phone, IPC_GET_METHOD(*request), |
|
| - | 771 | file->node->dev_handle, file->node->index, &answer); |
|
| - | 772 | ||
| - | 773 | /* Wait for reply from the FS server. */ |
|
| - | 774 | ipcarg_t rc; |
|
| - | 775 | async_wait_for(msg, &rc); |
|
| - | 776 | ||
| - | 777 | vfs_release_phone(fs_phone); |
|
| - | 778 | futex_up(&file->lock); |
|
| - | 779 | ||
| 625 | ipc_answer_0(rid, rc); |
780 | ipc_answer_0(rid, rc); |
| 626 | } |
781 | } |
| 627 | 782 | ||
| - | 783 | void vfs_close(ipc_callid_t rid, ipc_call_t *request) |
|
| - | 784 | { |
|
| - | 785 | int fd = IPC_GET_ARG1(*request); |
|
| - | 786 | ||
| - | 787 | /* Lookup the file structure corresponding to the file descriptor. */ |
|
| - | 788 | vfs_file_t *file = vfs_file_get(fd); |
|
| - | 789 | if (!file) { |
|
| - | 790 | ipc_answer_0(rid, ENOENT); |
|
| - | 791 | return; |
|
| - | 792 | } |
|
| - | 793 | ||
| - | 794 | /* |
|
| - | 795 | * Lock the open file structure so that no other thread can manipulate |
|
| - | 796 | * the same open file at a time. |
|
| - | 797 | */ |
|
| - | 798 | futex_down(&file->lock); |
|
| - | 799 | ||
| - | 800 | int fs_phone = vfs_grab_phone(file->node->fs_handle); |
|
| - | 801 | ||
| - | 802 | /* Make a VFS_CLOSE request at the destination FS server. */ |
|
| - | 803 | aid_t msg; |
|
| - | 804 | ipc_call_t answer; |
|
| - | 805 | msg = async_send_2(fs_phone, IPC_GET_METHOD(*request), |
|
| - | 806 | file->node->dev_handle, file->node->index, &answer); |
|
| - | 807 | ||
| - | 808 | /* Wait for reply from the FS server. */ |
|
| - | 809 | ipcarg_t rc; |
|
| - | 810 | async_wait_for(msg, &rc); |
|
| - | 811 | ||
| - | 812 | vfs_release_phone(fs_phone); |
|
| - | 813 | futex_up(&file->lock); |
|
| - | 814 | ||
| - | 815 | int retval = IPC_GET_ARG1(answer); |
|
| - | 816 | if (retval != EOK) |
|
| - | 817 | ipc_answer_0(rid, retval); |
|
| - | 818 | ||
| - | 819 | retval = vfs_fd_free(fd); |
|
| - | 820 | ipc_answer_0(rid, retval); |
|
| - | 821 | } |
|
| - | 822 | ||
| 628 | static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read) |
823 | static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read) |
| 629 | { |
824 | { |
| 630 | 825 | ||
| 631 | /* |
826 | /* |
| 632 | * The following code strongly depends on the fact that the files data |
827 | * The following code strongly depends on the fact that the files data |
| Line 703... | Line 898... | ||
| 703 | * ourselves. Note that call arguments are immutable in this case so we |
898 | * ourselves. Note that call arguments are immutable in this case so we |
| 704 | * don't have to bother. |
899 | * don't have to bother. |
| 705 | */ |
900 | */ |
| 706 | ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
901 | ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); |
| 707 | 902 | ||
| 708 | vfs_release_phone(fs_phone); |
- | |
| 709 | - | ||
| 710 | /* Wait for reply from the FS server. */ |
903 | /* Wait for reply from the FS server. */ |
| 711 | ipcarg_t rc; |
904 | ipcarg_t rc; |
| 712 | async_wait_for(msg, &rc); |
905 | async_wait_for(msg, &rc); |
| - | 906 | ||
| - | 907 | vfs_release_phone(fs_phone); |
|
| - | 908 | ||
| 713 | size_t bytes = IPC_GET_ARG1(answer); |
909 | size_t bytes = IPC_GET_ARG1(answer); |
| 714 | 910 | ||
| 715 | if (file->node->type == VFS_NODE_DIRECTORY) |
911 | if (file->node->type == VFS_NODE_DIRECTORY) |
| 716 | rwlock_read_unlock(&namespace_rwlock); |
912 | rwlock_read_unlock(&namespace_rwlock); |
| 717 | 913 | ||
| Line 1114... | Line 1310... | ||
| 1114 | ipc_answer_0(rid, EOK); |
1310 | ipc_answer_0(rid, EOK); |
| 1115 | } |
1311 | } |
| 1116 | 1312 | ||
| 1117 | /** |
1313 | /** |
| 1118 | * @} |
1314 | * @} |
| 1119 | */ |
1315 | */ |