Rev 2752 | Rev 2766 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2752 | Rev 2763 | ||
---|---|---|---|
Line 33... | Line 33... | ||
33 | /** |
33 | /** |
34 | * @file vfs_ops.c |
34 | * @file vfs_ops.c |
35 | * @brief Operations that VFS offers to its clients. |
35 | * @brief Operations that VFS offers to its clients. |
36 | */ |
36 | */ |
37 | 37 | ||
- | 38 | #include "vfs.h" |
|
38 | #include <ipc/ipc.h> |
39 | #include <ipc/ipc.h> |
39 | #include <async.h> |
40 | #include <async.h> |
40 | #include <errno.h> |
41 | #include <errno.h> |
41 | #include <stdio.h> |
42 | #include <stdio.h> |
42 | #include <stdlib.h> |
43 | #include <stdlib.h> |
Line 48... | Line 49... | ||
48 | #include <unistd.h> |
49 | #include <unistd.h> |
49 | #include <ctype.h> |
50 | #include <ctype.h> |
50 | #include <fcntl.h> |
51 | #include <fcntl.h> |
51 | #include <assert.h> |
52 | #include <assert.h> |
52 | #include <atomic.h> |
53 | #include <atomic.h> |
53 | #include "vfs.h" |
54 | #include <vfs/canonify.h> |
54 | 55 | ||
55 | /* Forward declarations of static functions. */ |
56 | /* Forward declarations of static functions. */ |
56 | static int vfs_truncate_internal(int, int, unsigned long, size_t); |
57 | static int vfs_truncate_internal(int, int, unsigned long, size_t); |
57 | 58 | ||
58 | /** |
59 | /** |
Line 304... | Line 305... | ||
304 | if (!ipc_data_write_receive(&callid, &len)) { |
305 | if (!ipc_data_write_receive(&callid, &len)) { |
305 | ipc_answer_0(callid, EINVAL); |
306 | ipc_answer_0(callid, EINVAL); |
306 | ipc_answer_0(rid, EINVAL); |
307 | ipc_answer_0(rid, EINVAL); |
307 | return; |
308 | return; |
308 | } |
309 | } |
309 | - | ||
310 | /* |
- | |
311 | * Now we are on the verge of accepting the path. |
- | |
312 | * |
- | |
313 | * There is one optimization we could do in the future: copy the path |
- | |
314 | * directly into the PLB using some kind of a callback. |
- | |
315 | */ |
- | |
316 | char *path = malloc(len + 1); |
310 | char *path = malloc(len + 1); |
317 | - | ||
318 | if (!path) { |
311 | if (!path) { |
319 | ipc_answer_0(callid, ENOMEM); |
312 | ipc_answer_0(callid, ENOMEM); |
320 | ipc_answer_0(rid, ENOMEM); |
313 | ipc_answer_0(rid, ENOMEM); |
321 | return; |
314 | return; |
322 | } |
315 | } |
323 | - | ||
324 | int rc; |
316 | int rc; |
325 | if ((rc = ipc_data_write_finalize(callid, path, len))) { |
317 | if ((rc = ipc_data_write_finalize(callid, path, len))) { |
326 | ipc_answer_0(rid, rc); |
318 | ipc_answer_0(rid, rc); |
327 | free(path); |
319 | free(path); |
328 | return; |
320 | return; |
Line 627... | Line 619... | ||
627 | if (!ipc_data_write_receive(&callid, &len)) { |
619 | if (!ipc_data_write_receive(&callid, &len)) { |
628 | ipc_answer_0(callid, EINVAL); |
620 | ipc_answer_0(callid, EINVAL); |
629 | ipc_answer_0(rid, EINVAL); |
621 | ipc_answer_0(rid, EINVAL); |
630 | return; |
622 | return; |
631 | } |
623 | } |
632 | - | ||
633 | /* |
- | |
634 | * Now we are on the verge of accepting the path. |
- | |
635 | * |
- | |
636 | * There is one optimization we could do in the future: copy the path |
- | |
637 | * directly into the PLB using some kind of a callback. |
- | |
638 | */ |
- | |
639 | char *path = malloc(len + 1); |
624 | char *path = malloc(len + 1); |
640 | - | ||
641 | if (!path) { |
625 | if (!path) { |
642 | ipc_answer_0(callid, ENOMEM); |
626 | ipc_answer_0(callid, ENOMEM); |
643 | ipc_answer_0(rid, ENOMEM); |
627 | ipc_answer_0(rid, ENOMEM); |
644 | return; |
628 | return; |
645 | } |
629 | } |
646 | - | ||
647 | int rc; |
630 | int rc; |
648 | if ((rc = ipc_data_write_finalize(callid, path, len))) { |
631 | if ((rc = ipc_data_write_finalize(callid, path, len))) { |
649 | ipc_answer_0(rid, rc); |
632 | ipc_answer_0(rid, rc); |
650 | free(path); |
633 | free(path); |
651 | return; |
634 | return; |
Line 670... | Line 653... | ||
670 | if (!ipc_data_write_receive(&callid, &len)) { |
653 | if (!ipc_data_write_receive(&callid, &len)) { |
671 | ipc_answer_0(callid, EINVAL); |
654 | ipc_answer_0(callid, EINVAL); |
672 | ipc_answer_0(rid, EINVAL); |
655 | ipc_answer_0(rid, EINVAL); |
673 | return; |
656 | return; |
674 | } |
657 | } |
675 | - | ||
676 | /* |
- | |
677 | * Now we are on the verge of accepting the path. |
- | |
678 | * |
- | |
679 | * There is one optimization we could do in the future: copy the path |
- | |
680 | * directly into the PLB using some kind of a callback. |
- | |
681 | */ |
- | |
682 | char *path = malloc(len + 1); |
658 | char *path = malloc(len + 1); |
683 | - | ||
684 | if (!path) { |
659 | if (!path) { |
685 | ipc_answer_0(callid, ENOMEM); |
660 | ipc_answer_0(callid, ENOMEM); |
686 | ipc_answer_0(rid, ENOMEM); |
661 | ipc_answer_0(rid, ENOMEM); |
687 | return; |
662 | return; |
688 | } |
663 | } |
689 | - | ||
690 | int rc; |
664 | int rc; |
691 | if ((rc = ipc_data_write_finalize(callid, path, len))) { |
665 | if ((rc = ipc_data_write_finalize(callid, path, len))) { |
692 | ipc_answer_0(rid, rc); |
666 | ipc_answer_0(rid, rc); |
693 | free(path); |
667 | free(path); |
694 | return; |
668 | return; |
Line 696... | Line 670... | ||
696 | path[len] = '\0'; |
670 | path[len] = '\0'; |
697 | 671 | ||
698 | rwlock_write_lock(&namespace_rwlock); |
672 | rwlock_write_lock(&namespace_rwlock); |
699 | lflag &= L_DIRECTORY; /* sanitize lflag */ |
673 | lflag &= L_DIRECTORY; /* sanitize lflag */ |
700 | vfs_lookup_res_t lr; |
674 | vfs_lookup_res_t lr; |
701 | rc = vfs_lookup_internal(path, lflag | L_DESTROY, &lr, NULL); |
675 | rc = vfs_lookup_internal(path, lflag | L_UNLINK, &lr, NULL); |
702 | free(path); |
676 | free(path); |
703 | if (rc != EOK) { |
677 | if (rc != EOK) { |
704 | rwlock_write_unlock(&namespace_rwlock); |
678 | rwlock_write_unlock(&namespace_rwlock); |
705 | ipc_answer_0(rid, rc); |
679 | ipc_answer_0(rid, rc); |
706 | return; |
680 | return; |
Line 716... | Line 690... | ||
716 | rwlock_write_unlock(&namespace_rwlock); |
690 | rwlock_write_unlock(&namespace_rwlock); |
717 | vfs_node_put(node); |
691 | vfs_node_put(node); |
718 | ipc_answer_0(rid, EOK); |
692 | ipc_answer_0(rid, EOK); |
719 | } |
693 | } |
720 | 694 | ||
- | 695 | void vfs_rename(ipc_callid_t rid, ipc_call_t *request) |
|
- | 696 | { |
|
- | 697 | size_t len; |
|
- | 698 | ipc_callid_t callid; |
|
- | 699 | int rc; |
|
- | 700 | ||
- | 701 | /* Retrieve the old path. */ |
|
- | 702 | if (!ipc_data_write_receive(&callid, &len)) { |
|
- | 703 | ipc_answer_0(callid, EINVAL); |
|
- | 704 | ipc_answer_0(rid, EINVAL); |
|
- | 705 | return; |
|
- | 706 | } |
|
- | 707 | char *old = malloc(len + 1); |
|
- | 708 | if (!old) { |
|
- | 709 | ipc_answer_0(callid, ENOMEM); |
|
- | 710 | ipc_answer_0(rid, ENOMEM); |
|
- | 711 | return; |
|
- | 712 | } |
|
- | 713 | if ((rc = ipc_data_write_finalize(callid, old, len))) { |
|
- | 714 | ipc_answer_0(rid, rc); |
|
- | 715 | free(old); |
|
- | 716 | return; |
|
- | 717 | } |
|
- | 718 | old[len] = '\0'; |
|
- | 719 | ||
- | 720 | /* Retrieve the new path. */ |
|
- | 721 | if (!ipc_data_write_receive(&callid, &len)) { |
|
- | 722 | ipc_answer_0(callid, EINVAL); |
|
- | 723 | ipc_answer_0(rid, EINVAL); |
|
- | 724 | free(old); |
|
- | 725 | return; |
|
- | 726 | } |
|
- | 727 | char *new = malloc(len + 1); |
|
- | 728 | if (!new) { |
|
- | 729 | ipc_answer_0(callid, ENOMEM); |
|
- | 730 | ipc_answer_0(rid, ENOMEM); |
|
- | 731 | free(old); |
|
- | 732 | return; |
|
- | 733 | } |
|
- | 734 | if ((rc = ipc_data_write_finalize(callid, new, len))) { |
|
- | 735 | ipc_answer_0(rid, rc); |
|
- | 736 | free(old); |
|
- | 737 | free(new); |
|
- | 738 | return; |
|
- | 739 | } |
|
- | 740 | new[len] = '\0'; |
|
- | 741 | ||
- | 742 | char *oldc = canonify(old, &len); |
|
- | 743 | char *newc = canonify(new, NULL); |
|
- | 744 | if (!oldc || !newc) { |
|
- | 745 | ipc_answer_0(rid, EINVAL); |
|
- | 746 | free(old); |
|
- | 747 | free(new); |
|
- | 748 | return; |
|
- | 749 | } |
|
- | 750 | if (!strncmp(newc, oldc, len)) { |
|
- | 751 | /* oldc is a prefix of newc */ |
|
- | 752 | ipc_answer_0(rid, EINVAL); |
|
- | 753 | free(old); |
|
- | 754 | free(new); |
|
- | 755 | return; |
|
- | 756 | } |
|
- | 757 | ||
- | 758 | vfs_lookup_res_t old_lr; |
|
- | 759 | vfs_lookup_res_t new_lr; |
|
- | 760 | vfs_lookup_res_t new_par_lr; |
|
- | 761 | rwlock_write_lock(&namespace_rwlock); |
|
- | 762 | /* Lookup the node belonging to the old file name. */ |
|
- | 763 | rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL); |
|
- | 764 | if (rc != EOK) { |
|
- | 765 | rwlock_write_unlock(&namespace_rwlock); |
|
- | 766 | ipc_answer_0(rid, rc); |
|
- | 767 | free(old); |
|
- | 768 | free(new); |
|
- | 769 | return; |
|
- | 770 | } |
|
- | 771 | vfs_node_t *old_node = vfs_node_get(&old_lr); |
|
- | 772 | if (!old_node) { |
|
- | 773 | rwlock_write_unlock(&namespace_rwlock); |
|
- | 774 | ipc_answer_0(rid, ENOMEM); |
|
- | 775 | free(old); |
|
- | 776 | free(new); |
|
- | 777 | return; |
|
- | 778 | } |
|
- | 779 | /* Lookup parent of the new file name. */ |
|
- | 780 | rc = vfs_lookup_internal(newc, L_PARENT, &new_par_lr, NULL); |
|
- | 781 | if (rc != EOK) { |
|
- | 782 | rwlock_write_unlock(&namespace_rwlock); |
|
- | 783 | ipc_answer_0(rid, rc); |
|
- | 784 | free(old); |
|
- | 785 | free(new); |
|
- | 786 | return; |
|
- | 787 | } |
|
- | 788 | /* Check whether linking to the same file system instance. */ |
|
- | 789 | if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) || |
|
- | 790 | (old_node->dev_handle != new_par_lr.triplet.dev_handle)) { |
|
- | 791 | rwlock_write_unlock(&namespace_rwlock); |
|
- | 792 | ipc_answer_0(rid, EXDEV); /* different file systems */ |
|
- | 793 | free(old); |
|
- | 794 | free(new); |
|
- | 795 | return; |
|
- | 796 | } |
|
- | 797 | /* Destroy the old link for the new name. */ |
|
- | 798 | vfs_node_t *new_node = NULL; |
|
- | 799 | rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL); |
|
- | 800 | switch (rc) { |
|
- | 801 | case ENOENT: |
|
- | 802 | /* simply not in our way */ |
|
- | 803 | break; |
|
- | 804 | case EOK: |
|
- | 805 | new_node = vfs_node_get(&new_lr); |
|
- | 806 | if (!new_node) { |
|
- | 807 | rwlock_write_unlock(&namespace_rwlock); |
|
- | 808 | ipc_answer_0(rid, ENOMEM); |
|
- | 809 | free(old); |
|
- | 810 | free(new); |
|
- | 811 | return; |
|
- | 812 | } |
|
- | 813 | new_node->lnkcnt--; |
|
- | 814 | break; |
|
- | 815 | default: |
|
- | 816 | rwlock_write_unlock(&namespace_rwlock); |
|
- | 817 | ipc_answer_0(rid, ENOTEMPTY); |
|
- | 818 | free(old); |
|
- | 819 | free(new); |
|
- | 820 | return; |
|
- | 821 | } |
|
- | 822 | /* Create the new link for the new name. */ |
|
- | 823 | rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index); |
|
- | 824 | if (rc != EOK) { |
|
- | 825 | rwlock_write_unlock(&namespace_rwlock); |
|
- | 826 | if (new_node) |
|
- | 827 | vfs_node_put(new_node); |
|
- | 828 | ipc_answer_0(rid, rc); |
|
- | 829 | free(old); |
|
- | 830 | free(new); |
|
- | 831 | return; |
|
- | 832 | } |
|
- | 833 | old_node->lnkcnt++; |
|
- | 834 | /* Destroy the link for the old name. */ |
|
- | 835 | rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL); |
|
- | 836 | if (rc != EOK) { |
|
- | 837 | rwlock_write_unlock(&namespace_rwlock); |
|
- | 838 | vfs_node_put(old_node); |
|
- | 839 | if (new_node) |
|
- | 840 | vfs_node_put(new_node); |
|
- | 841 | ipc_answer_0(rid, rc); |
|
- | 842 | free(old); |
|
- | 843 | free(new); |
|
- | 844 | return; |
|
- | 845 | } |
|
- | 846 | old_node->lnkcnt--; |
|
- | 847 | rwlock_write_unlock(&namespace_rwlock); |
|
- | 848 | vfs_node_put(old_node); |
|
- | 849 | if (new_node) |
|
- | 850 | vfs_node_put(new_node); |
|
- | 851 | free(old); |
|
- | 852 | free(new); |
|
- | 853 | ipc_answer_0(rid, EOK); |
|
- | 854 | } |
|
- | 855 | ||
721 | /** |
856 | /** |
722 | * @} |
857 | * @} |
723 | */ |
858 | */ |