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 | */ |