| @@ -657,2070 +657,2095 @@ setup_suitable_read_buffer(struct archiv | | | @@ -657,2070 +657,2095 @@ setup_suitable_read_buffer(struct archiv |
657 | while (asize < 1024*64) | | 657 | while (asize < 1024*64) |
658 | asize += incr; | | 658 | asize += incr; |
659 | /* Take a margin to adjust to the filesystem | | 659 | /* Take a margin to adjust to the filesystem |
660 | * alignment. */ | | 660 | * alignment. */ |
661 | asize += xfer_align; | | 661 | asize += xfer_align; |
662 | } | | 662 | } |
663 | cf->allocation_ptr = malloc(asize); | | 663 | cf->allocation_ptr = malloc(asize); |
664 | if (cf->allocation_ptr == NULL) { | | 664 | if (cf->allocation_ptr == NULL) { |
665 | archive_set_error(&a->archive, ENOMEM, | | 665 | archive_set_error(&a->archive, ENOMEM, |
666 | "Couldn't allocate memory"); | | 666 | "Couldn't allocate memory"); |
667 | a->archive.state = ARCHIVE_STATE_FATAL; | | 667 | a->archive.state = ARCHIVE_STATE_FATAL; |
668 | return (ARCHIVE_FATAL); | | 668 | return (ARCHIVE_FATAL); |
669 | } | | 669 | } |
670 | | | 670 | |
671 | /* | | 671 | /* |
672 | * Calculate proper address for the filesystem. | | 672 | * Calculate proper address for the filesystem. |
673 | */ | | 673 | */ |
674 | s = (uintptr_t)cf->allocation_ptr; | | 674 | s = (uintptr_t)cf->allocation_ptr; |
675 | s %= xfer_align; | | 675 | s %= xfer_align; |
676 | if (s > 0) | | 676 | if (s > 0) |
677 | s = xfer_align - s; | | 677 | s = xfer_align - s; |
678 | | | 678 | |
679 | /* | | 679 | /* |
680 | * Set a read buffer pointer in the proper alignment of | | 680 | * Set a read buffer pointer in the proper alignment of |
681 | * the current filesystem. | | 681 | * the current filesystem. |
682 | */ | | 682 | */ |
683 | cf->buff = cf->allocation_ptr + s; | | 683 | cf->buff = cf->allocation_ptr + s; |
684 | cf->buff_size = asize - xfer_align; | | 684 | cf->buff_size = asize - xfer_align; |
685 | } | | 685 | } |
686 | return (ARCHIVE_OK); | | 686 | return (ARCHIVE_OK); |
687 | } | | 687 | } |
688 | | | 688 | |
689 | static int | | 689 | static int |
690 | _archive_read_data_block(struct archive *_a, const void **buff, | | 690 | _archive_read_data_block(struct archive *_a, const void **buff, |
691 | size_t *size, int64_t *offset) | | 691 | size_t *size, int64_t *offset) |
692 | { | | 692 | { |
693 | struct archive_read_disk *a = (struct archive_read_disk *)_a; | | 693 | struct archive_read_disk *a = (struct archive_read_disk *)_a; |
694 | struct tree *t = a->tree; | | 694 | struct tree *t = a->tree; |
695 | int r; | | 695 | int r; |
696 | ssize_t bytes; | | 696 | ssize_t bytes; |
697 | size_t buffbytes; | | 697 | size_t buffbytes; |
698 | int empty_sparse_region = 0; | | 698 | int empty_sparse_region = 0; |
699 | | | 699 | |
700 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, | | 700 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, |
701 | "archive_read_data_block"); | | 701 | "archive_read_data_block"); |
702 | | | 702 | |
703 | if (t->entry_eof || t->entry_remaining_bytes <= 0) { | | 703 | if (t->entry_eof || t->entry_remaining_bytes <= 0) { |
704 | r = ARCHIVE_EOF; | | 704 | r = ARCHIVE_EOF; |
705 | goto abort_read_data; | | 705 | goto abort_read_data; |
706 | } | | 706 | } |
707 | | | 707 | |
708 | /* | | 708 | /* |
709 | * Open the current file. | | 709 | * Open the current file. |
710 | */ | | 710 | */ |
711 | if (t->entry_fd < 0) { | | 711 | if (t->entry_fd < 0) { |
712 | int flags = O_RDONLY | O_BINARY | O_CLOEXEC; | | 712 | int flags = O_RDONLY | O_BINARY | O_CLOEXEC; |
713 | | | 713 | |
714 | /* | | 714 | /* |
715 | * Eliminate or reduce cache effects if we can. | | 715 | * Eliminate or reduce cache effects if we can. |
716 | * | | 716 | * |
717 | * Carefully consider this to be enabled. | | 717 | * Carefully consider this to be enabled. |
718 | */ | | 718 | */ |
719 | #if defined(O_DIRECT) && 0/* Disabled for now */ | | 719 | #if defined(O_DIRECT) && 0/* Disabled for now */ |
720 | if (t->current_filesystem->xfer_align != -1 && | | 720 | if (t->current_filesystem->xfer_align != -1 && |
721 | t->nlink == 1) | | 721 | t->nlink == 1) |
722 | flags |= O_DIRECT; | | 722 | flags |= O_DIRECT; |
723 | #endif | | 723 | #endif |
724 | #if defined(O_NOATIME) | | 724 | #if defined(O_NOATIME) |
725 | /* | | 725 | /* |
726 | * Linux has O_NOATIME flag; use it if we need. | | 726 | * Linux has O_NOATIME flag; use it if we need. |
727 | */ | | 727 | */ |
728 | if ((t->flags & needsRestoreTimes) != 0 && | | 728 | if ((t->flags & needsRestoreTimes) != 0 && |
729 | t->restore_time.noatime == 0) | | 729 | t->restore_time.noatime == 0) |
730 | flags |= O_NOATIME; | | 730 | flags |= O_NOATIME; |
731 | do { | | 731 | do { |
732 | #endif | | 732 | #endif |
733 | t->entry_fd = open_on_current_dir(t, | | 733 | t->entry_fd = open_on_current_dir(t, |
734 | tree_current_access_path(t), flags); | | 734 | tree_current_access_path(t), flags); |
735 | __archive_ensure_cloexec_flag(t->entry_fd); | | 735 | __archive_ensure_cloexec_flag(t->entry_fd); |
736 | #if defined(O_NOATIME) | | 736 | #if defined(O_NOATIME) |
737 | /* | | 737 | /* |
738 | * When we did open the file with O_NOATIME flag, | | 738 | * When we did open the file with O_NOATIME flag, |
739 | * if successful, set 1 to t->restore_time.noatime | | 739 | * if successful, set 1 to t->restore_time.noatime |
740 | * not to restore an atime of the file later. | | 740 | * not to restore an atime of the file later. |
741 | * if failed by EPERM, retry it without O_NOATIME flag. | | 741 | * if failed by EPERM, retry it without O_NOATIME flag. |
742 | */ | | 742 | */ |
743 | if (flags & O_NOATIME) { | | 743 | if (flags & O_NOATIME) { |
744 | if (t->entry_fd >= 0) | | 744 | if (t->entry_fd >= 0) |
745 | t->restore_time.noatime = 1; | | 745 | t->restore_time.noatime = 1; |
746 | else if (errno == EPERM) { | | 746 | else if (errno == EPERM) { |
747 | flags &= ~O_NOATIME; | | 747 | flags &= ~O_NOATIME; |
748 | continue; | | 748 | continue; |
749 | } | | 749 | } |
750 | } | | 750 | } |
751 | } while (0); | | 751 | } while (0); |
752 | #endif | | 752 | #endif |
753 | if (t->entry_fd < 0) { | | 753 | if (t->entry_fd < 0) { |
754 | archive_set_error(&a->archive, errno, | | 754 | archive_set_error(&a->archive, errno, |
755 | "Couldn't open %s", tree_current_path(t)); | | 755 | "Couldn't open %s", tree_current_path(t)); |
756 | r = ARCHIVE_FAILED; | | 756 | r = ARCHIVE_FAILED; |
757 | tree_enter_initial_dir(t); | | 757 | tree_enter_initial_dir(t); |
758 | goto abort_read_data; | | 758 | goto abort_read_data; |
759 | } | | 759 | } |
760 | tree_enter_initial_dir(t); | | 760 | tree_enter_initial_dir(t); |
761 | } | | 761 | } |
762 | | | 762 | |
763 | /* | | 763 | /* |
764 | * Allocate read buffer if not allocated. | | 764 | * Allocate read buffer if not allocated. |
765 | */ | | 765 | */ |
766 | if (t->current_filesystem->allocation_ptr == NULL) { | | 766 | if (t->current_filesystem->allocation_ptr == NULL) { |
767 | r = setup_suitable_read_buffer(a); | | 767 | r = setup_suitable_read_buffer(a); |
768 | if (r != ARCHIVE_OK) { | | 768 | if (r != ARCHIVE_OK) { |
769 | a->archive.state = ARCHIVE_STATE_FATAL; | | 769 | a->archive.state = ARCHIVE_STATE_FATAL; |
770 | goto abort_read_data; | | 770 | goto abort_read_data; |
771 | } | | 771 | } |
772 | } | | 772 | } |
773 | t->entry_buff = t->current_filesystem->buff; | | 773 | t->entry_buff = t->current_filesystem->buff; |
774 | t->entry_buff_size = t->current_filesystem->buff_size; | | 774 | t->entry_buff_size = t->current_filesystem->buff_size; |
775 | | | 775 | |
776 | buffbytes = t->entry_buff_size; | | 776 | buffbytes = t->entry_buff_size; |
777 | if ((int64_t)buffbytes > t->current_sparse->length) | | 777 | if ((int64_t)buffbytes > t->current_sparse->length) |
778 | buffbytes = t->current_sparse->length; | | 778 | buffbytes = t->current_sparse->length; |
779 | | | 779 | |
780 | if (t->current_sparse->length == 0) | | 780 | if (t->current_sparse->length == 0) |
781 | empty_sparse_region = 1; | | 781 | empty_sparse_region = 1; |
782 | | | 782 | |
783 | /* | | 783 | /* |
784 | * Skip hole. | | 784 | * Skip hole. |
785 | * TODO: Should we consider t->current_filesystem->xfer_align? | | 785 | * TODO: Should we consider t->current_filesystem->xfer_align? |
786 | */ | | 786 | */ |
787 | if (t->current_sparse->offset > t->entry_total) { | | 787 | if (t->current_sparse->offset > t->entry_total) { |
788 | if (lseek(t->entry_fd, | | 788 | if (lseek(t->entry_fd, |
789 | (off_t)t->current_sparse->offset, SEEK_SET) < 0) { | | 789 | (off_t)t->current_sparse->offset, SEEK_SET) < 0) { |
790 | archive_set_error(&a->archive, errno, "Seek error"); | | 790 | archive_set_error(&a->archive, errno, "Seek error"); |
791 | r = ARCHIVE_FATAL; | | 791 | r = ARCHIVE_FATAL; |
792 | a->archive.state = ARCHIVE_STATE_FATAL; | | 792 | a->archive.state = ARCHIVE_STATE_FATAL; |
793 | goto abort_read_data; | | 793 | goto abort_read_data; |
794 | } | | 794 | } |
795 | bytes = t->current_sparse->offset - t->entry_total; | | 795 | bytes = t->current_sparse->offset - t->entry_total; |
796 | t->entry_remaining_bytes -= bytes; | | 796 | t->entry_remaining_bytes -= bytes; |
797 | t->entry_total += bytes; | | 797 | t->entry_total += bytes; |
798 | } | | 798 | } |
799 | | | 799 | |
800 | /* | | 800 | /* |
801 | * Read file contents. | | 801 | * Read file contents. |
802 | */ | | 802 | */ |
803 | if (buffbytes > 0) { | | 803 | if (buffbytes > 0) { |
804 | bytes = read(t->entry_fd, t->entry_buff, buffbytes); | | 804 | bytes = read(t->entry_fd, t->entry_buff, buffbytes); |
805 | if (bytes < 0) { | | 805 | if (bytes < 0) { |
806 | archive_set_error(&a->archive, errno, "Read error"); | | 806 | archive_set_error(&a->archive, errno, "Read error"); |
807 | r = ARCHIVE_FATAL; | | 807 | r = ARCHIVE_FATAL; |
808 | a->archive.state = ARCHIVE_STATE_FATAL; | | 808 | a->archive.state = ARCHIVE_STATE_FATAL; |
809 | goto abort_read_data; | | 809 | goto abort_read_data; |
810 | } | | 810 | } |
811 | } else | | 811 | } else |
812 | bytes = 0; | | 812 | bytes = 0; |
813 | /* | | 813 | /* |
814 | * Return an EOF unless we've read a leading empty sparse region, which | | 814 | * Return an EOF unless we've read a leading empty sparse region, which |
815 | * is used to represent fully-sparse files. | | 815 | * is used to represent fully-sparse files. |
816 | */ | | 816 | */ |
817 | if (bytes == 0 && !empty_sparse_region) { | | 817 | if (bytes == 0 && !empty_sparse_region) { |
818 | /* Get EOF */ | | 818 | /* Get EOF */ |
819 | t->entry_eof = 1; | | 819 | t->entry_eof = 1; |
820 | r = ARCHIVE_EOF; | | 820 | r = ARCHIVE_EOF; |
821 | goto abort_read_data; | | 821 | goto abort_read_data; |
822 | } | | 822 | } |
823 | *buff = t->entry_buff; | | 823 | *buff = t->entry_buff; |
824 | *size = bytes; | | 824 | *size = bytes; |
825 | *offset = t->entry_total; | | 825 | *offset = t->entry_total; |
826 | t->entry_total += bytes; | | 826 | t->entry_total += bytes; |
827 | t->entry_remaining_bytes -= bytes; | | 827 | t->entry_remaining_bytes -= bytes; |
828 | if (t->entry_remaining_bytes == 0) { | | 828 | if (t->entry_remaining_bytes == 0) { |
829 | /* Close the current file descriptor */ | | 829 | /* Close the current file descriptor */ |
830 | close_and_restore_time(t->entry_fd, t, &t->restore_time); | | 830 | close_and_restore_time(t->entry_fd, t, &t->restore_time); |
831 | t->entry_fd = -1; | | 831 | t->entry_fd = -1; |
832 | t->entry_eof = 1; | | 832 | t->entry_eof = 1; |
833 | } | | 833 | } |
834 | t->current_sparse->offset += bytes; | | 834 | t->current_sparse->offset += bytes; |
835 | t->current_sparse->length -= bytes; | | 835 | t->current_sparse->length -= bytes; |
836 | if (t->current_sparse->length == 0 && !t->entry_eof) | | 836 | if (t->current_sparse->length == 0 && !t->entry_eof) |
837 | t->current_sparse++; | | 837 | t->current_sparse++; |
838 | return (ARCHIVE_OK); | | 838 | return (ARCHIVE_OK); |
839 | | | 839 | |
840 | abort_read_data: | | 840 | abort_read_data: |
841 | *buff = NULL; | | 841 | *buff = NULL; |
842 | *size = 0; | | 842 | *size = 0; |
843 | *offset = t->entry_total; | | 843 | *offset = t->entry_total; |
844 | if (t->entry_fd >= 0) { | | 844 | if (t->entry_fd >= 0) { |
845 | /* Close the current file descriptor */ | | 845 | /* Close the current file descriptor */ |
846 | close_and_restore_time(t->entry_fd, t, &t->restore_time); | | 846 | close_and_restore_time(t->entry_fd, t, &t->restore_time); |
847 | t->entry_fd = -1; | | 847 | t->entry_fd = -1; |
848 | } | | 848 | } |
849 | return (r); | | 849 | return (r); |
850 | } | | 850 | } |
851 | | | 851 | |
852 | static int | | 852 | static int |
853 | next_entry(struct archive_read_disk *a, struct tree *t, | | 853 | next_entry(struct archive_read_disk *a, struct tree *t, |
854 | struct archive_entry *entry) | | 854 | struct archive_entry *entry) |
855 | { | | 855 | { |
856 | const struct stat *st; /* info to use for this entry */ | | 856 | const struct stat *st; /* info to use for this entry */ |
857 | const struct stat *lst;/* lstat() information */ | | 857 | const struct stat *lst;/* lstat() information */ |
858 | const char *name; | | 858 | const char *name; |
859 | int delayed, delayed_errno, descend, r; | | 859 | int delayed, delayed_errno, descend, r; |
860 | struct archive_string delayed_str; | | 860 | struct archive_string delayed_str; |
861 | | | 861 | |
862 | delayed = ARCHIVE_OK; | | 862 | delayed = ARCHIVE_OK; |
863 | delayed_errno = 0; | | 863 | delayed_errno = 0; |
864 | archive_string_init(&delayed_str); | | 864 | archive_string_init(&delayed_str); |
865 | | | 865 | |
866 | st = NULL; | | 866 | st = NULL; |
867 | lst = NULL; | | 867 | lst = NULL; |
868 | t->descend = 0; | | 868 | t->descend = 0; |
869 | do { | | 869 | do { |
870 | switch (tree_next(t)) { | | 870 | switch (tree_next(t)) { |
871 | case TREE_ERROR_FATAL: | | 871 | case TREE_ERROR_FATAL: |
872 | archive_set_error(&a->archive, t->tree_errno, | | 872 | archive_set_error(&a->archive, t->tree_errno, |
873 | "%s: Unable to continue traversing directory tree", | | 873 | "%s: Unable to continue traversing directory tree", |
874 | tree_current_path(t)); | | 874 | tree_current_path(t)); |
875 | a->archive.state = ARCHIVE_STATE_FATAL; | | 875 | a->archive.state = ARCHIVE_STATE_FATAL; |
876 | tree_enter_initial_dir(t); | | 876 | tree_enter_initial_dir(t); |
877 | return (ARCHIVE_FATAL); | | 877 | return (ARCHIVE_FATAL); |
878 | case TREE_ERROR_DIR: | | 878 | case TREE_ERROR_DIR: |
879 | archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, | | 879 | archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, |
880 | "%s: Couldn't visit directory", | | 880 | "%s: Couldn't visit directory", |
881 | tree_current_path(t)); | | 881 | tree_current_path(t)); |
882 | tree_enter_initial_dir(t); | | 882 | tree_enter_initial_dir(t); |
883 | return (ARCHIVE_FAILED); | | 883 | return (ARCHIVE_FAILED); |
884 | case 0: | | 884 | case 0: |
885 | tree_enter_initial_dir(t); | | 885 | tree_enter_initial_dir(t); |
886 | return (ARCHIVE_EOF); | | 886 | return (ARCHIVE_EOF); |
887 | case TREE_POSTDESCENT: | | 887 | case TREE_POSTDESCENT: |
888 | case TREE_POSTASCENT: | | 888 | case TREE_POSTASCENT: |
889 | break; | | 889 | break; |
890 | case TREE_REGULAR: | | 890 | case TREE_REGULAR: |
891 | lst = tree_current_lstat(t); | | 891 | lst = tree_current_lstat(t); |
892 | if (lst == NULL) { | | 892 | if (lst == NULL) { |
893 | if (errno == ENOENT && t->depth > 0) { | | 893 | if (errno == ENOENT && t->depth > 0) { |
894 | delayed = ARCHIVE_WARN; | | 894 | delayed = ARCHIVE_WARN; |
895 | delayed_errno = errno; | | 895 | delayed_errno = errno; |
896 | if (delayed_str.length == 0) { | | 896 | if (delayed_str.length == 0) { |
897 | archive_string_sprintf(&delayed_str, | | 897 | archive_string_sprintf(&delayed_str, |
898 | "%s", tree_current_path(t)); | | 898 | "%s", tree_current_path(t)); |
899 | } else { | | 899 | } else { |
900 | archive_string_sprintf(&delayed_str, | | 900 | archive_string_sprintf(&delayed_str, |
901 | " %s", tree_current_path(t)); | | 901 | " %s", tree_current_path(t)); |
902 | } | | 902 | } |
903 | } else { | | 903 | } else { |
904 | archive_set_error(&a->archive, errno, | | 904 | archive_set_error(&a->archive, errno, |
905 | "%s: Cannot stat", | | 905 | "%s: Cannot stat", |
906 | tree_current_path(t)); | | 906 | tree_current_path(t)); |
907 | tree_enter_initial_dir(t); | | 907 | tree_enter_initial_dir(t); |
908 | return (ARCHIVE_FAILED); | | 908 | return (ARCHIVE_FAILED); |
909 | } | | 909 | } |
910 | } | | 910 | } |
911 | break; | | 911 | break; |
912 | } | | 912 | } |
913 | } while (lst == NULL); | | 913 | } while (lst == NULL); |
914 | | | 914 | |
915 | #ifdef __APPLE__ | | 915 | #ifdef __APPLE__ |
916 | if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) { | | 916 | if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) { |
917 | /* If we're using copyfile(), ignore "._XXX" files. */ | | 917 | /* If we're using copyfile(), ignore "._XXX" files. */ |
918 | const char *bname = strrchr(tree_current_path(t), '/'); | | 918 | const char *bname = strrchr(tree_current_path(t), '/'); |
919 | if (bname == NULL) | | 919 | if (bname == NULL) |
920 | bname = tree_current_path(t); | | 920 | bname = tree_current_path(t); |
921 | else | | 921 | else |
922 | ++bname; | | 922 | ++bname; |
923 | if (bname[0] == '.' && bname[1] == '_') | | 923 | if (bname[0] == '.' && bname[1] == '_') |
924 | return (ARCHIVE_RETRY); | | 924 | return (ARCHIVE_RETRY); |
925 | } | | 925 | } |
926 | #endif | | 926 | #endif |
927 | | | 927 | |
928 | archive_entry_copy_pathname(entry, tree_current_path(t)); | | 928 | archive_entry_copy_pathname(entry, tree_current_path(t)); |
929 | /* | | 929 | /* |
930 | * Perform path matching. | | 930 | * Perform path matching. |
931 | */ | | 931 | */ |
932 | if (a->matching) { | | 932 | if (a->matching) { |
933 | r = archive_match_path_excluded(a->matching, entry); | | 933 | r = archive_match_path_excluded(a->matching, entry); |
934 | if (r < 0) { | | 934 | if (r < 0) { |
935 | archive_set_error(&(a->archive), errno, | | 935 | archive_set_error(&(a->archive), errno, |
936 | "Failed : %s", archive_error_string(a->matching)); | | 936 | "Failed : %s", archive_error_string(a->matching)); |
937 | return (r); | | 937 | return (r); |
938 | } | | 938 | } |
939 | if (r) { | | 939 | if (r) { |
940 | if (a->excluded_cb_func) | | 940 | if (a->excluded_cb_func) |
941 | a->excluded_cb_func(&(a->archive), | | 941 | a->excluded_cb_func(&(a->archive), |
942 | a->excluded_cb_data, entry); | | 942 | a->excluded_cb_data, entry); |
943 | return (ARCHIVE_RETRY); | | 943 | return (ARCHIVE_RETRY); |
944 | } | | 944 | } |
945 | } | | 945 | } |
946 | | | 946 | |
947 | /* | | 947 | /* |
948 | * Distinguish 'L'/'P'/'H' symlink following. | | 948 | * Distinguish 'L'/'P'/'H' symlink following. |
949 | */ | | 949 | */ |
950 | switch(t->symlink_mode) { | | 950 | switch(t->symlink_mode) { |
951 | case 'H': | | 951 | case 'H': |
952 | /* 'H': After the first item, rest like 'P'. */ | | 952 | /* 'H': After the first item, rest like 'P'. */ |
953 | t->symlink_mode = 'P'; | | 953 | t->symlink_mode = 'P'; |
954 | /* 'H': First item (from command line) like 'L'. */ | | 954 | /* 'H': First item (from command line) like 'L'. */ |
955 | /* FALLTHROUGH */ | | 955 | /* FALLTHROUGH */ |
956 | case 'L': | | 956 | case 'L': |
957 | /* 'L': Do descend through a symlink to dir. */ | | 957 | /* 'L': Do descend through a symlink to dir. */ |
958 | descend = tree_current_is_dir(t); | | 958 | descend = tree_current_is_dir(t); |
959 | /* 'L': Follow symlinks to files. */ | | 959 | /* 'L': Follow symlinks to files. */ |
960 | a->symlink_mode = 'L'; | | 960 | a->symlink_mode = 'L'; |
961 | a->follow_symlinks = 1; | | 961 | a->follow_symlinks = 1; |
962 | /* 'L': Archive symlinks as targets, if we can. */ | | 962 | /* 'L': Archive symlinks as targets, if we can. */ |
963 | st = tree_current_stat(t); | | 963 | st = tree_current_stat(t); |
964 | if (st != NULL && !tree_target_is_same_as_parent(t, st)) | | 964 | if (st != NULL && !tree_target_is_same_as_parent(t, st)) |
965 | break; | | 965 | break; |
966 | /* If stat fails, we have a broken symlink; | | 966 | /* If stat fails, we have a broken symlink; |
967 | * in that case, don't follow the link. */ | | 967 | * in that case, don't follow the link. */ |
968 | /* FALLTHROUGH */ | | 968 | /* FALLTHROUGH */ |
969 | default: | | 969 | default: |
970 | /* 'P': Don't descend through a symlink to dir. */ | | 970 | /* 'P': Don't descend through a symlink to dir. */ |
971 | descend = tree_current_is_physical_dir(t); | | 971 | descend = tree_current_is_physical_dir(t); |
972 | /* 'P': Don't follow symlinks to files. */ | | 972 | /* 'P': Don't follow symlinks to files. */ |
973 | a->symlink_mode = 'P'; | | 973 | a->symlink_mode = 'P'; |
974 | a->follow_symlinks = 0; | | 974 | a->follow_symlinks = 0; |
975 | /* 'P': Archive symlinks as symlinks. */ | | 975 | /* 'P': Archive symlinks as symlinks. */ |
976 | st = lst; | | 976 | st = lst; |
977 | break; | | 977 | break; |
978 | } | | 978 | } |
979 | | | 979 | |
980 | if (update_current_filesystem(a, st->st_dev) != ARCHIVE_OK) { | | 980 | if (update_current_filesystem(a, st->st_dev) != ARCHIVE_OK) { |
981 | a->archive.state = ARCHIVE_STATE_FATAL; | | 981 | a->archive.state = ARCHIVE_STATE_FATAL; |
982 | tree_enter_initial_dir(t); | | 982 | tree_enter_initial_dir(t); |
983 | return (ARCHIVE_FATAL); | | 983 | return (ARCHIVE_FATAL); |
984 | } | | 984 | } |
985 | if (t->initial_filesystem_id == -1) | | 985 | if (t->initial_filesystem_id == -1) |
986 | t->initial_filesystem_id = t->current_filesystem_id; | | 986 | t->initial_filesystem_id = t->current_filesystem_id; |
987 | if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) { | | 987 | if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) { |
988 | if (t->initial_filesystem_id != t->current_filesystem_id) | | 988 | if (t->initial_filesystem_id != t->current_filesystem_id) |
989 | descend = 0; | | 989 | descend = 0; |
990 | } | | 990 | } |
991 | t->descend = descend; | | 991 | t->descend = descend; |
992 | | | 992 | |
993 | /* | | 993 | /* |
994 | * Honor nodump flag. | | 994 | * Honor nodump flag. |
995 | * If the file is marked with nodump flag, do not return this entry. | | 995 | * If the file is marked with nodump flag, do not return this entry. |
996 | */ | | 996 | */ |
997 | if (a->flags & ARCHIVE_READDISK_HONOR_NODUMP) { | | 997 | if (a->flags & ARCHIVE_READDISK_HONOR_NODUMP) { |
998 | #if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) | | 998 | #if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) |
999 | if (st->st_flags & UF_NODUMP) | | 999 | if (st->st_flags & UF_NODUMP) |
1000 | return (ARCHIVE_RETRY); | | 1000 | return (ARCHIVE_RETRY); |
1001 | #elif (defined(FS_IOC_GETFLAGS) && defined(FS_NODUMP_FL) && \ | | 1001 | #elif (defined(FS_IOC_GETFLAGS) && defined(FS_NODUMP_FL) && \ |
1002 | defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \ | | 1002 | defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \ |
1003 | (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) && \ | | 1003 | (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) && \ |
1004 | defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)) | | 1004 | defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)) |
1005 | if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) { | | 1005 | if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) { |
1006 | int stflags; | | 1006 | int stflags; |
1007 | | | 1007 | |
1008 | t->entry_fd = open_on_current_dir(t, | | 1008 | t->entry_fd = open_on_current_dir(t, |
1009 | tree_current_access_path(t), | | 1009 | tree_current_access_path(t), |
1010 | O_RDONLY | O_NONBLOCK | O_CLOEXEC); | | 1010 | O_RDONLY | O_NONBLOCK | O_CLOEXEC); |
1011 | __archive_ensure_cloexec_flag(t->entry_fd); | | 1011 | __archive_ensure_cloexec_flag(t->entry_fd); |
1012 | if (t->entry_fd >= 0) { | | 1012 | if (t->entry_fd >= 0) { |
1013 | r = ioctl(t->entry_fd, | | 1013 | r = ioctl(t->entry_fd, |
1014 | #ifdef FS_IOC_GETFLAGS | | 1014 | #ifdef FS_IOC_GETFLAGS |
1015 | FS_IOC_GETFLAGS, | | 1015 | FS_IOC_GETFLAGS, |
1016 | #else | | 1016 | #else |
1017 | EXT2_IOC_GETFLAGS, | | 1017 | EXT2_IOC_GETFLAGS, |
1018 | #endif | | 1018 | #endif |
1019 | &stflags); | | 1019 | &stflags); |
1020 | #ifdef FS_NODUMP_FL | | 1020 | #ifdef FS_NODUMP_FL |
1021 | if (r == 0 && (stflags & FS_NODUMP_FL) != 0) | | 1021 | if (r == 0 && (stflags & FS_NODUMP_FL) != 0) |
1022 | #else | | 1022 | #else |
1023 | if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0) | | 1023 | if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0) |
1024 | #endif | | 1024 | #endif |
1025 | return (ARCHIVE_RETRY); | | 1025 | return (ARCHIVE_RETRY); |
1026 | } | | 1026 | } |
1027 | } | | 1027 | } |
1028 | #endif | | 1028 | #endif |
1029 | } | | 1029 | } |
1030 | | | 1030 | |
1031 | archive_entry_copy_stat(entry, st); | | 1031 | archive_entry_copy_stat(entry, st); |
1032 | | | 1032 | |
1033 | /* Save the times to be restored. This must be in before | | 1033 | /* Save the times to be restored. This must be in before |
1034 | * calling archive_read_disk_descend() or any chance of it, | | 1034 | * calling archive_read_disk_descend() or any chance of it, |
1035 | * especially, invoking a callback. */ | | 1035 | * especially, invoking a callback. */ |
1036 | t->restore_time.mtime = archive_entry_mtime(entry); | | 1036 | t->restore_time.mtime = archive_entry_mtime(entry); |
1037 | t->restore_time.mtime_nsec = archive_entry_mtime_nsec(entry); | | 1037 | t->restore_time.mtime_nsec = archive_entry_mtime_nsec(entry); |
1038 | t->restore_time.atime = archive_entry_atime(entry); | | 1038 | t->restore_time.atime = archive_entry_atime(entry); |
1039 | t->restore_time.atime_nsec = archive_entry_atime_nsec(entry); | | 1039 | t->restore_time.atime_nsec = archive_entry_atime_nsec(entry); |
1040 | t->restore_time.filetype = archive_entry_filetype(entry); | | 1040 | t->restore_time.filetype = archive_entry_filetype(entry); |
1041 | t->restore_time.noatime = t->current_filesystem->noatime; | | 1041 | t->restore_time.noatime = t->current_filesystem->noatime; |
1042 | | | 1042 | |
1043 | /* | | 1043 | /* |
1044 | * Perform time matching. | | 1044 | * Perform time matching. |
1045 | */ | | 1045 | */ |
1046 | if (a->matching) { | | 1046 | if (a->matching) { |
1047 | r = archive_match_time_excluded(a->matching, entry); | | 1047 | r = archive_match_time_excluded(a->matching, entry); |
1048 | if (r < 0) { | | 1048 | if (r < 0) { |
1049 | archive_set_error(&(a->archive), errno, | | 1049 | archive_set_error(&(a->archive), errno, |
1050 | "Failed : %s", archive_error_string(a->matching)); | | 1050 | "Failed : %s", archive_error_string(a->matching)); |
1051 | return (r); | | 1051 | return (r); |
1052 | } | | 1052 | } |
1053 | if (r) { | | 1053 | if (r) { |
1054 | if (a->excluded_cb_func) | | 1054 | if (a->excluded_cb_func) |
1055 | a->excluded_cb_func(&(a->archive), | | 1055 | a->excluded_cb_func(&(a->archive), |
1056 | a->excluded_cb_data, entry); | | 1056 | a->excluded_cb_data, entry); |
1057 | return (ARCHIVE_RETRY); | | 1057 | return (ARCHIVE_RETRY); |
1058 | } | | 1058 | } |
1059 | } | | 1059 | } |
1060 | | | 1060 | |
1061 | /* Lookup uname/gname */ | | 1061 | /* Lookup uname/gname */ |
1062 | name = archive_read_disk_uname(&(a->archive), archive_entry_uid(entry)); | | 1062 | name = archive_read_disk_uname(&(a->archive), archive_entry_uid(entry)); |
1063 | if (name != NULL) | | 1063 | if (name != NULL) |
1064 | archive_entry_copy_uname(entry, name); | | 1064 | archive_entry_copy_uname(entry, name); |
1065 | name = archive_read_disk_gname(&(a->archive), archive_entry_gid(entry)); | | 1065 | name = archive_read_disk_gname(&(a->archive), archive_entry_gid(entry)); |
1066 | if (name != NULL) | | 1066 | if (name != NULL) |
1067 | archive_entry_copy_gname(entry, name); | | 1067 | archive_entry_copy_gname(entry, name); |
1068 | | | 1068 | |
1069 | /* | | 1069 | /* |
1070 | * Perform owner matching. | | 1070 | * Perform owner matching. |
1071 | */ | | 1071 | */ |
1072 | if (a->matching) { | | 1072 | if (a->matching) { |
1073 | r = archive_match_owner_excluded(a->matching, entry); | | 1073 | r = archive_match_owner_excluded(a->matching, entry); |
1074 | if (r < 0) { | | 1074 | if (r < 0) { |
1075 | archive_set_error(&(a->archive), errno, | | 1075 | archive_set_error(&(a->archive), errno, |
1076 | "Failed : %s", archive_error_string(a->matching)); | | 1076 | "Failed : %s", archive_error_string(a->matching)); |
1077 | return (r); | | 1077 | return (r); |
1078 | } | | 1078 | } |
1079 | if (r) { | | 1079 | if (r) { |
1080 | if (a->excluded_cb_func) | | 1080 | if (a->excluded_cb_func) |
1081 | a->excluded_cb_func(&(a->archive), | | 1081 | a->excluded_cb_func(&(a->archive), |
1082 | a->excluded_cb_data, entry); | | 1082 | a->excluded_cb_data, entry); |
1083 | return (ARCHIVE_RETRY); | | 1083 | return (ARCHIVE_RETRY); |
1084 | } | | 1084 | } |
1085 | } | | 1085 | } |
1086 | | | 1086 | |
1087 | /* | | 1087 | /* |
1088 | * Invoke a meta data filter callback. | | 1088 | * Invoke a meta data filter callback. |
1089 | */ | | 1089 | */ |
1090 | if (a->metadata_filter_func) { | | 1090 | if (a->metadata_filter_func) { |
1091 | if (!a->metadata_filter_func(&(a->archive), | | 1091 | if (!a->metadata_filter_func(&(a->archive), |
1092 | a->metadata_filter_data, entry)) | | 1092 | a->metadata_filter_data, entry)) |
1093 | return (ARCHIVE_RETRY); | | 1093 | return (ARCHIVE_RETRY); |
1094 | } | | 1094 | } |
1095 | | | 1095 | |
1096 | /* | | 1096 | /* |
1097 | * Populate the archive_entry with metadata from the disk. | | 1097 | * Populate the archive_entry with metadata from the disk. |
1098 | */ | | 1098 | */ |
1099 | archive_entry_copy_sourcepath(entry, tree_current_access_path(t)); | | 1099 | archive_entry_copy_sourcepath(entry, tree_current_access_path(t)); |
1100 | r = archive_read_disk_entry_from_file(&(a->archive), entry, | | 1100 | r = archive_read_disk_entry_from_file(&(a->archive), entry, |
1101 | t->entry_fd, st); | | 1101 | t->entry_fd, st); |
1102 | | | 1102 | |
1103 | if (r == ARCHIVE_OK) { | | 1103 | if (r == ARCHIVE_OK) { |
1104 | r = delayed; | | 1104 | r = delayed; |
1105 | if (r != ARCHIVE_OK) { | | 1105 | if (r != ARCHIVE_OK) { |
1106 | archive_string_sprintf(&delayed_str, ": %s", | | 1106 | archive_string_sprintf(&delayed_str, ": %s", |
1107 | "File removed before we read it"); | | 1107 | "File removed before we read it"); |
1108 | archive_set_error(&(a->archive), delayed_errno, | | 1108 | archive_set_error(&(a->archive), delayed_errno, |
1109 | "%s", delayed_str.s); | | 1109 | "%s", delayed_str.s); |
1110 | } | | 1110 | } |
1111 | } | | 1111 | } |
1112 | if (!archive_string_empty(&delayed_str)) | | 1112 | if (!archive_string_empty(&delayed_str)) |
1113 | archive_string_free(&delayed_str); | | 1113 | archive_string_free(&delayed_str); |
1114 | | | 1114 | |
1115 | return (r); | | 1115 | return (r); |
1116 | } | | 1116 | } |
1117 | | | 1117 | |
1118 | static int | | 1118 | static int |
1119 | _archive_read_next_header(struct archive *_a, struct archive_entry **entryp) | | 1119 | _archive_read_next_header(struct archive *_a, struct archive_entry **entryp) |
1120 | { | | 1120 | { |
1121 | int ret; | | 1121 | int ret; |
1122 | struct archive_read_disk *a = (struct archive_read_disk *)_a; | | 1122 | struct archive_read_disk *a = (struct archive_read_disk *)_a; |
1123 | *entryp = NULL; | | 1123 | *entryp = NULL; |
1124 | ret = _archive_read_next_header2(_a, a->entry); | | 1124 | ret = _archive_read_next_header2(_a, a->entry); |
1125 | *entryp = a->entry; | | 1125 | *entryp = a->entry; |
1126 | return ret; | | 1126 | return ret; |
1127 | } | | 1127 | } |
1128 | | | 1128 | |
1129 | static int | | 1129 | static int |
1130 | _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) | | 1130 | _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) |
1131 | { | | 1131 | { |
1132 | struct archive_read_disk *a = (struct archive_read_disk *)_a; | | 1132 | struct archive_read_disk *a = (struct archive_read_disk *)_a; |
1133 | struct tree *t; | | 1133 | struct tree *t; |
1134 | int r; | | 1134 | int r; |
1135 | | | 1135 | |
1136 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, | | 1136 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, |
1137 | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, | | 1137 | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, |
1138 | "archive_read_next_header2"); | | 1138 | "archive_read_next_header2"); |
1139 | | | 1139 | |
1140 | t = a->tree; | | 1140 | t = a->tree; |
1141 | if (t->entry_fd >= 0) { | | 1141 | if (t->entry_fd >= 0) { |
1142 | close_and_restore_time(t->entry_fd, t, &t->restore_time); | | 1142 | close_and_restore_time(t->entry_fd, t, &t->restore_time); |
1143 | t->entry_fd = -1; | | 1143 | t->entry_fd = -1; |
1144 | } | | 1144 | } |
1145 | | | 1145 | |
1146 | for (;;) { | | 1146 | for (;;) { |
1147 | r = next_entry(a, t, entry); | | 1147 | r = next_entry(a, t, entry); |
1148 | if (t->entry_fd >= 0) { | | 1148 | if (t->entry_fd >= 0) { |
1149 | close(t->entry_fd); | | 1149 | close(t->entry_fd); |
1150 | t->entry_fd = -1; | | 1150 | t->entry_fd = -1; |
1151 | } | | 1151 | } |
1152 | | | 1152 | |
1153 | if (r == ARCHIVE_RETRY) { | | 1153 | if (r == ARCHIVE_RETRY) { |
1154 | archive_entry_clear(entry); | | 1154 | archive_entry_clear(entry); |
1155 | continue; | | 1155 | continue; |
1156 | } | | 1156 | } |
1157 | break; | | 1157 | break; |
1158 | } | | 1158 | } |
1159 | | | 1159 | |
1160 | /* Return to the initial directory. */ | | 1160 | /* Return to the initial directory. */ |
1161 | tree_enter_initial_dir(t); | | 1161 | tree_enter_initial_dir(t); |
1162 | | | 1162 | |
1163 | /* | | 1163 | /* |
1164 | * EOF and FATAL are persistent at this layer. By | | 1164 | * EOF and FATAL are persistent at this layer. By |
1165 | * modifying the state, we guarantee that future calls to | | 1165 | * modifying the state, we guarantee that future calls to |
1166 | * read a header or read data will fail. | | 1166 | * read a header or read data will fail. |
1167 | */ | | 1167 | */ |
1168 | switch (r) { | | 1168 | switch (r) { |
1169 | case ARCHIVE_EOF: | | 1169 | case ARCHIVE_EOF: |
1170 | a->archive.state = ARCHIVE_STATE_EOF; | | 1170 | a->archive.state = ARCHIVE_STATE_EOF; |
1171 | break; | | 1171 | break; |
1172 | case ARCHIVE_OK: | | 1172 | case ARCHIVE_OK: |
1173 | case ARCHIVE_WARN: | | 1173 | case ARCHIVE_WARN: |
1174 | /* Overwrite the sourcepath based on the initial directory. */ | | 1174 | /* Overwrite the sourcepath based on the initial directory. */ |
1175 | archive_entry_copy_sourcepath(entry, tree_current_path(t)); | | 1175 | archive_entry_copy_sourcepath(entry, tree_current_path(t)); |
1176 | t->entry_total = 0; | | 1176 | t->entry_total = 0; |
1177 | if (archive_entry_filetype(entry) == AE_IFREG) { | | 1177 | if (archive_entry_filetype(entry) == AE_IFREG) { |
1178 | t->nlink = archive_entry_nlink(entry); | | 1178 | t->nlink = archive_entry_nlink(entry); |
1179 | t->entry_remaining_bytes = archive_entry_size(entry); | | 1179 | t->entry_remaining_bytes = archive_entry_size(entry); |
1180 | t->entry_eof = (t->entry_remaining_bytes == 0)? 1: 0; | | 1180 | t->entry_eof = (t->entry_remaining_bytes == 0)? 1: 0; |
1181 | if (!t->entry_eof && | | 1181 | if (!t->entry_eof && |
1182 | setup_sparse(a, entry) != ARCHIVE_OK) | | 1182 | setup_sparse(a, entry) != ARCHIVE_OK) |
1183 | return (ARCHIVE_FATAL); | | 1183 | return (ARCHIVE_FATAL); |
1184 | } else { | | 1184 | } else { |
1185 | t->entry_remaining_bytes = 0; | | 1185 | t->entry_remaining_bytes = 0; |
1186 | t->entry_eof = 1; | | 1186 | t->entry_eof = 1; |
1187 | } | | 1187 | } |
1188 | a->archive.state = ARCHIVE_STATE_DATA; | | 1188 | a->archive.state = ARCHIVE_STATE_DATA; |
1189 | break; | | 1189 | break; |
1190 | case ARCHIVE_RETRY: | | 1190 | case ARCHIVE_RETRY: |
1191 | break; | | 1191 | break; |
1192 | case ARCHIVE_FATAL: | | 1192 | case ARCHIVE_FATAL: |
1193 | a->archive.state = ARCHIVE_STATE_FATAL; | | 1193 | a->archive.state = ARCHIVE_STATE_FATAL; |
1194 | break; | | 1194 | break; |
1195 | } | | 1195 | } |
1196 | | | 1196 | |
1197 | __archive_reset_read_data(&a->archive); | | 1197 | __archive_reset_read_data(&a->archive); |
1198 | return (r); | | 1198 | return (r); |
1199 | } | | 1199 | } |
1200 | | | 1200 | |
1201 | static int | | 1201 | static int |
1202 | setup_sparse(struct archive_read_disk *a, struct archive_entry *entry) | | 1202 | setup_sparse(struct archive_read_disk *a, struct archive_entry *entry) |
1203 | { | | 1203 | { |
1204 | struct tree *t = a->tree; | | 1204 | struct tree *t = a->tree; |
1205 | int64_t length, offset; | | 1205 | int64_t length, offset; |
1206 | int i; | | 1206 | int i; |
1207 | | | 1207 | |
1208 | t->sparse_count = archive_entry_sparse_reset(entry); | | 1208 | t->sparse_count = archive_entry_sparse_reset(entry); |
1209 | if (t->sparse_count+1 > t->sparse_list_size) { | | 1209 | if (t->sparse_count+1 > t->sparse_list_size) { |
1210 | free(t->sparse_list); | | 1210 | free(t->sparse_list); |
1211 | t->sparse_list_size = t->sparse_count + 1; | | 1211 | t->sparse_list_size = t->sparse_count + 1; |
1212 | t->sparse_list = malloc(sizeof(t->sparse_list[0]) * | | 1212 | t->sparse_list = malloc(sizeof(t->sparse_list[0]) * |
1213 | t->sparse_list_size); | | 1213 | t->sparse_list_size); |
1214 | if (t->sparse_list == NULL) { | | 1214 | if (t->sparse_list == NULL) { |
1215 | t->sparse_list_size = 0; | | 1215 | t->sparse_list_size = 0; |
1216 | archive_set_error(&a->archive, ENOMEM, | | 1216 | archive_set_error(&a->archive, ENOMEM, |
1217 | "Can't allocate data"); | | 1217 | "Can't allocate data"); |
1218 | a->archive.state = ARCHIVE_STATE_FATAL; | | 1218 | a->archive.state = ARCHIVE_STATE_FATAL; |
1219 | return (ARCHIVE_FATAL); | | 1219 | return (ARCHIVE_FATAL); |
1220 | } | | 1220 | } |
1221 | } | | 1221 | } |
1222 | for (i = 0; i < t->sparse_count; i++) { | | 1222 | for (i = 0; i < t->sparse_count; i++) { |
1223 | archive_entry_sparse_next(entry, &offset, &length); | | 1223 | archive_entry_sparse_next(entry, &offset, &length); |
1224 | t->sparse_list[i].offset = offset; | | 1224 | t->sparse_list[i].offset = offset; |
1225 | t->sparse_list[i].length = length; | | 1225 | t->sparse_list[i].length = length; |
1226 | } | | 1226 | } |
1227 | if (i == 0) { | | 1227 | if (i == 0) { |
1228 | t->sparse_list[i].offset = 0; | | 1228 | t->sparse_list[i].offset = 0; |
1229 | t->sparse_list[i].length = archive_entry_size(entry); | | 1229 | t->sparse_list[i].length = archive_entry_size(entry); |
1230 | } else { | | 1230 | } else { |
1231 | t->sparse_list[i].offset = archive_entry_size(entry); | | 1231 | t->sparse_list[i].offset = archive_entry_size(entry); |
1232 | t->sparse_list[i].length = 0; | | 1232 | t->sparse_list[i].length = 0; |
1233 | } | | 1233 | } |
1234 | t->current_sparse = t->sparse_list; | | 1234 | t->current_sparse = t->sparse_list; |
1235 | | | 1235 | |
1236 | return (ARCHIVE_OK); | | 1236 | return (ARCHIVE_OK); |
1237 | } | | 1237 | } |
1238 | | | 1238 | |
1239 | int | | 1239 | int |
1240 | archive_read_disk_set_matching(struct archive *_a, struct archive *_ma, | | 1240 | archive_read_disk_set_matching(struct archive *_a, struct archive *_ma, |
1241 | void (*_excluded_func)(struct archive *, void *, struct archive_entry *), | | 1241 | void (*_excluded_func)(struct archive *, void *, struct archive_entry *), |
1242 | void *_client_data) | | 1242 | void *_client_data) |
1243 | { | | 1243 | { |
1244 | struct archive_read_disk *a = (struct archive_read_disk *)_a; | | 1244 | struct archive_read_disk *a = (struct archive_read_disk *)_a; |
1245 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, | | 1245 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, |
1246 | ARCHIVE_STATE_ANY, "archive_read_disk_set_matching"); | | 1246 | ARCHIVE_STATE_ANY, "archive_read_disk_set_matching"); |
1247 | a->matching = _ma; | | 1247 | a->matching = _ma; |
1248 | a->excluded_cb_func = _excluded_func; | | 1248 | a->excluded_cb_func = _excluded_func; |
1249 | a->excluded_cb_data = _client_data; | | 1249 | a->excluded_cb_data = _client_data; |
1250 | return (ARCHIVE_OK); | | 1250 | return (ARCHIVE_OK); |
1251 | } | | 1251 | } |
1252 | | | 1252 | |
1253 | int | | 1253 | int |
1254 | archive_read_disk_set_metadata_filter_callback(struct archive *_a, | | 1254 | archive_read_disk_set_metadata_filter_callback(struct archive *_a, |
1255 | int (*_metadata_filter_func)(struct archive *, void *, | | 1255 | int (*_metadata_filter_func)(struct archive *, void *, |
1256 | struct archive_entry *), void *_client_data) | | 1256 | struct archive_entry *), void *_client_data) |
1257 | { | | 1257 | { |
1258 | struct archive_read_disk *a = (struct archive_read_disk *)_a; | | 1258 | struct archive_read_disk *a = (struct archive_read_disk *)_a; |
1259 | | | 1259 | |
1260 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, | | 1260 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, |
1261 | "archive_read_disk_set_metadata_filter_callback"); | | 1261 | "archive_read_disk_set_metadata_filter_callback"); |
1262 | | | 1262 | |
1263 | a->metadata_filter_func = _metadata_filter_func; | | 1263 | a->metadata_filter_func = _metadata_filter_func; |
1264 | a->metadata_filter_data = _client_data; | | 1264 | a->metadata_filter_data = _client_data; |
1265 | return (ARCHIVE_OK); | | 1265 | return (ARCHIVE_OK); |
1266 | } | | 1266 | } |
1267 | | | 1267 | |
1268 | int | | 1268 | int |
1269 | archive_read_disk_can_descend(struct archive *_a) | | 1269 | archive_read_disk_can_descend(struct archive *_a) |
1270 | { | | 1270 | { |
1271 | struct archive_read_disk *a = (struct archive_read_disk *)_a; | | 1271 | struct archive_read_disk *a = (struct archive_read_disk *)_a; |
1272 | struct tree *t = a->tree; | | 1272 | struct tree *t = a->tree; |
1273 | | | 1273 | |
1274 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, | | 1274 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, |
1275 | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, | | 1275 | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, |
1276 | "archive_read_disk_can_descend"); | | 1276 | "archive_read_disk_can_descend"); |
1277 | | | 1277 | |
1278 | return (t->visit_type == TREE_REGULAR && t->descend); | | 1278 | return (t->visit_type == TREE_REGULAR && t->descend); |
1279 | } | | 1279 | } |
1280 | | | 1280 | |
1281 | /* | | 1281 | /* |
1282 | * Called by the client to mark the directory just returned from | | 1282 | * Called by the client to mark the directory just returned from |
1283 | * tree_next() as needing to be visited. | | 1283 | * tree_next() as needing to be visited. |
1284 | */ | | 1284 | */ |
1285 | int | | 1285 | int |
1286 | archive_read_disk_descend(struct archive *_a) | | 1286 | archive_read_disk_descend(struct archive *_a) |
1287 | { | | 1287 | { |
1288 | struct archive_read_disk *a = (struct archive_read_disk *)_a; | | 1288 | struct archive_read_disk *a = (struct archive_read_disk *)_a; |
1289 | struct tree *t = a->tree; | | 1289 | struct tree *t = a->tree; |
1290 | | | 1290 | |
1291 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, | | 1291 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, |
1292 | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, | | 1292 | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, |
1293 | "archive_read_disk_descend"); | | 1293 | "archive_read_disk_descend"); |
1294 | | | 1294 | |
1295 | if (t->visit_type != TREE_REGULAR || !t->descend) | | 1295 | if (t->visit_type != TREE_REGULAR || !t->descend) |
1296 | return (ARCHIVE_OK); | | 1296 | return (ARCHIVE_OK); |
1297 | | | 1297 | |
1298 | /* | | 1298 | /* |
1299 | * We must not treat the initial specified path as a physical dir, | | 1299 | * We must not treat the initial specified path as a physical dir, |
1300 | * because if we do then we will try and ascend out of it by opening | | 1300 | * because if we do then we will try and ascend out of it by opening |
1301 | * ".." which is (a) wrong and (b) causes spurious permissions errors | | 1301 | * ".." which is (a) wrong and (b) causes spurious permissions errors |
1302 | * if ".." is not readable by us. Instead, treat it as if it were a | | 1302 | * if ".." is not readable by us. Instead, treat it as if it were a |
1303 | * symlink. (This uses an extra fd, but it can only happen once at the | | 1303 | * symlink. (This uses an extra fd, but it can only happen once at the |
1304 | * top level of a traverse.) But we can't necessarily assume t->st is | | 1304 | * top level of a traverse.) But we can't necessarily assume t->st is |
1305 | * valid here (though t->lst is), which complicates the logic a | | 1305 | * valid here (though t->lst is), which complicates the logic a |
1306 | * little. | | 1306 | * little. |
1307 | */ | | 1307 | */ |
1308 | if (tree_current_is_physical_dir(t)) { | | 1308 | if (tree_current_is_physical_dir(t)) { |
1309 | tree_push(t, t->basename, t->current_filesystem_id, | | 1309 | tree_push(t, t->basename, t->current_filesystem_id, |
1310 | t->lst.st_dev, t->lst.st_ino, &t->restore_time); | | 1310 | t->lst.st_dev, t->lst.st_ino, &t->restore_time); |
1311 | if (t->stack->parent->parent != NULL) | | 1311 | if (t->stack->parent->parent != NULL) |
1312 | t->stack->flags |= isDir; | | 1312 | t->stack->flags |= isDir; |
1313 | else | | 1313 | else |
1314 | t->stack->flags |= isDirLink; | | 1314 | t->stack->flags |= isDirLink; |
1315 | } else if (tree_current_is_dir(t)) { | | 1315 | } else if (tree_current_is_dir(t)) { |
1316 | tree_push(t, t->basename, t->current_filesystem_id, | | 1316 | tree_push(t, t->basename, t->current_filesystem_id, |
1317 | t->st.st_dev, t->st.st_ino, &t->restore_time); | | 1317 | t->st.st_dev, t->st.st_ino, &t->restore_time); |
1318 | t->stack->flags |= isDirLink; | | 1318 | t->stack->flags |= isDirLink; |
1319 | } | | 1319 | } |
1320 | t->descend = 0; | | 1320 | t->descend = 0; |
1321 | return (ARCHIVE_OK); | | 1321 | return (ARCHIVE_OK); |
1322 | } | | 1322 | } |
1323 | | | 1323 | |
1324 | int | | 1324 | int |
1325 | archive_read_disk_open(struct archive *_a, const char *pathname) | | 1325 | archive_read_disk_open(struct archive *_a, const char *pathname) |
1326 | { | | 1326 | { |
1327 | struct archive_read_disk *a = (struct archive_read_disk *)_a; | | 1327 | struct archive_read_disk *a = (struct archive_read_disk *)_a; |
1328 | | | 1328 | |
1329 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, | | 1329 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, |
1330 | ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED, | | 1330 | ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED, |
1331 | "archive_read_disk_open"); | | 1331 | "archive_read_disk_open"); |
1332 | archive_clear_error(&a->archive); | | 1332 | archive_clear_error(&a->archive); |
1333 | | | 1333 | |
1334 | return (_archive_read_disk_open(_a, pathname)); | | 1334 | return (_archive_read_disk_open(_a, pathname)); |
1335 | } | | 1335 | } |
1336 | | | 1336 | |
1337 | int | | 1337 | int |
1338 | archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname) | | 1338 | archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname) |
1339 | { | | 1339 | { |
1340 | struct archive_read_disk *a = (struct archive_read_disk *)_a; | | 1340 | struct archive_read_disk *a = (struct archive_read_disk *)_a; |
1341 | struct archive_string path; | | 1341 | struct archive_string path; |
1342 | int ret; | | 1342 | int ret; |
1343 | | | 1343 | |
1344 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, | | 1344 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, |
1345 | ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED, | | 1345 | ARCHIVE_STATE_NEW | ARCHIVE_STATE_CLOSED, |
1346 | "archive_read_disk_open_w"); | | 1346 | "archive_read_disk_open_w"); |
1347 | archive_clear_error(&a->archive); | | 1347 | archive_clear_error(&a->archive); |
1348 | | | 1348 | |
1349 | /* Make a char string from a wchar_t string. */ | | 1349 | /* Make a char string from a wchar_t string. */ |
1350 | archive_string_init(&path); | | 1350 | archive_string_init(&path); |
1351 | if (archive_string_append_from_wcs(&path, pathname, | | 1351 | if (archive_string_append_from_wcs(&path, pathname, |
1352 | wcslen(pathname)) != 0) { | | 1352 | wcslen(pathname)) != 0) { |
1353 | if (errno == ENOMEM) | | 1353 | if (errno == ENOMEM) |
1354 | archive_set_error(&a->archive, ENOMEM, | | 1354 | archive_set_error(&a->archive, ENOMEM, |
1355 | "Can't allocate memory"); | | 1355 | "Can't allocate memory"); |
1356 | else | | 1356 | else |
1357 | archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, | | 1357 | archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, |
1358 | "Can't convert a path to a char string"); | | 1358 | "Can't convert a path to a char string"); |
1359 | a->archive.state = ARCHIVE_STATE_FATAL; | | 1359 | a->archive.state = ARCHIVE_STATE_FATAL; |
1360 | ret = ARCHIVE_FATAL; | | 1360 | ret = ARCHIVE_FATAL; |
1361 | } else | | 1361 | } else |
1362 | ret = _archive_read_disk_open(_a, path.s); | | 1362 | ret = _archive_read_disk_open(_a, path.s); |
1363 | | | 1363 | |
1364 | archive_string_free(&path); | | 1364 | archive_string_free(&path); |
1365 | return (ret); | | 1365 | return (ret); |
1366 | } | | 1366 | } |
1367 | | | 1367 | |
1368 | static int | | 1368 | static int |
1369 | _archive_read_disk_open(struct archive *_a, const char *pathname) | | 1369 | _archive_read_disk_open(struct archive *_a, const char *pathname) |
1370 | { | | 1370 | { |
1371 | struct archive_read_disk *a = (struct archive_read_disk *)_a; | | 1371 | struct archive_read_disk *a = (struct archive_read_disk *)_a; |
1372 | | | 1372 | |
1373 | if (a->tree != NULL) | | 1373 | if (a->tree != NULL) |
1374 | a->tree = tree_reopen(a->tree, pathname, | | 1374 | a->tree = tree_reopen(a->tree, pathname, |
1375 | a->flags & ARCHIVE_READDISK_RESTORE_ATIME); | | 1375 | a->flags & ARCHIVE_READDISK_RESTORE_ATIME); |
1376 | else | | 1376 | else |
1377 | a->tree = tree_open(pathname, a->symlink_mode, | | 1377 | a->tree = tree_open(pathname, a->symlink_mode, |
1378 | a->flags & ARCHIVE_READDISK_RESTORE_ATIME); | | 1378 | a->flags & ARCHIVE_READDISK_RESTORE_ATIME); |
1379 | if (a->tree == NULL) { | | 1379 | if (a->tree == NULL) { |
1380 | archive_set_error(&a->archive, ENOMEM, | | 1380 | archive_set_error(&a->archive, ENOMEM, |
1381 | "Can't allocate tar data"); | | 1381 | "Can't allocate tar data"); |
1382 | a->archive.state = ARCHIVE_STATE_FATAL; | | 1382 | a->archive.state = ARCHIVE_STATE_FATAL; |
1383 | return (ARCHIVE_FATAL); | | 1383 | return (ARCHIVE_FATAL); |
1384 | } | | 1384 | } |
1385 | a->archive.state = ARCHIVE_STATE_HEADER; | | 1385 | a->archive.state = ARCHIVE_STATE_HEADER; |
1386 | | | 1386 | |
1387 | return (ARCHIVE_OK); | | 1387 | return (ARCHIVE_OK); |
1388 | } | | 1388 | } |
1389 | | | 1389 | |
1390 | /* | | 1390 | /* |
1391 | * Return a current filesystem ID which is index of the filesystem entry | | 1391 | * Return a current filesystem ID which is index of the filesystem entry |
1392 | * you've visited through archive_read_disk. | | 1392 | * you've visited through archive_read_disk. |
1393 | */ | | 1393 | */ |
1394 | int | | 1394 | int |
1395 | archive_read_disk_current_filesystem(struct archive *_a) | | 1395 | archive_read_disk_current_filesystem(struct archive *_a) |
1396 | { | | 1396 | { |
1397 | struct archive_read_disk *a = (struct archive_read_disk *)_a; | | 1397 | struct archive_read_disk *a = (struct archive_read_disk *)_a; |
1398 | | | 1398 | |
1399 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, | | 1399 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, |
1400 | "archive_read_disk_current_filesystem"); | | 1400 | "archive_read_disk_current_filesystem"); |
1401 | | | 1401 | |
1402 | return (a->tree->current_filesystem_id); | | 1402 | return (a->tree->current_filesystem_id); |
1403 | } | | 1403 | } |
1404 | | | 1404 | |
1405 | static int | | 1405 | static int |
1406 | update_current_filesystem(struct archive_read_disk *a, int64_t dev) | | 1406 | update_current_filesystem(struct archive_read_disk *a, int64_t dev) |
1407 | { | | 1407 | { |
1408 | struct tree *t = a->tree; | | 1408 | struct tree *t = a->tree; |
1409 | int i, fid; | | 1409 | int i, fid; |
1410 | | | 1410 | |
1411 | if (t->current_filesystem != NULL && | | 1411 | if (t->current_filesystem != NULL && |
1412 | t->current_filesystem->dev == dev) | | 1412 | t->current_filesystem->dev == dev) |
1413 | return (ARCHIVE_OK); | | 1413 | return (ARCHIVE_OK); |
1414 | | | 1414 | |
1415 | for (i = 0; i < t->max_filesystem_id; i++) { | | 1415 | for (i = 0; i < t->max_filesystem_id; i++) { |
1416 | if (t->filesystem_table[i].dev == dev) { | | 1416 | if (t->filesystem_table[i].dev == dev) { |
1417 | /* There is the filesystem ID we've already generated. */ | | 1417 | /* There is the filesystem ID we've already generated. */ |
1418 | t->current_filesystem_id = i; | | 1418 | t->current_filesystem_id = i; |
1419 | t->current_filesystem = &(t->filesystem_table[i]); | | 1419 | t->current_filesystem = &(t->filesystem_table[i]); |
1420 | return (ARCHIVE_OK); | | 1420 | return (ARCHIVE_OK); |
1421 | } | | 1421 | } |
1422 | } | | 1422 | } |
1423 | | | 1423 | |
1424 | /* | | 1424 | /* |
1425 | * This is the new filesystem which we have to generate a new ID for. | | 1425 | * This is the new filesystem which we have to generate a new ID for. |
1426 | */ | | 1426 | */ |
1427 | fid = t->max_filesystem_id++; | | 1427 | fid = t->max_filesystem_id++; |
1428 | if (t->max_filesystem_id > t->allocated_filesystem) { | | 1428 | if (t->max_filesystem_id > t->allocated_filesystem) { |
1429 | size_t s; | | 1429 | size_t s; |
1430 | void *p; | | 1430 | void *p; |
1431 | | | 1431 | |
1432 | s = t->max_filesystem_id * 2; | | 1432 | s = t->max_filesystem_id * 2; |
1433 | p = realloc(t->filesystem_table, | | 1433 | p = realloc(t->filesystem_table, |
1434 | s * sizeof(*t->filesystem_table)); | | 1434 | s * sizeof(*t->filesystem_table)); |
1435 | if (p == NULL) { | | 1435 | if (p == NULL) { |
1436 | archive_set_error(&a->archive, ENOMEM, | | 1436 | archive_set_error(&a->archive, ENOMEM, |
1437 | "Can't allocate tar data"); | | 1437 | "Can't allocate tar data"); |
1438 | return (ARCHIVE_FATAL); | | 1438 | return (ARCHIVE_FATAL); |
1439 | } | | 1439 | } |
1440 | t->filesystem_table = (struct filesystem *)p; | | 1440 | t->filesystem_table = (struct filesystem *)p; |
1441 | t->allocated_filesystem = s; | | 1441 | t->allocated_filesystem = s; |
1442 | } | | 1442 | } |
1443 | t->current_filesystem_id = fid; | | 1443 | t->current_filesystem_id = fid; |
1444 | t->current_filesystem = &(t->filesystem_table[fid]); | | 1444 | t->current_filesystem = &(t->filesystem_table[fid]); |
1445 | t->current_filesystem->dev = dev; | | 1445 | t->current_filesystem->dev = dev; |
1446 | t->current_filesystem->allocation_ptr = NULL; | | 1446 | t->current_filesystem->allocation_ptr = NULL; |
1447 | t->current_filesystem->buff = NULL; | | 1447 | t->current_filesystem->buff = NULL; |
1448 | | | 1448 | |
1449 | /* Setup the current filesystem properties which depend on | | 1449 | /* Setup the current filesystem properties which depend on |
1450 | * platform specific. */ | | 1450 | * platform specific. */ |
1451 | return (setup_current_filesystem(a)); | | 1451 | return (setup_current_filesystem(a)); |
1452 | } | | 1452 | } |
1453 | | | 1453 | |
1454 | /* | | 1454 | /* |
1455 | * Returns 1 if current filesystem is generated filesystem, 0 if it is not | | 1455 | * Returns 1 if current filesystem is generated filesystem, 0 if it is not |
1456 | * or -1 if it is unknown. | | 1456 | * or -1 if it is unknown. |
1457 | */ | | 1457 | */ |
1458 | int | | 1458 | int |
1459 | archive_read_disk_current_filesystem_is_synthetic(struct archive *_a) | | 1459 | archive_read_disk_current_filesystem_is_synthetic(struct archive *_a) |
1460 | { | | 1460 | { |
1461 | struct archive_read_disk *a = (struct archive_read_disk *)_a; | | 1461 | struct archive_read_disk *a = (struct archive_read_disk *)_a; |
1462 | | | 1462 | |
1463 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, | | 1463 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, |
1464 | "archive_read_disk_current_filesystem"); | | 1464 | "archive_read_disk_current_filesystem"); |
1465 | | | 1465 | |
1466 | return (a->tree->current_filesystem->synthetic); | | 1466 | return (a->tree->current_filesystem->synthetic); |
1467 | } | | 1467 | } |
1468 | | | 1468 | |
1469 | /* | | 1469 | /* |
1470 | * Returns 1 if current filesystem is remote filesystem, 0 if it is not | | 1470 | * Returns 1 if current filesystem is remote filesystem, 0 if it is not |
1471 | * or -1 if it is unknown. | | 1471 | * or -1 if it is unknown. |
1472 | */ | | 1472 | */ |
1473 | int | | 1473 | int |
1474 | archive_read_disk_current_filesystem_is_remote(struct archive *_a) | | 1474 | archive_read_disk_current_filesystem_is_remote(struct archive *_a) |
1475 | { | | 1475 | { |
1476 | struct archive_read_disk *a = (struct archive_read_disk *)_a; | | 1476 | struct archive_read_disk *a = (struct archive_read_disk *)_a; |
1477 | | | 1477 | |
1478 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, | | 1478 | archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA, |
1479 | "archive_read_disk_current_filesystem"); | | 1479 | "archive_read_disk_current_filesystem"); |
1480 | | | 1480 | |
1481 | return (a->tree->current_filesystem->remote); | | 1481 | return (a->tree->current_filesystem->remote); |
1482 | } | | 1482 | } |
1483 | | | 1483 | |
1484 | #if defined(_PC_REC_INCR_XFER_SIZE) && defined(_PC_REC_MAX_XFER_SIZE) &&\ | | 1484 | #if defined(_PC_REC_INCR_XFER_SIZE) && defined(_PC_REC_MAX_XFER_SIZE) &&\ |
1485 | defined(_PC_REC_MIN_XFER_SIZE) && defined(_PC_REC_XFER_ALIGN) | | 1485 | defined(_PC_REC_MIN_XFER_SIZE) && defined(_PC_REC_XFER_ALIGN) |
1486 | static int | | 1486 | static int |
1487 | get_xfer_size(struct tree *t, int fd, const char *path) | | 1487 | get_xfer_size(struct tree *t, int fd, const char *path) |
1488 | { | | 1488 | { |
1489 | t->current_filesystem->xfer_align = -1; | | 1489 | t->current_filesystem->xfer_align = -1; |
1490 | errno = 0; | | 1490 | errno = 0; |
1491 | if (fd >= 0) { | | 1491 | if (fd >= 0) { |
1492 | t->current_filesystem->incr_xfer_size = | | 1492 | t->current_filesystem->incr_xfer_size = |
1493 | fpathconf(fd, _PC_REC_INCR_XFER_SIZE); | | 1493 | fpathconf(fd, _PC_REC_INCR_XFER_SIZE); |
1494 | t->current_filesystem->max_xfer_size = | | 1494 | t->current_filesystem->max_xfer_size = |
1495 | fpathconf(fd, _PC_REC_MAX_XFER_SIZE); | | 1495 | fpathconf(fd, _PC_REC_MAX_XFER_SIZE); |
1496 | t->current_filesystem->min_xfer_size = | | 1496 | t->current_filesystem->min_xfer_size = |
1497 | fpathconf(fd, _PC_REC_MIN_XFER_SIZE); | | 1497 | fpathconf(fd, _PC_REC_MIN_XFER_SIZE); |
1498 | t->current_filesystem->xfer_align = | | 1498 | t->current_filesystem->xfer_align = |
1499 | fpathconf(fd, _PC_REC_XFER_ALIGN); | | 1499 | fpathconf(fd, _PC_REC_XFER_ALIGN); |
1500 | } else if (path != NULL) { | | 1500 | } else if (path != NULL) { |
1501 | t->current_filesystem->incr_xfer_size = | | 1501 | t->current_filesystem->incr_xfer_size = |
1502 | pathconf(path, _PC_REC_INCR_XFER_SIZE); | | 1502 | pathconf(path, _PC_REC_INCR_XFER_SIZE); |
1503 | t->current_filesystem->max_xfer_size = | | 1503 | t->current_filesystem->max_xfer_size = |
1504 | pathconf(path, _PC_REC_MAX_XFER_SIZE); | | 1504 | pathconf(path, _PC_REC_MAX_XFER_SIZE); |
1505 | t->current_filesystem->min_xfer_size = | | 1505 | t->current_filesystem->min_xfer_size = |
1506 | pathconf(path, _PC_REC_MIN_XFER_SIZE); | | 1506 | pathconf(path, _PC_REC_MIN_XFER_SIZE); |
1507 | t->current_filesystem->xfer_align = | | 1507 | t->current_filesystem->xfer_align = |
1508 | pathconf(path, _PC_REC_XFER_ALIGN); | | 1508 | pathconf(path, _PC_REC_XFER_ALIGN); |
1509 | } | | 1509 | } |
1510 | /* At least we need an alignment size. */ | | 1510 | /* At least we need an alignment size. */ |
1511 | if (t->current_filesystem->xfer_align == -1) | | 1511 | if (t->current_filesystem->xfer_align == -1) |
1512 | return ((errno == EINVAL)?1:-1); | | 1512 | return ((errno == EINVAL)?1:-1); |
1513 | else | | 1513 | else |
1514 | return (0); | | 1514 | return (0); |
1515 | } | | 1515 | } |
1516 | #else | | 1516 | #else |
1517 | static int | | 1517 | static int |
1518 | get_xfer_size(struct tree *t, int fd, const char *path) | | 1518 | get_xfer_size(struct tree *t, int fd, const char *path) |
1519 | { | | 1519 | { |
1520 | (void)t; /* UNUSED */ | | 1520 | (void)t; /* UNUSED */ |
1521 | (void)fd; /* UNUSED */ | | 1521 | (void)fd; /* UNUSED */ |
1522 | (void)path; /* UNUSED */ | | 1522 | (void)path; /* UNUSED */ |
1523 | return (1);/* Not supported */ | | 1523 | return (1);/* Not supported */ |
1524 | } | | 1524 | } |
1525 | #endif | | 1525 | #endif |
1526 | | | 1526 | |
1527 | #if defined(HAVE_STATFS) && defined(HAVE_FSTATFS) && defined(MNT_LOCAL) \ | | 1527 | #if defined(HAVE_STATFS) && defined(HAVE_FSTATFS) && defined(MNT_LOCAL) \ |
1528 | && !defined(ST_LOCAL) | | 1528 | && !defined(ST_LOCAL) |
1529 | | | 1529 | |
1530 | static void | | 1530 | static void |
1531 | set_transfer_size(struct filesystem *fs, const struct statfs *sfs) | | 1531 | set_transfer_size(struct filesystem *fs, const struct statfs *sfs) |
1532 | { | | 1532 | { |
1533 | fs->xfer_align = sfs->f_bsize > 0 ? (long)sfs->fs_bsize : -1; | | 1533 | fs->xfer_align = sfs->f_bsize > 0 ? (long)sfs->fs_bsize : -1; |
1534 | fs->max_xfer_size = -1; | | 1534 | fs->max_xfer_size = -1; |
1535 | fs->min_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1; | | 1535 | fs->min_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1; |
1536 | fs->incr_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1; | | 1536 | fs->incr_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1; |
1537 | } | | 1537 | } |
1538 | | | 1538 | |
1539 | /* | | 1539 | /* |
1540 | * Gather current filesystem properties on FreeBSD, OpenBSD and Mac OS X. | | 1540 | * Gather current filesystem properties on FreeBSD, OpenBSD and Mac OS X. |
1541 | */ | | 1541 | */ |
1542 | static int | | 1542 | static int |
1543 | setup_current_filesystem(struct archive_read_disk *a) | | 1543 | setup_current_filesystem(struct archive_read_disk *a) |
1544 | { | | 1544 | { |
1545 | struct tree *t = a->tree; | | 1545 | struct tree *t = a->tree; |
1546 | struct statfs sfs; | | 1546 | struct statfs sfs; |
1547 | #if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC) | | 1547 | #if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC) |
1548 | /* TODO: configure should set GETVFSBYNAME_ARG_TYPE to make | | 1548 | /* TODO: configure should set GETVFSBYNAME_ARG_TYPE to make |
1549 | * this accurate; some platforms have both and we need the one that's | | 1549 | * this accurate; some platforms have both and we need the one that's |
1550 | * used by getvfsbyname() | | 1550 | * used by getvfsbyname() |
1551 | * | | 1551 | * |
1552 | * Then the following would become: | | 1552 | * Then the following would become: |
1553 | * #if defined(GETVFSBYNAME_ARG_TYPE) | | 1553 | * #if defined(GETVFSBYNAME_ARG_TYPE) |
1554 | * GETVFSBYNAME_ARG_TYPE vfc; | | 1554 | * GETVFSBYNAME_ARG_TYPE vfc; |
1555 | * #endif | | 1555 | * #endif |
1556 | */ | | 1556 | */ |
1557 | # if defined(HAVE_STRUCT_XVFSCONF) | | 1557 | # if defined(HAVE_STRUCT_XVFSCONF) |
1558 | struct xvfsconf vfc; | | 1558 | struct xvfsconf vfc; |
1559 | # else | | 1559 | # else |
1560 | struct vfsconf vfc; | | 1560 | struct vfsconf vfc; |
1561 | # endif | | 1561 | # endif |
1562 | #endif | | 1562 | #endif |
1563 | int r, xr = 0; | | 1563 | int r, xr = 0; |
1564 | #if !defined(HAVE_STRUCT_STATFS_F_NAMEMAX) | | 1564 | #if !defined(HAVE_STRUCT_STATFS_F_NAMEMAX) |
1565 | long nm; | | 1565 | long nm; |
1566 | #endif | | 1566 | #endif |
1567 | | | 1567 | |
1568 | t->current_filesystem->synthetic = -1; | | 1568 | t->current_filesystem->synthetic = -1; |
1569 | t->current_filesystem->remote = -1; | | 1569 | t->current_filesystem->remote = -1; |
1570 | if (tree_current_is_symblic_link_target(t)) { | | 1570 | if (tree_current_is_symblic_link_target(t)) { |
1571 | #if defined(HAVE_OPENAT) | | 1571 | #if defined(HAVE_OPENAT) |
1572 | /* | | 1572 | /* |
1573 | * Get file system statistics on any directory | | 1573 | * Get file system statistics on any directory |
1574 | * where current is. | | 1574 | * where current is. |
1575 | */ | | 1575 | */ |
1576 | int fd = openat(tree_current_dir_fd(t), | | 1576 | int fd = openat(tree_current_dir_fd(t), |
1577 | tree_current_access_path(t), O_RDONLY | O_CLOEXEC); | | 1577 | tree_current_access_path(t), O_RDONLY | O_CLOEXEC); |
1578 | __archive_ensure_cloexec_flag(fd); | | 1578 | __archive_ensure_cloexec_flag(fd); |
1579 | if (fd < 0) { | | 1579 | if (fd < 0) { |
1580 | archive_set_error(&a->archive, errno, | | 1580 | archive_set_error(&a->archive, errno, |
1581 | "openat failed"); | | 1581 | "openat failed"); |
1582 | return (ARCHIVE_FAILED); | | 1582 | return (ARCHIVE_FAILED); |
1583 | } | | 1583 | } |
1584 | r = fstatfs(fd, &sfs); | | 1584 | r = fstatfs(fd, &sfs); |
1585 | if (r == 0) | | 1585 | if (r == 0) |
1586 | xr = get_xfer_size(t, fd, NULL); | | 1586 | xr = get_xfer_size(t, fd, NULL); |
1587 | close(fd); | | 1587 | close(fd); |
1588 | #else | | 1588 | #else |
1589 | if (tree_enter_working_dir(t) != 0) { | | 1589 | if (tree_enter_working_dir(t) != 0) { |
1590 | archive_set_error(&a->archive, errno, "fchdir failed"); | | 1590 | archive_set_error(&a->archive, errno, "fchdir failed"); |
1591 | return (ARCHIVE_FAILED); | | 1591 | return (ARCHIVE_FAILED); |
1592 | } | | 1592 | } |
1593 | r = statfs(tree_current_access_path(t), &sfs); | | 1593 | r = statfs(tree_current_access_path(t), &sfs); |
1594 | if (r == 0) | | 1594 | if (r == 0) |
1595 | xr = get_xfer_size(t, -1, tree_current_access_path(t)); | | 1595 | xr = get_xfer_size(t, -1, tree_current_access_path(t)); |
1596 | #endif | | 1596 | #endif |
1597 | } else { | | 1597 | } else { |
1598 | r = fstatfs(tree_current_dir_fd(t), &sfs); | | 1598 | r = fstatfs(tree_current_dir_fd(t), &sfs); |
1599 | if (r == 0) | | 1599 | if (r == 0) |
1600 | xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); | | 1600 | xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); |
1601 | } | | 1601 | } |
1602 | if (r == -1 || xr == -1) { | | 1602 | if (r == -1 || xr == -1) { |
1603 | archive_set_error(&a->archive, errno, "statfs failed"); | | 1603 | archive_set_error(&a->archive, errno, "statfs failed"); |
1604 | return (ARCHIVE_FAILED); | | 1604 | return (ARCHIVE_FAILED); |
1605 | } else if (xr == 1) { | | 1605 | } else if (xr == 1) { |
1606 | /* pathconf(_PC_REX_*) operations are not supported. */ | | 1606 | /* pathconf(_PC_REX_*) operations are not supported. */ |
1607 | set_transfer_size(t->current_filesystem, &sfs); | | 1607 | set_transfer_size(t->current_filesystem, &sfs); |
1608 | } | | 1608 | } |
1609 | if (sfs.f_flags & MNT_LOCAL) | | 1609 | if (sfs.f_flags & MNT_LOCAL) |
1610 | t->current_filesystem->remote = 0; | | 1610 | t->current_filesystem->remote = 0; |
1611 | else | | 1611 | else |
1612 | t->current_filesystem->remote = 1; | | 1612 | t->current_filesystem->remote = 1; |
1613 | | | 1613 | |
1614 | #if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC) | | 1614 | #if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC) |
1615 | r = getvfsbyname(sfs.f_fstypename, &vfc); | | 1615 | r = getvfsbyname(sfs.f_fstypename, &vfc); |
1616 | if (r == -1) { | | 1616 | if (r == -1) { |
1617 | archive_set_error(&a->archive, errno, "getvfsbyname failed"); | | 1617 | archive_set_error(&a->archive, errno, "getvfsbyname failed"); |
1618 | return (ARCHIVE_FAILED); | | 1618 | return (ARCHIVE_FAILED); |
1619 | } | | 1619 | } |
1620 | if (vfc.vfc_flags & VFCF_SYNTHETIC) | | 1620 | if (vfc.vfc_flags & VFCF_SYNTHETIC) |
1621 | t->current_filesystem->synthetic = 1; | | 1621 | t->current_filesystem->synthetic = 1; |
1622 | else | | 1622 | else |
1623 | t->current_filesystem->synthetic = 0; | | 1623 | t->current_filesystem->synthetic = 0; |
1624 | #endif | | 1624 | #endif |
1625 | | | 1625 | |
1626 | #if defined(MNT_NOATIME) | | 1626 | #if defined(MNT_NOATIME) |
1627 | if (sfs.f_flags & MNT_NOATIME) | | 1627 | if (sfs.f_flags & MNT_NOATIME) |
1628 | t->current_filesystem->noatime = 1; | | 1628 | t->current_filesystem->noatime = 1; |
1629 | else | | 1629 | else |
1630 | #endif | | 1630 | #endif |
1631 | t->current_filesystem->noatime = 0; | | 1631 | t->current_filesystem->noatime = 0; |
1632 | | | 1632 | |
1633 | #if defined(USE_READDIR_R) | | 1633 | #if defined(USE_READDIR_R) |
1634 | /* Set maximum filename length. */ | | 1634 | /* Set maximum filename length. */ |
1635 | #if defined(HAVE_STRUCT_STATFS_F_NAMEMAX) | | 1635 | #if defined(HAVE_STRUCT_STATFS_F_NAMEMAX) |
1636 | t->current_filesystem->name_max = sfs.f_namemax; | | 1636 | t->current_filesystem->name_max = sfs.f_namemax; |
1637 | #else | | 1637 | #else |
1638 | # if defined(_PC_NAME_MAX) | | 1638 | # if defined(_PC_NAME_MAX) |
1639 | /* Mac OS X does not have f_namemax in struct statfs. */ | | 1639 | /* Mac OS X does not have f_namemax in struct statfs. */ |
1640 | if (tree_current_is_symblic_link_target(t)) { | | 1640 | if (tree_current_is_symblic_link_target(t)) { |
1641 | if (tree_enter_working_dir(t) != 0) { | | 1641 | if (tree_enter_working_dir(t) != 0) { |
1642 | archive_set_error(&a->archive, errno, "fchdir failed"); | | 1642 | archive_set_error(&a->archive, errno, "fchdir failed"); |
1643 | return (ARCHIVE_FAILED); | | 1643 | return (ARCHIVE_FAILED); |
1644 | } | | 1644 | } |
1645 | nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX); | | 1645 | nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX); |
1646 | } else | | 1646 | } else |
1647 | nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX); | | 1647 | nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX); |
1648 | # else | | 1648 | # else |
1649 | nm = -1; | | 1649 | nm = -1; |
1650 | # endif | | 1650 | # endif |
1651 | if (nm == -1) | | 1651 | if (nm == -1) |
1652 | t->current_filesystem->name_max = NAME_MAX; | | 1652 | t->current_filesystem->name_max = NAME_MAX; |
1653 | else | | 1653 | else |
1654 | t->current_filesystem->name_max = nm; | | 1654 | t->current_filesystem->name_max = nm; |
1655 | #endif | | 1655 | #endif |
| | | 1656 | if (t->current_filesystem->name_max == 0) { |
| | | 1657 | archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, |
| | | 1658 | "Cannot determine name_max"); |
| | | 1659 | return (ARCHIVE_FAILED); |
| | | 1660 | } |
1656 | #endif /* USE_READDIR_R */ | | 1661 | #endif /* USE_READDIR_R */ |
1657 | return (ARCHIVE_OK); | | 1662 | return (ARCHIVE_OK); |
1658 | } | | 1663 | } |
1659 | | | 1664 | |
1660 | #elif (defined(HAVE_STATVFS) || defined(HAVE_FSTATVFS)) && defined(ST_LOCAL) | | 1665 | #elif (defined(HAVE_STATVFS) || defined(HAVE_FSTATVFS)) && defined(ST_LOCAL) |
1661 | | | 1666 | |
1662 | static void | | 1667 | static void |
1663 | set_transfer_size(struct filesystem *fs, const struct statvfs *sfs) | | 1668 | set_transfer_size(struct filesystem *fs, const struct statvfs *sfs) |
1664 | { | | 1669 | { |
1665 | fs->xfer_align = sfs->f_frsize > 0 ? (long)sfs->f_frsize : -1; | | 1670 | fs->xfer_align = sfs->f_frsize > 0 ? (long)sfs->f_frsize : -1; |
1666 | fs->max_xfer_size = -1; | | 1671 | fs->max_xfer_size = -1; |
1667 | #if defined(HAVE_STRUCT_STATVFS_F_IOSIZE) | | 1672 | #if defined(HAVE_STRUCT_STATVFS_F_IOSIZE) |
1668 | fs->min_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1; | | 1673 | fs->min_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1; |
1669 | fs->incr_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1; | | 1674 | fs->incr_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1; |
1670 | #else | | 1675 | #else |
1671 | fs->min_xfer_size = sfs->f_bsize > 0 : (long)sfs->f_bsize : -1; | | 1676 | fs->min_xfer_size = sfs->f_bsize > 0 : (long)sfs->f_bsize : -1; |
1672 | fs->incr_xfer_size = sfs->f_bsize > 0 : (long)sfs->f_bsize : -1; | | 1677 | fs->incr_xfer_size = sfs->f_bsize > 0 : (long)sfs->f_bsize : -1; |
1673 | #endif | | 1678 | #endif |
1674 | } | | 1679 | } |
1675 | | | 1680 | |
1676 | /* | | 1681 | /* |
1677 | * Gather current filesystem properties on NetBSD | | 1682 | * Gather current filesystem properties on NetBSD |
1678 | */ | | 1683 | */ |
1679 | static int | | 1684 | static int |
1680 | setup_current_filesystem(struct archive_read_disk *a) | | 1685 | setup_current_filesystem(struct archive_read_disk *a) |
1681 | { | | 1686 | { |
1682 | struct tree *t = a->tree; | | 1687 | struct tree *t = a->tree; |
1683 | struct statvfs sfs; | | 1688 | struct statvfs sfs; |
1684 | int r, xr = 0; | | 1689 | int r, xr = 0; |
1685 | | | 1690 | |
1686 | t->current_filesystem->synthetic = -1; | | 1691 | t->current_filesystem->synthetic = -1; |
1687 | if (tree_enter_working_dir(t) != 0) { | | 1692 | if (tree_enter_working_dir(t) != 0) { |
1688 | archive_set_error(&a->archive, errno, "fchdir failed"); | | 1693 | archive_set_error(&a->archive, errno, "fchdir failed"); |
1689 | return (ARCHIVE_FAILED); | | 1694 | return (ARCHIVE_FAILED); |
1690 | } | | 1695 | } |
1691 | if (tree_current_is_symblic_link_target(t)) { | | 1696 | if (tree_current_is_symblic_link_target(t)) { |
1692 | r = statvfs(tree_current_access_path(t), &sfs); | | 1697 | r = statvfs(tree_current_access_path(t), &sfs); |
1693 | if (r == 0) | | 1698 | if (r == 0) |
1694 | xr = get_xfer_size(t, -1, tree_current_access_path(t)); | | 1699 | xr = get_xfer_size(t, -1, tree_current_access_path(t)); |
1695 | } else { | | 1700 | } else { |
1696 | #ifdef HAVE_FSTATVFS | | 1701 | #ifdef HAVE_FSTATVFS |
1697 | r = fstatvfs(tree_current_dir_fd(t), &sfs); | | 1702 | r = fstatvfs(tree_current_dir_fd(t), &sfs); |
1698 | if (r == 0) | | 1703 | if (r == 0) |
1699 | xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); | | 1704 | xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); |
1700 | #else | | 1705 | #else |
1701 | r = statvfs(".", &sfs); | | 1706 | r = statvfs(".", &sfs); |
1702 | if (r == 0) | | 1707 | if (r == 0) |
1703 | xr = get_xfer_size(t, -1, "."); | | 1708 | xr = get_xfer_size(t, -1, "."); |
1704 | #endif | | 1709 | #endif |
1705 | } | | 1710 | } |
1706 | if (r == -1 || xr == -1) { | | 1711 | if (r == -1 || xr == -1) { |
1707 | t->current_filesystem->remote = -1; | | 1712 | t->current_filesystem->remote = -1; |
1708 | archive_set_error(&a->archive, errno, "statvfs failed"); | | 1713 | archive_set_error(&a->archive, errno, "statvfs failed"); |
1709 | return (ARCHIVE_FAILED); | | 1714 | return (ARCHIVE_FAILED); |
1710 | } else if (xr == 1) { | | 1715 | } else if (xr == 1) { |
1711 | /* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN | | 1716 | /* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN |
1712 | * for pathconf() function. */ | | 1717 | * for pathconf() function. */ |
1713 | set_transfer_size(t->current_filesystem, &sfs); | | 1718 | set_transfer_size(t->current_filesystem, &sfs); |
1714 | } | | 1719 | } |
1715 | if (sfs.f_flag & ST_LOCAL) | | 1720 | if (sfs.f_flag & ST_LOCAL) |
1716 | t->current_filesystem->remote = 0; | | 1721 | t->current_filesystem->remote = 0; |
1717 | else | | 1722 | else |
1718 | t->current_filesystem->remote = 1; | | 1723 | t->current_filesystem->remote = 1; |
1719 | | | 1724 | |
1720 | #if defined(ST_NOATIME) | | 1725 | #if defined(ST_NOATIME) |
1721 | if (sfs.f_flag & ST_NOATIME) | | 1726 | if (sfs.f_flag & ST_NOATIME) |
1722 | t->current_filesystem->noatime = 1; | | 1727 | t->current_filesystem->noatime = 1; |
1723 | else | | 1728 | else |
1724 | #endif | | 1729 | #endif |
1725 | t->current_filesystem->noatime = 0; | | 1730 | t->current_filesystem->noatime = 0; |
1726 | | | 1731 | |
1727 | /* Set maximum filename length. */ | | 1732 | /* Set maximum filename length. */ |
1728 | t->current_filesystem->name_max = sfs.f_namemax; | | 1733 | t->current_filesystem->name_max = sfs.f_namemax; |
| | | 1734 | if (t->current_filesystem->name_max == 0) { |
| | | 1735 | archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, |
| | | 1736 | "Cannot determine name_max"); |
| | | 1737 | return (ARCHIVE_FAILED); |
| | | 1738 | } |
1729 | return (ARCHIVE_OK); | | 1739 | return (ARCHIVE_OK); |
1730 | } | | 1740 | } |
1731 | | | 1741 | |
1732 | #elif defined(HAVE_SYS_STATFS_H) && defined(HAVE_LINUX_MAGIC_H) &&\ | | 1742 | #elif defined(HAVE_SYS_STATFS_H) && defined(HAVE_LINUX_MAGIC_H) &&\ |
1733 | defined(HAVE_STATFS) && defined(HAVE_FSTATFS) | | 1743 | defined(HAVE_STATFS) && defined(HAVE_FSTATFS) |
1734 | /* | | 1744 | /* |
1735 | * Note: statfs is deprecated since LSB 3.2 | | 1745 | * Note: statfs is deprecated since LSB 3.2 |
1736 | */ | | 1746 | */ |
1737 | | | 1747 | |
1738 | #ifndef CIFS_SUPER_MAGIC | | 1748 | #ifndef CIFS_SUPER_MAGIC |
1739 | #define CIFS_SUPER_MAGIC 0xFF534D42 | | 1749 | #define CIFS_SUPER_MAGIC 0xFF534D42 |
1740 | #endif | | 1750 | #endif |
1741 | #ifndef DEVFS_SUPER_MAGIC | | 1751 | #ifndef DEVFS_SUPER_MAGIC |
1742 | #define DEVFS_SUPER_MAGIC 0x1373 | | 1752 | #define DEVFS_SUPER_MAGIC 0x1373 |
1743 | #endif | | 1753 | #endif |
1744 | | | 1754 | |
1745 | /* | | 1755 | /* |
1746 | * Gather current filesystem properties on Linux | | 1756 | * Gather current filesystem properties on Linux |
1747 | */ | | 1757 | */ |
1748 | static int | | 1758 | static int |
1749 | setup_current_filesystem(struct archive_read_disk *a) | | 1759 | setup_current_filesystem(struct archive_read_disk *a) |
1750 | { | | 1760 | { |
1751 | struct tree *t = a->tree; | | 1761 | struct tree *t = a->tree; |
1752 | struct statfs sfs; | | 1762 | struct statfs sfs; |
1753 | #if defined(HAVE_STATVFS) | | 1763 | #if defined(HAVE_STATVFS) |
1754 | struct statvfs svfs; | | 1764 | struct statvfs svfs; |
1755 | #endif | | 1765 | #endif |
1756 | int r, vr = 0, xr = 0; | | 1766 | int r, vr = 0, xr = 0; |
1757 | | | 1767 | |
1758 | if (tree_current_is_symblic_link_target(t)) { | | 1768 | if (tree_current_is_symblic_link_target(t)) { |
1759 | #if defined(HAVE_OPENAT) | | 1769 | #if defined(HAVE_OPENAT) |
1760 | /* | | 1770 | /* |
1761 | * Get file system statistics on any directory | | 1771 | * Get file system statistics on any directory |
1762 | * where current is. | | 1772 | * where current is. |
1763 | */ | | 1773 | */ |
1764 | int fd = openat(tree_current_dir_fd(t), | | 1774 | int fd = openat(tree_current_dir_fd(t), |
1765 | tree_current_access_path(t), O_RDONLY | O_CLOEXEC); | | 1775 | tree_current_access_path(t), O_RDONLY | O_CLOEXEC); |
1766 | __archive_ensure_cloexec_flag(fd); | | 1776 | __archive_ensure_cloexec_flag(fd); |
1767 | if (fd < 0) { | | 1777 | if (fd < 0) { |
1768 | archive_set_error(&a->archive, errno, | | 1778 | archive_set_error(&a->archive, errno, |
1769 | "openat failed"); | | 1779 | "openat failed"); |
1770 | return (ARCHIVE_FAILED); | | 1780 | return (ARCHIVE_FAILED); |
1771 | } | | 1781 | } |
1772 | #if defined(HAVE_FSTATVFS) | | 1782 | #if defined(HAVE_FSTATVFS) |
1773 | vr = fstatvfs(fd, &svfs);/* for f_flag, mount flags */ | | 1783 | vr = fstatvfs(fd, &svfs);/* for f_flag, mount flags */ |
1774 | #endif | | 1784 | #endif |
1775 | r = fstatfs(fd, &sfs); | | 1785 | r = fstatfs(fd, &sfs); |
1776 | if (r == 0) | | 1786 | if (r == 0) |
1777 | xr = get_xfer_size(t, fd, NULL); | | 1787 | xr = get_xfer_size(t, fd, NULL); |
1778 | close(fd); | | 1788 | close(fd); |
1779 | #else | | 1789 | #else |
1780 | if (tree_enter_working_dir(t) != 0) { | | 1790 | if (tree_enter_working_dir(t) != 0) { |
1781 | archive_set_error(&a->archive, errno, "fchdir failed"); | | 1791 | archive_set_error(&a->archive, errno, "fchdir failed"); |
1782 | return (ARCHIVE_FAILED); | | 1792 | return (ARCHIVE_FAILED); |
1783 | } | | 1793 | } |
1784 | #if defined(HAVE_STATVFS) | | 1794 | #if defined(HAVE_STATVFS) |
1785 | vr = statvfs(tree_current_access_path(t), &svfs); | | 1795 | vr = statvfs(tree_current_access_path(t), &svfs); |
1786 | #endif | | 1796 | #endif |
1787 | r = statfs(tree_current_access_path(t), &sfs); | | 1797 | r = statfs(tree_current_access_path(t), &sfs); |
1788 | if (r == 0) | | 1798 | if (r == 0) |
1789 | xr = get_xfer_size(t, -1, tree_current_access_path(t)); | | 1799 | xr = get_xfer_size(t, -1, tree_current_access_path(t)); |
1790 | #endif | | 1800 | #endif |
1791 | } else { | | 1801 | } else { |
1792 | #ifdef HAVE_FSTATFS | | 1802 | #ifdef HAVE_FSTATFS |
1793 | #if defined(HAVE_FSTATVFS) | | 1803 | #if defined(HAVE_FSTATVFS) |
1794 | vr = fstatvfs(tree_current_dir_fd(t), &svfs); | | 1804 | vr = fstatvfs(tree_current_dir_fd(t), &svfs); |
1795 | #endif | | 1805 | #endif |
1796 | r = fstatfs(tree_current_dir_fd(t), &sfs); | | 1806 | r = fstatfs(tree_current_dir_fd(t), &sfs); |
1797 | if (r == 0) | | 1807 | if (r == 0) |
1798 | xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); | | 1808 | xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); |
1799 | #else | | 1809 | #else |
1800 | if (tree_enter_working_dir(t) != 0) { | | 1810 | if (tree_enter_working_dir(t) != 0) { |
1801 | archive_set_error(&a->archive, errno, "fchdir failed"); | | 1811 | archive_set_error(&a->archive, errno, "fchdir failed"); |
1802 | return (ARCHIVE_FAILED); | | 1812 | return (ARCHIVE_FAILED); |
1803 | } | | 1813 | } |
1804 | #if defined(HAVE_STATVFS) | | 1814 | #if defined(HAVE_STATVFS) |
1805 | vr = statvfs(".", &svfs); | | 1815 | vr = statvfs(".", &svfs); |
1806 | #endif | | 1816 | #endif |
1807 | r = statfs(".", &sfs); | | 1817 | r = statfs(".", &sfs); |
1808 | if (r == 0) | | 1818 | if (r == 0) |
1809 | xr = get_xfer_size(t, -1, "."); | | 1819 | xr = get_xfer_size(t, -1, "."); |
1810 | #endif | | 1820 | #endif |
1811 | } | | 1821 | } |
1812 | if (r == -1 || xr == -1 || vr == -1) { | | 1822 | if (r == -1 || xr == -1 || vr == -1) { |
1813 | t->current_filesystem->synthetic = -1; | | 1823 | t->current_filesystem->synthetic = -1; |
1814 | t->current_filesystem->remote = -1; | | 1824 | t->current_filesystem->remote = -1; |
1815 | archive_set_error(&a->archive, errno, "statfs failed"); | | 1825 | archive_set_error(&a->archive, errno, "statfs failed"); |
1816 | return (ARCHIVE_FAILED); | | 1826 | return (ARCHIVE_FAILED); |
1817 | } else if (xr == 1) { | | 1827 | } else if (xr == 1) { |
1818 | /* pathconf(_PC_REX_*) operations are not supported. */ | | 1828 | /* pathconf(_PC_REX_*) operations are not supported. */ |
1819 | #if defined(HAVE_STATVFS) | | 1829 | #if defined(HAVE_STATVFS) |
1820 | set_transfer_size(t->current_filesystem, &svfs); | | 1830 | set_transfer_size(t->current_filesystem, &svfs); |
1821 | #else | | 1831 | #else |
1822 | set_transfer_size(t->current_filesystem, &sfs); | | 1832 | set_transfer_size(t->current_filesystem, &sfs); |
1823 | #endif | | 1833 | #endif |
1824 | } | | 1834 | } |
1825 | switch (sfs.f_type) { | | 1835 | switch (sfs.f_type) { |
1826 | case AFS_SUPER_MAGIC: | | 1836 | case AFS_SUPER_MAGIC: |
1827 | case CIFS_SUPER_MAGIC: | | 1837 | case CIFS_SUPER_MAGIC: |
1828 | case CODA_SUPER_MAGIC: | | 1838 | case CODA_SUPER_MAGIC: |
1829 | case NCP_SUPER_MAGIC:/* NetWare */ | | 1839 | case NCP_SUPER_MAGIC:/* NetWare */ |
1830 | case NFS_SUPER_MAGIC: | | 1840 | case NFS_SUPER_MAGIC: |
1831 | case SMB_SUPER_MAGIC: | | 1841 | case SMB_SUPER_MAGIC: |
1832 | t->current_filesystem->remote = 1; | | 1842 | t->current_filesystem->remote = 1; |
1833 | t->current_filesystem->synthetic = 0; | | 1843 | t->current_filesystem->synthetic = 0; |
1834 | break; | | 1844 | break; |
1835 | case DEVFS_SUPER_MAGIC: | | 1845 | case DEVFS_SUPER_MAGIC: |
1836 | case PROC_SUPER_MAGIC: | | 1846 | case PROC_SUPER_MAGIC: |
1837 | case USBDEVICE_SUPER_MAGIC: | | 1847 | case USBDEVICE_SUPER_MAGIC: |
1838 | t->current_filesystem->remote = 0; | | 1848 | t->current_filesystem->remote = 0; |
1839 | t->current_filesystem->synthetic = 1; | | 1849 | t->current_filesystem->synthetic = 1; |
1840 | break; | | 1850 | break; |
1841 | default: | | 1851 | default: |
1842 | t->current_filesystem->remote = 0; | | 1852 | t->current_filesystem->remote = 0; |
1843 | t->current_filesystem->synthetic = 0; | | 1853 | t->current_filesystem->synthetic = 0; |
1844 | break; | | 1854 | break; |
1845 | } | | 1855 | } |
1846 | | | 1856 | |
1847 | #if defined(ST_NOATIME) | | 1857 | #if defined(ST_NOATIME) |
1848 | #if defined(HAVE_STATVFS) | | 1858 | #if defined(HAVE_STATVFS) |
1849 | if (svfs.f_flag & ST_NOATIME) | | 1859 | if (svfs.f_flag & ST_NOATIME) |
1850 | #else | | 1860 | #else |
1851 | if (sfs.f_flag & ST_NOATIME) | | 1861 | if (sfs.f_flag & ST_NOATIME) |
1852 | #endif | | 1862 | #endif |
1853 | t->current_filesystem->noatime = 1; | | 1863 | t->current_filesystem->noatime = 1; |
1854 | else | | 1864 | else |
1855 | #endif | | 1865 | #endif |
1856 | t->current_filesystem->noatime = 0; | | 1866 | t->current_filesystem->noatime = 0; |
1857 | | | 1867 | |
1858 | #if defined(USE_READDIR_R) | | 1868 | #if defined(USE_READDIR_R) |
1859 | /* Set maximum filename length. */ | | 1869 | /* Set maximum filename length. */ |
1860 | t->current_filesystem->name_max = sfs.f_namelen; | | 1870 | t->current_filesystem->name_max = sfs.f_namelen; |
| | | 1871 | if (t->current_filesystem->name_max == 0) { |
| | | 1872 | archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, |
| | | 1873 | "Cannot determine name_max"); |
| | | 1874 | return (ARCHIVE_FAILED); |
| | | 1875 | } |
1861 | #endif | | 1876 | #endif |
1862 | return (ARCHIVE_OK); | | 1877 | return (ARCHIVE_OK); |
1863 | } | | 1878 | } |
1864 | | | 1879 | |
1865 | #elif defined(HAVE_SYS_STATVFS_H) &&\ | | 1880 | #elif defined(HAVE_SYS_STATVFS_H) &&\ |
1866 | (defined(HAVE_STATVFS) || defined(HAVE_FSTATVFS)) | | 1881 | (defined(HAVE_STATVFS) || defined(HAVE_FSTATVFS)) |
1867 | | | 1882 | |
1868 | /* | | 1883 | /* |
1869 | * Gather current filesystem properties on other posix platform. | | 1884 | * Gather current filesystem properties on other posix platform. |
1870 | */ | | 1885 | */ |
1871 | static int | | 1886 | static int |
1872 | setup_current_filesystem(struct archive_read_disk *a) | | 1887 | setup_current_filesystem(struct archive_read_disk *a) |
1873 | { | | 1888 | { |
1874 | struct tree *t = a->tree; | | 1889 | struct tree *t = a->tree; |
1875 | struct statvfs sfs; | | 1890 | struct statvfs sfs; |
1876 | int r, xr = 0; | | 1891 | int r, xr = 0; |
1877 | | | 1892 | |
1878 | t->current_filesystem->synthetic = -1;/* Not supported */ | | 1893 | t->current_filesystem->synthetic = -1;/* Not supported */ |
1879 | t->current_filesystem->remote = -1;/* Not supported */ | | 1894 | t->current_filesystem->remote = -1;/* Not supported */ |
1880 | if (tree_current_is_symblic_link_target(t)) { | | 1895 | if (tree_current_is_symblic_link_target(t)) { |
1881 | #if defined(HAVE_OPENAT) | | 1896 | #if defined(HAVE_OPENAT) |
1882 | /* | | 1897 | /* |
1883 | * Get file system statistics on any directory | | 1898 | * Get file system statistics on any directory |
1884 | * where current is. | | 1899 | * where current is. |
1885 | */ | | 1900 | */ |
1886 | int fd = openat(tree_current_dir_fd(t), | | 1901 | int fd = openat(tree_current_dir_fd(t), |
1887 | tree_current_access_path(t), O_RDONLY | O_CLOEXEC); | | 1902 | tree_current_access_path(t), O_RDONLY | O_CLOEXEC); |
1888 | __archive_ensure_cloexec_flag(fd); | | 1903 | __archive_ensure_cloexec_flag(fd); |
1889 | if (fd < 0) { | | 1904 | if (fd < 0) { |
1890 | archive_set_error(&a->archive, errno, | | 1905 | archive_set_error(&a->archive, errno, |
1891 | "openat failed"); | | 1906 | "openat failed"); |
1892 | return (ARCHIVE_FAILED); | | 1907 | return (ARCHIVE_FAILED); |
1893 | } | | 1908 | } |
1894 | r = fstatvfs(fd, &sfs); | | 1909 | r = fstatvfs(fd, &sfs); |
1895 | if (r == 0) | | 1910 | if (r == 0) |
1896 | xr = get_xfer_size(t, fd, NULL); | | 1911 | xr = get_xfer_size(t, fd, NULL); |
1897 | close(fd); | | 1912 | close(fd); |
1898 | #else | | 1913 | #else |
1899 | if (tree_enter_working_dir(t) != 0) { | | 1914 | if (tree_enter_working_dir(t) != 0) { |
1900 | archive_set_error(&a->archive, errno, "fchdir failed"); | | 1915 | archive_set_error(&a->archive, errno, "fchdir failed"); |
1901 | return (ARCHIVE_FAILED); | | 1916 | return (ARCHIVE_FAILED); |
1902 | } | | 1917 | } |
1903 | r = statvfs(tree_current_access_path(t), &sfs); | | 1918 | r = statvfs(tree_current_access_path(t), &sfs); |
1904 | if (r == 0) | | 1919 | if (r == 0) |
1905 | xr = get_xfer_size(t, -1, tree_current_access_path(t)); | | 1920 | xr = get_xfer_size(t, -1, tree_current_access_path(t)); |
1906 | #endif | | 1921 | #endif |
1907 | } else { | | 1922 | } else { |
1908 | #ifdef HAVE_FSTATVFS | | 1923 | #ifdef HAVE_FSTATVFS |
1909 | r = fstatvfs(tree_current_dir_fd(t), &sfs); | | 1924 | r = fstatvfs(tree_current_dir_fd(t), &sfs); |
1910 | if (r == 0) | | 1925 | if (r == 0) |
1911 | xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); | | 1926 | xr = get_xfer_size(t, tree_current_dir_fd(t), NULL); |
1912 | #else | | 1927 | #else |
1913 | if (tree_enter_working_dir(t) != 0) { | | 1928 | if (tree_enter_working_dir(t) != 0) { |
1914 | archive_set_error(&a->archive, errno, "fchdir failed"); | | 1929 | archive_set_error(&a->archive, errno, "fchdir failed"); |
1915 | return (ARCHIVE_FAILED); | | 1930 | return (ARCHIVE_FAILED); |
1916 | } | | 1931 | } |
1917 | r = statvfs(".", &sfs); | | 1932 | r = statvfs(".", &sfs); |
1918 | if (r == 0) | | 1933 | if (r == 0) |
1919 | xr = get_xfer_size(t, -1, "."); | | 1934 | xr = get_xfer_size(t, -1, "."); |
1920 | #endif | | 1935 | #endif |
1921 | } | | 1936 | } |
1922 | if (r == -1 || xr == -1) { | | 1937 | if (r == -1 || xr == -1) { |
1923 | t->current_filesystem->synthetic = -1; | | 1938 | t->current_filesystem->synthetic = -1; |
1924 | t->current_filesystem->remote = -1; | | 1939 | t->current_filesystem->remote = -1; |
1925 | archive_set_error(&a->archive, errno, "statvfs failed"); | | 1940 | archive_set_error(&a->archive, errno, "statvfs failed"); |
1926 | return (ARCHIVE_FAILED); | | 1941 | return (ARCHIVE_FAILED); |
1927 | } else if (xr == 1) { | | 1942 | } else if (xr == 1) { |
1928 | /* pathconf(_PC_REX_*) operations are not supported. */ | | 1943 | /* pathconf(_PC_REX_*) operations are not supported. */ |
1929 | set_transfer_size(t->current_filesystem, &sfs); | | 1944 | set_transfer_size(t->current_filesystem, &sfs); |
1930 | } | | 1945 | } |
1931 | | | 1946 | |
1932 | #if defined(ST_NOATIME) | | 1947 | #if defined(ST_NOATIME) |
1933 | if (sfs.f_flag & ST_NOATIME) | | 1948 | if (sfs.f_flag & ST_NOATIME) |
1934 | t->current_filesystem->noatime = 1; | | 1949 | t->current_filesystem->noatime = 1; |
1935 | else | | 1950 | else |
1936 | #endif | | 1951 | #endif |
1937 | t->current_filesystem->noatime = 0; | | 1952 | t->current_filesystem->noatime = 0; |
1938 | | | 1953 | |
1939 | #if defined(USE_READDIR_R) | | 1954 | #if defined(USE_READDIR_R) |
1940 | /* Set maximum filename length. */ | | 1955 | /* Set maximum filename length. */ |
1941 | t->current_filesystem->name_max = sfs.f_namemax; | | 1956 | t->current_filesystem->name_max = sfs.f_namemax; |
| | | 1957 | if (t->current_filesystem->name_max == 0) { |
| | | 1958 | archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, |
| | | 1959 | "Cannot determine name_max"); |
| | | 1960 | return (ARCHIVE_FAILED); |
| | | 1961 | } |
1942 | #endif | | 1962 | #endif |
1943 | return (ARCHIVE_OK); | | 1963 | return (ARCHIVE_OK); |
1944 | } | | 1964 | } |
1945 | | | 1965 | |
1946 | #else | | 1966 | #else |
1947 | | | 1967 | |
1948 | /* | | 1968 | /* |
1949 | * Generic: Gather current filesystem properties. | | 1969 | * Generic: Gather current filesystem properties. |
1950 | * TODO: Is this generic function really needed? | | 1970 | * TODO: Is this generic function really needed? |
1951 | */ | | 1971 | */ |
1952 | static int | | 1972 | static int |
1953 | setup_current_filesystem(struct archive_read_disk *a) | | 1973 | setup_current_filesystem(struct archive_read_disk *a) |
1954 | { | | 1974 | { |
1955 | struct tree *t = a->tree; | | 1975 | struct tree *t = a->tree; |
1956 | #if defined(_PC_NAME_MAX) && defined(USE_READDIR_R) | | 1976 | #if defined(_PC_NAME_MAX) && defined(USE_READDIR_R) |
1957 | long nm; | | 1977 | long nm; |
1958 | #endif | | 1978 | #endif |
1959 | t->current_filesystem->synthetic = -1;/* Not supported */ | | 1979 | t->current_filesystem->synthetic = -1;/* Not supported */ |
1960 | t->current_filesystem->remote = -1;/* Not supported */ | | 1980 | t->current_filesystem->remote = -1;/* Not supported */ |
1961 | t->current_filesystem->noatime = 0; | | 1981 | t->current_filesystem->noatime = 0; |
1962 | (void)get_xfer_size(t, -1, ".");/* Dummy call to avoid build error. */ | | 1982 | (void)get_xfer_size(t, -1, ".");/* Dummy call to avoid build error. */ |
1963 | t->current_filesystem->xfer_align = -1;/* Unknown */ | | 1983 | t->current_filesystem->xfer_align = -1;/* Unknown */ |
1964 | t->current_filesystem->max_xfer_size = -1; | | 1984 | t->current_filesystem->max_xfer_size = -1; |
1965 | t->current_filesystem->min_xfer_size = -1; | | 1985 | t->current_filesystem->min_xfer_size = -1; |
1966 | t->current_filesystem->incr_xfer_size = -1; | | 1986 | t->current_filesystem->incr_xfer_size = -1; |
1967 | | | 1987 | |
1968 | #if defined(USE_READDIR_R) | | 1988 | #if defined(USE_READDIR_R) |
1969 | /* Set maximum filename length. */ | | 1989 | /* Set maximum filename length. */ |
1970 | # if defined(_PC_NAME_MAX) | | 1990 | # if defined(_PC_NAME_MAX) |
1971 | if (tree_current_is_symblic_link_target(t)) { | | 1991 | if (tree_current_is_symblic_link_target(t)) { |
1972 | if (tree_enter_working_dir(t) != 0) { | | 1992 | if (tree_enter_working_dir(t) != 0) { |
1973 | archive_set_error(&a->archive, errno, "fchdir failed"); | | 1993 | archive_set_error(&a->archive, errno, "fchdir failed"); |
1974 | return (ARCHIVE_FAILED); | | 1994 | return (ARCHIVE_FAILED); |
1975 | } | | 1995 | } |
1976 | nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX); | | 1996 | nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX); |
1977 | } else | | 1997 | } else |
1978 | nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX); | | 1998 | nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX); |
1979 | if (nm == -1) | | 1999 | if (nm == -1) |
1980 | # endif /* _PC_NAME_MAX */ | | 2000 | # endif /* _PC_NAME_MAX */ |
1981 | /* | | 2001 | /* |
1982 | * Some systems (HP-UX or others?) incorrectly defined | | 2002 | * Some systems (HP-UX or others?) incorrectly defined |
1983 | * NAME_MAX macro to be a smaller value. | | 2003 | * NAME_MAX macro to be a smaller value. |
1984 | */ | | 2004 | */ |
1985 | # if defined(NAME_MAX) && NAME_MAX >= 255 | | 2005 | # if defined(NAME_MAX) && NAME_MAX >= 255 |
1986 | t->current_filesystem->name_max = NAME_MAX; | | 2006 | t->current_filesystem->name_max = NAME_MAX; |
1987 | # else | | 2007 | # else |
1988 | /* No way to get a trusted value of maximum filename | | 2008 | /* No way to get a trusted value of maximum filename |
1989 | * length. */ | | 2009 | * length. */ |
1990 | t->current_filesystem->name_max = PATH_MAX; | | 2010 | t->current_filesystem->name_max = PATH_MAX; |
1991 | # endif /* NAME_MAX */ | | 2011 | # endif /* NAME_MAX */ |
1992 | # if defined(_PC_NAME_MAX) | | 2012 | # if defined(_PC_NAME_MAX) |
1993 | else | | 2013 | else |
1994 | t->current_filesystem->name_max = nm; | | 2014 | t->current_filesystem->name_max = nm; |
1995 | # endif /* _PC_NAME_MAX */ | | 2015 | # endif /* _PC_NAME_MAX */ |
| | | 2016 | if (t->current_filesystem->name_max == 0) { |
| | | 2017 | archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, |
| | | 2018 | "Cannot determine name_max"); |
| | | 2019 | return (ARCHIVE_FAILED); |
| | | 2020 | } |
1996 | #endif /* USE_READDIR_R */ | | 2021 | #endif /* USE_READDIR_R */ |
1997 | return (ARCHIVE_OK); | | 2022 | return (ARCHIVE_OK); |
1998 | } | | 2023 | } |
1999 | | | 2024 | |
2000 | #endif | | 2025 | #endif |
2001 | | | 2026 | |
2002 | static int | | 2027 | static int |
2003 | close_and_restore_time(int fd, struct tree *t, struct restore_time *rt) | | 2028 | close_and_restore_time(int fd, struct tree *t, struct restore_time *rt) |
2004 | { | | 2029 | { |
2005 | #ifndef HAVE_UTIMES | | 2030 | #ifndef HAVE_UTIMES |
2006 | (void)t; /* UNUSED */ | | 2031 | (void)t; /* UNUSED */ |
2007 | (void)rt; /* UNUSED */ | | 2032 | (void)rt; /* UNUSED */ |
2008 | return (close(fd)); | | 2033 | return (close(fd)); |
2009 | #else | | 2034 | #else |
2010 | #if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__) | | 2035 | #if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__) |
2011 | struct timespec timespecs[2]; | | 2036 | struct timespec timespecs[2]; |
2012 | #endif | | 2037 | #endif |
2013 | struct timeval times[2]; | | 2038 | struct timeval times[2]; |
2014 | | | 2039 | |
2015 | if ((t->flags & needsRestoreTimes) == 0 || rt->noatime) { | | 2040 | if ((t->flags & needsRestoreTimes) == 0 || rt->noatime) { |
2016 | if (fd >= 0) | | 2041 | if (fd >= 0) |
2017 | return (close(fd)); | | 2042 | return (close(fd)); |
2018 | else | | 2043 | else |
2019 | return (0); | | 2044 | return (0); |
2020 | } | | 2045 | } |
2021 | | | 2046 | |
2022 | #if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__) | | 2047 | #if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__) |
2023 | timespecs[1].tv_sec = rt->mtime; | | 2048 | timespecs[1].tv_sec = rt->mtime; |
2024 | timespecs[1].tv_nsec = rt->mtime_nsec; | | 2049 | timespecs[1].tv_nsec = rt->mtime_nsec; |
2025 | | | 2050 | |
2026 | timespecs[0].tv_sec = rt->atime; | | 2051 | timespecs[0].tv_sec = rt->atime; |
2027 | timespecs[0].tv_nsec = rt->atime_nsec; | | 2052 | timespecs[0].tv_nsec = rt->atime_nsec; |
2028 | /* futimens() is defined in POSIX.1-2008. */ | | 2053 | /* futimens() is defined in POSIX.1-2008. */ |
2029 | if (futimens(fd, timespecs) == 0) | | 2054 | if (futimens(fd, timespecs) == 0) |
2030 | return (close(fd)); | | 2055 | return (close(fd)); |
2031 | #endif | | 2056 | #endif |
2032 | | | 2057 | |
2033 | times[1].tv_sec = rt->mtime; | | 2058 | times[1].tv_sec = rt->mtime; |
2034 | times[1].tv_usec = rt->mtime_nsec / 1000; | | 2059 | times[1].tv_usec = rt->mtime_nsec / 1000; |
2035 | | | 2060 | |
2036 | times[0].tv_sec = rt->atime; | | 2061 | times[0].tv_sec = rt->atime; |
2037 | times[0].tv_usec = rt->atime_nsec / 1000; | | 2062 | times[0].tv_usec = rt->atime_nsec / 1000; |
2038 | | | 2063 | |
2039 | #if !defined(HAVE_FUTIMENS) && defined(HAVE_FUTIMES) && !defined(__CYGWIN__) | | 2064 | #if !defined(HAVE_FUTIMENS) && defined(HAVE_FUTIMES) && !defined(__CYGWIN__) |
2040 | if (futimes(fd, times) == 0) | | 2065 | if (futimes(fd, times) == 0) |
2041 | return (close(fd)); | | 2066 | return (close(fd)); |
2042 | #endif | | 2067 | #endif |
2043 | close(fd); | | 2068 | close(fd); |
2044 | #if defined(HAVE_FUTIMESAT) | | 2069 | #if defined(HAVE_FUTIMESAT) |
2045 | if (futimesat(tree_current_dir_fd(t), rt->name, times) == 0) | | 2070 | if (futimesat(tree_current_dir_fd(t), rt->name, times) == 0) |
2046 | return (0); | | 2071 | return (0); |
2047 | #endif | | 2072 | #endif |
2048 | #ifdef HAVE_LUTIMES | | 2073 | #ifdef HAVE_LUTIMES |
2049 | if (lutimes(rt->name, times) != 0) | | 2074 | if (lutimes(rt->name, times) != 0) |
2050 | #else | | 2075 | #else |
2051 | if (AE_IFLNK != rt->filetype && utimes(rt->name, times) != 0) | | 2076 | if (AE_IFLNK != rt->filetype && utimes(rt->name, times) != 0) |
2052 | #endif | | 2077 | #endif |
2053 | return (-1); | | 2078 | return (-1); |
2054 | #endif | | 2079 | #endif |
2055 | return (0); | | 2080 | return (0); |
2056 | } | | 2081 | } |
2057 | | | 2082 | |
2058 | static int | | 2083 | static int |
2059 | open_on_current_dir(struct tree *t, const char *path, int flags) | | 2084 | open_on_current_dir(struct tree *t, const char *path, int flags) |
2060 | { | | 2085 | { |
2061 | #ifdef HAVE_OPENAT | | 2086 | #ifdef HAVE_OPENAT |
2062 | return (openat(tree_current_dir_fd(t), path, flags)); | | 2087 | return (openat(tree_current_dir_fd(t), path, flags)); |
2063 | #else | | 2088 | #else |
2064 | if (tree_enter_working_dir(t) != 0) | | 2089 | if (tree_enter_working_dir(t) != 0) |
2065 | return (-1); | | 2090 | return (-1); |
2066 | return (open(path, flags)); | | 2091 | return (open(path, flags)); |
2067 | #endif | | 2092 | #endif |
2068 | } | | 2093 | } |
2069 | | | 2094 | |
2070 | static int | | 2095 | static int |
2071 | tree_dup(int fd) | | 2096 | tree_dup(int fd) |
2072 | { | | 2097 | { |
2073 | int new_fd; | | 2098 | int new_fd; |
2074 | #ifdef F_DUPFD_CLOEXEC | | 2099 | #ifdef F_DUPFD_CLOEXEC |
2075 | static volatile int can_dupfd_cloexec = 1; | | 2100 | static volatile int can_dupfd_cloexec = 1; |
2076 | | | 2101 | |
2077 | if (can_dupfd_cloexec) { | | 2102 | if (can_dupfd_cloexec) { |
2078 | new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); | | 2103 | new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); |
2079 | if (new_fd != -1) | | 2104 | if (new_fd != -1) |
2080 | return (new_fd); | | 2105 | return (new_fd); |
2081 | /* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC, | | 2106 | /* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC, |
2082 | * but it cannot be used. So we have to try dup(). */ | | 2107 | * but it cannot be used. So we have to try dup(). */ |
2083 | /* We won't try F_DUPFD_CLOEXEC. */ | | 2108 | /* We won't try F_DUPFD_CLOEXEC. */ |
2084 | can_dupfd_cloexec = 0; | | 2109 | can_dupfd_cloexec = 0; |
2085 | } | | 2110 | } |
2086 | #endif /* F_DUPFD_CLOEXEC */ | | 2111 | #endif /* F_DUPFD_CLOEXEC */ |
2087 | new_fd = dup(fd); | | 2112 | new_fd = dup(fd); |
2088 | __archive_ensure_cloexec_flag(new_fd); | | 2113 | __archive_ensure_cloexec_flag(new_fd); |
2089 | return (new_fd); | | 2114 | return (new_fd); |
2090 | } | | 2115 | } |
2091 | | | 2116 | |
2092 | /* | | 2117 | /* |
2093 | * Add a directory path to the current stack. | | 2118 | * Add a directory path to the current stack. |
2094 | */ | | 2119 | */ |
2095 | static void | | 2120 | static void |
2096 | tree_push(struct tree *t, const char *path, int filesystem_id, | | 2121 | tree_push(struct tree *t, const char *path, int filesystem_id, |
2097 | int64_t dev, int64_t ino, struct restore_time *rt) | | 2122 | int64_t dev, int64_t ino, struct restore_time *rt) |
2098 | { | | 2123 | { |
2099 | struct tree_entry *te; | | 2124 | struct tree_entry *te; |
2100 | | | 2125 | |
2101 | te = calloc(1, sizeof(*te)); | | 2126 | te = calloc(1, sizeof(*te)); |
2102 | te->next = t->stack; | | 2127 | te->next = t->stack; |
2103 | te->parent = t->current; | | 2128 | te->parent = t->current; |
2104 | if (te->parent) | | 2129 | if (te->parent) |
2105 | te->depth = te->parent->depth + 1; | | 2130 | te->depth = te->parent->depth + 1; |
2106 | t->stack = te; | | 2131 | t->stack = te; |
2107 | archive_string_init(&te->name); | | 2132 | archive_string_init(&te->name); |
2108 | te->symlink_parent_fd = -1; | | 2133 | te->symlink_parent_fd = -1; |
2109 | archive_strcpy(&te->name, path); | | 2134 | archive_strcpy(&te->name, path); |
2110 | te->flags = needsDescent | needsOpen | needsAscent; | | 2135 | te->flags = needsDescent | needsOpen | needsAscent; |
2111 | te->filesystem_id = filesystem_id; | | 2136 | te->filesystem_id = filesystem_id; |
2112 | te->dev = dev; | | 2137 | te->dev = dev; |
2113 | te->ino = ino; | | 2138 | te->ino = ino; |
2114 | te->dirname_length = t->dirname_length; | | 2139 | te->dirname_length = t->dirname_length; |
2115 | te->restore_time.name = te->name.s; | | 2140 | te->restore_time.name = te->name.s; |
2116 | if (rt != NULL) { | | 2141 | if (rt != NULL) { |
2117 | te->restore_time.mtime = rt->mtime; | | 2142 | te->restore_time.mtime = rt->mtime; |
2118 | te->restore_time.mtime_nsec = rt->mtime_nsec; | | 2143 | te->restore_time.mtime_nsec = rt->mtime_nsec; |
2119 | te->restore_time.atime = rt->atime; | | 2144 | te->restore_time.atime = rt->atime; |
2120 | te->restore_time.atime_nsec = rt->atime_nsec; | | 2145 | te->restore_time.atime_nsec = rt->atime_nsec; |
2121 | te->restore_time.filetype = rt->filetype; | | 2146 | te->restore_time.filetype = rt->filetype; |
2122 | te->restore_time.noatime = rt->noatime; | | 2147 | te->restore_time.noatime = rt->noatime; |
2123 | } | | 2148 | } |
2124 | } | | 2149 | } |
2125 | | | 2150 | |
2126 | /* | | 2151 | /* |
2127 | * Append a name to the current dir path. | | 2152 | * Append a name to the current dir path. |
2128 | */ | | 2153 | */ |
2129 | static void | | 2154 | static void |
2130 | tree_append(struct tree *t, const char *name, size_t name_length) | | 2155 | tree_append(struct tree *t, const char *name, size_t name_length) |
2131 | { | | 2156 | { |
2132 | size_t size_needed; | | 2157 | size_t size_needed; |
2133 | | | 2158 | |
2134 | t->path.s[t->dirname_length] = '\0'; | | 2159 | t->path.s[t->dirname_length] = '\0'; |
2135 | t->path.length = t->dirname_length; | | 2160 | t->path.length = t->dirname_length; |
2136 | /* Strip trailing '/' from name, unless entire name is "/". */ | | 2161 | /* Strip trailing '/' from name, unless entire name is "/". */ |
2137 | while (name_length > 1 && name[name_length - 1] == '/') | | 2162 | while (name_length > 1 && name[name_length - 1] == '/') |
2138 | name_length--; | | 2163 | name_length--; |
2139 | | | 2164 | |
2140 | /* Resize pathname buffer as needed. */ | | 2165 | /* Resize pathname buffer as needed. */ |
2141 | size_needed = name_length + t->dirname_length + 2; | | 2166 | size_needed = name_length + t->dirname_length + 2; |
2142 | archive_string_ensure(&t->path, size_needed); | | 2167 | archive_string_ensure(&t->path, size_needed); |
2143 | /* Add a separating '/' if it's needed. */ | | 2168 | /* Add a separating '/' if it's needed. */ |
2144 | if (t->dirname_length > 0 && t->path.s[archive_strlen(&t->path)-1] != '/') | | 2169 | if (t->dirname_length > 0 && t->path.s[archive_strlen(&t->path)-1] != '/') |
2145 | archive_strappend_char(&t->path, '/'); | | 2170 | archive_strappend_char(&t->path, '/'); |
2146 | t->basename = t->path.s + archive_strlen(&t->path); | | 2171 | t->basename = t->path.s + archive_strlen(&t->path); |
2147 | archive_strncat(&t->path, name, name_length); | | 2172 | archive_strncat(&t->path, name, name_length); |
2148 | t->restore_time.name = t->basename; | | 2173 | t->restore_time.name = t->basename; |
2149 | } | | 2174 | } |
2150 | | | 2175 | |
2151 | /* | | 2176 | /* |
2152 | * Open a directory tree for traversal. | | 2177 | * Open a directory tree for traversal. |
2153 | */ | | 2178 | */ |
2154 | static struct tree * | | 2179 | static struct tree * |
2155 | tree_open(const char *path, int symlink_mode, int restore_time) | | 2180 | tree_open(const char *path, int symlink_mode, int restore_time) |
2156 | { | | 2181 | { |
2157 | struct tree *t; | | 2182 | struct tree *t; |
2158 | | | 2183 | |
2159 | if ((t = calloc(1, sizeof(*t))) == NULL) | | 2184 | if ((t = calloc(1, sizeof(*t))) == NULL) |
2160 | return (NULL); | | 2185 | return (NULL); |
2161 | archive_string_init(&t->path); | | 2186 | archive_string_init(&t->path); |
2162 | archive_string_ensure(&t->path, 31); | | 2187 | archive_string_ensure(&t->path, 31); |
2163 | t->initial_symlink_mode = symlink_mode; | | 2188 | t->initial_symlink_mode = symlink_mode; |
2164 | return (tree_reopen(t, path, restore_time)); | | 2189 | return (tree_reopen(t, path, restore_time)); |
2165 | } | | 2190 | } |
2166 | | | 2191 | |
2167 | static struct tree * | | 2192 | static struct tree * |
2168 | tree_reopen(struct tree *t, const char *path, int restore_time) | | 2193 | tree_reopen(struct tree *t, const char *path, int restore_time) |
2169 | { | | 2194 | { |
2170 | #if defined(O_PATH) | | 2195 | #if defined(O_PATH) |
2171 | /* Linux */ | | 2196 | /* Linux */ |
2172 | const int o_flag = O_PATH; | | 2197 | const int o_flag = O_PATH; |
2173 | #elif defined(O_SEARCH) | | 2198 | #elif defined(O_SEARCH) |
2174 | /* SunOS */ | | 2199 | /* SunOS */ |
2175 | const int o_flag = O_SEARCH; | | 2200 | const int o_flag = O_SEARCH; |
2176 | #elif defined(O_EXEC) | | 2201 | #elif defined(O_EXEC) |
2177 | /* FreeBSD */ | | 2202 | /* FreeBSD */ |
2178 | const int o_flag = O_EXEC; | | 2203 | const int o_flag = O_EXEC; |
2179 | #endif | | 2204 | #endif |
2180 | | | 2205 | |
2181 | t->flags = (restore_time != 0)?needsRestoreTimes:0; | | 2206 | t->flags = (restore_time != 0)?needsRestoreTimes:0; |
2182 | t->flags |= onInitialDir; | | 2207 | t->flags |= onInitialDir; |
2183 | t->visit_type = 0; | | 2208 | t->visit_type = 0; |
2184 | t->tree_errno = 0; | | 2209 | t->tree_errno = 0; |
2185 | t->dirname_length = 0; | | 2210 | t->dirname_length = 0; |
2186 | t->depth = 0; | | 2211 | t->depth = 0; |
2187 | t->descend = 0; | | 2212 | t->descend = 0; |
2188 | t->current = NULL; | | 2213 | t->current = NULL; |
2189 | t->d = INVALID_DIR_HANDLE; | | 2214 | t->d = INVALID_DIR_HANDLE; |
2190 | t->symlink_mode = t->initial_symlink_mode; | | 2215 | t->symlink_mode = t->initial_symlink_mode; |
2191 | archive_string_empty(&t->path); | | 2216 | archive_string_empty(&t->path); |
2192 | t->entry_fd = -1; | | 2217 | t->entry_fd = -1; |
2193 | t->entry_eof = 0; | | 2218 | t->entry_eof = 0; |
2194 | t->entry_remaining_bytes = 0; | | 2219 | t->entry_remaining_bytes = 0; |
2195 | t->initial_filesystem_id = -1; | | 2220 | t->initial_filesystem_id = -1; |
2196 | | | 2221 | |
2197 | /* First item is set up a lot like a symlink traversal. */ | | 2222 | /* First item is set up a lot like a symlink traversal. */ |
2198 | tree_push(t, path, 0, 0, 0, NULL); | | 2223 | tree_push(t, path, 0, 0, 0, NULL); |
2199 | t->stack->flags = needsFirstVisit; | | 2224 | t->stack->flags = needsFirstVisit; |
2200 | t->maxOpenCount = t->openCount = 1; | | 2225 | t->maxOpenCount = t->openCount = 1; |
2201 | t->initial_dir_fd = open(".", O_RDONLY | O_CLOEXEC); | | 2226 | t->initial_dir_fd = open(".", O_RDONLY | O_CLOEXEC); |
2202 | #if defined(O_PATH) || defined(O_SEARCH) || defined(O_EXEC) | | 2227 | #if defined(O_PATH) || defined(O_SEARCH) || defined(O_EXEC) |
2203 | /* | | 2228 | /* |
2204 | * Most likely reason to fail opening "." is that it's not readable, | | 2229 | * Most likely reason to fail opening "." is that it's not readable, |
2205 | * so try again for execute. The consequences of not opening this are | | 2230 | * so try again for execute. The consequences of not opening this are |
2206 | * unhelpful and unnecessary errors later. | | 2231 | * unhelpful and unnecessary errors later. |
2207 | */ | | 2232 | */ |
2208 | if (t->initial_dir_fd < 0) | | 2233 | if (t->initial_dir_fd < 0) |
2209 | t->initial_dir_fd = open(".", o_flag | O_CLOEXEC); | | 2234 | t->initial_dir_fd = open(".", o_flag | O_CLOEXEC); |
2210 | #endif | | 2235 | #endif |
2211 | __archive_ensure_cloexec_flag(t->initial_dir_fd); | | 2236 | __archive_ensure_cloexec_flag(t->initial_dir_fd); |
2212 | t->working_dir_fd = tree_dup(t->initial_dir_fd); | | 2237 | t->working_dir_fd = tree_dup(t->initial_dir_fd); |
2213 | return (t); | | 2238 | return (t); |
2214 | } | | 2239 | } |
2215 | | | 2240 | |
2216 | static int | | 2241 | static int |
2217 | tree_descent(struct tree *t) | | 2242 | tree_descent(struct tree *t) |
2218 | { | | 2243 | { |
2219 | int flag, new_fd, r = 0; | | 2244 | int flag, new_fd, r = 0; |
2220 | | | 2245 | |
2221 | t->dirname_length = archive_strlen(&t->path); | | 2246 | t->dirname_length = archive_strlen(&t->path); |
2222 | flag = O_RDONLY | O_CLOEXEC; | | 2247 | flag = O_RDONLY | O_CLOEXEC; |
2223 | #if defined(O_DIRECTORY) | | 2248 | #if defined(O_DIRECTORY) |
2224 | flag |= O_DIRECTORY; | | 2249 | flag |= O_DIRECTORY; |
2225 | #endif | | 2250 | #endif |
2226 | new_fd = open_on_current_dir(t, t->stack->name.s, flag); | | 2251 | new_fd = open_on_current_dir(t, t->stack->name.s, flag); |
2227 | __archive_ensure_cloexec_flag(new_fd); | | 2252 | __archive_ensure_cloexec_flag(new_fd); |
2228 | if (new_fd < 0) { | | 2253 | if (new_fd < 0) { |
2229 | t->tree_errno = errno; | | 2254 | t->tree_errno = errno; |
2230 | r = TREE_ERROR_DIR; | | 2255 | r = TREE_ERROR_DIR; |
2231 | } else { | | 2256 | } else { |
2232 | t->depth++; | | 2257 | t->depth++; |
2233 | /* If it is a link, set up fd for the ascent. */ | | 2258 | /* If it is a link, set up fd for the ascent. */ |
2234 | if (t->stack->flags & isDirLink) { | | 2259 | if (t->stack->flags & isDirLink) { |
2235 | t->stack->symlink_parent_fd = t->working_dir_fd; | | 2260 | t->stack->symlink_parent_fd = t->working_dir_fd; |
2236 | t->openCount++; | | 2261 | t->openCount++; |
2237 | if (t->openCount > t->maxOpenCount) | | 2262 | if (t->openCount > t->maxOpenCount) |
2238 | t->maxOpenCount = t->openCount; | | 2263 | t->maxOpenCount = t->openCount; |
2239 | } else | | 2264 | } else |
2240 | close(t->working_dir_fd); | | 2265 | close(t->working_dir_fd); |
2241 | /* Renew the current working directory. */ | | 2266 | /* Renew the current working directory. */ |
2242 | t->working_dir_fd = new_fd; | | 2267 | t->working_dir_fd = new_fd; |
2243 | t->flags &= ~onWorkingDir; | | 2268 | t->flags &= ~onWorkingDir; |
2244 | } | | 2269 | } |
2245 | return (r); | | 2270 | return (r); |
2246 | } | | 2271 | } |
2247 | | | 2272 | |
2248 | /* | | 2273 | /* |
2249 | * We've finished a directory; ascend back to the parent. | | 2274 | * We've finished a directory; ascend back to the parent. |
2250 | */ | | 2275 | */ |
2251 | static int | | 2276 | static int |
2252 | tree_ascend(struct tree *t) | | 2277 | tree_ascend(struct tree *t) |
2253 | { | | 2278 | { |
2254 | struct tree_entry *te; | | 2279 | struct tree_entry *te; |
2255 | int new_fd, r = 0, prev_dir_fd; | | 2280 | int new_fd, r = 0, prev_dir_fd; |
2256 | | | 2281 | |
2257 | te = t->stack; | | 2282 | te = t->stack; |
2258 | prev_dir_fd = t->working_dir_fd; | | 2283 | prev_dir_fd = t->working_dir_fd; |
2259 | if (te->flags & isDirLink) | | 2284 | if (te->flags & isDirLink) |
2260 | new_fd = te->symlink_parent_fd; | | 2285 | new_fd = te->symlink_parent_fd; |
2261 | else { | | 2286 | else { |
2262 | new_fd = open_on_current_dir(t, "..", O_RDONLY | O_CLOEXEC); | | 2287 | new_fd = open_on_current_dir(t, "..", O_RDONLY | O_CLOEXEC); |
2263 | __archive_ensure_cloexec_flag(new_fd); | | 2288 | __archive_ensure_cloexec_flag(new_fd); |
2264 | } | | 2289 | } |
2265 | if (new_fd < 0) { | | 2290 | if (new_fd < 0) { |
2266 | t->tree_errno = errno; | | 2291 | t->tree_errno = errno; |
2267 | r = TREE_ERROR_FATAL; | | 2292 | r = TREE_ERROR_FATAL; |
2268 | } else { | | 2293 | } else { |
2269 | /* Renew the current working directory. */ | | 2294 | /* Renew the current working directory. */ |
2270 | t->working_dir_fd = new_fd; | | 2295 | t->working_dir_fd = new_fd; |
2271 | t->flags &= ~onWorkingDir; | | 2296 | t->flags &= ~onWorkingDir; |
2272 | /* Current directory has been changed, we should | | 2297 | /* Current directory has been changed, we should |
2273 | * close an fd of previous working directory. */ | | 2298 | * close an fd of previous working directory. */ |
2274 | close_and_restore_time(prev_dir_fd, t, &te->restore_time); | | 2299 | close_and_restore_time(prev_dir_fd, t, &te->restore_time); |
2275 | if (te->flags & isDirLink) { | | 2300 | if (te->flags & isDirLink) { |
2276 | t->openCount--; | | 2301 | t->openCount--; |
2277 | te->symlink_parent_fd = -1; | | 2302 | te->symlink_parent_fd = -1; |
2278 | } | | 2303 | } |
2279 | t->depth--; | | 2304 | t->depth--; |
2280 | } | | 2305 | } |
2281 | return (r); | | 2306 | return (r); |
2282 | } | | 2307 | } |
2283 | | | 2308 | |
2284 | /* | | 2309 | /* |
2285 | * Return to the initial directory where tree_open() was performed. | | 2310 | * Return to the initial directory where tree_open() was performed. |
2286 | */ | | 2311 | */ |
2287 | static int | | 2312 | static int |
2288 | tree_enter_initial_dir(struct tree *t) | | 2313 | tree_enter_initial_dir(struct tree *t) |
2289 | { | | 2314 | { |
2290 | int r = 0; | | 2315 | int r = 0; |
2291 | | | 2316 | |
2292 | if ((t->flags & onInitialDir) == 0) { | | 2317 | if ((t->flags & onInitialDir) == 0) { |
2293 | r = fchdir(t->initial_dir_fd); | | 2318 | r = fchdir(t->initial_dir_fd); |
2294 | if (r == 0) { | | 2319 | if (r == 0) { |
2295 | t->flags &= ~onWorkingDir; | | 2320 | t->flags &= ~onWorkingDir; |
2296 | t->flags |= onInitialDir; | | 2321 | t->flags |= onInitialDir; |
2297 | } | | 2322 | } |
2298 | } | | 2323 | } |
2299 | return (r); | | 2324 | return (r); |
2300 | } | | 2325 | } |
2301 | | | 2326 | |
2302 | /* | | 2327 | /* |
2303 | * Restore working directory of directory traversals. | | 2328 | * Restore working directory of directory traversals. |
2304 | */ | | 2329 | */ |
2305 | static int | | 2330 | static int |
2306 | tree_enter_working_dir(struct tree *t) | | 2331 | tree_enter_working_dir(struct tree *t) |
2307 | { | | 2332 | { |
2308 | int r = 0; | | 2333 | int r = 0; |
2309 | | | 2334 | |
2310 | /* | | 2335 | /* |
2311 | * Change the current directory if really needed. | | 2336 | * Change the current directory if really needed. |
2312 | * Sometimes this is unneeded when we did not do | | 2337 | * Sometimes this is unneeded when we did not do |
2313 | * descent. | | 2338 | * descent. |
2314 | */ | | 2339 | */ |
2315 | if (t->depth > 0 && (t->flags & onWorkingDir) == 0) { | | 2340 | if (t->depth > 0 && (t->flags & onWorkingDir) == 0) { |
2316 | r = fchdir(t->working_dir_fd); | | 2341 | r = fchdir(t->working_dir_fd); |
2317 | if (r == 0) { | | 2342 | if (r == 0) { |
2318 | t->flags &= ~onInitialDir; | | 2343 | t->flags &= ~onInitialDir; |
2319 | t->flags |= onWorkingDir; | | 2344 | t->flags |= onWorkingDir; |
2320 | } | | 2345 | } |
2321 | } | | 2346 | } |
2322 | return (r); | | 2347 | return (r); |
2323 | } | | 2348 | } |
2324 | | | 2349 | |
2325 | static int | | 2350 | static int |
2326 | tree_current_dir_fd(struct tree *t) | | 2351 | tree_current_dir_fd(struct tree *t) |
2327 | { | | 2352 | { |
2328 | return (t->working_dir_fd); | | 2353 | return (t->working_dir_fd); |
2329 | } | | 2354 | } |
2330 | | | 2355 | |
2331 | /* | | 2356 | /* |
2332 | * Pop the working stack. | | 2357 | * Pop the working stack. |
2333 | */ | | 2358 | */ |
2334 | static void | | 2359 | static void |
2335 | tree_pop(struct tree *t) | | 2360 | tree_pop(struct tree *t) |
2336 | { | | 2361 | { |
2337 | struct tree_entry *te; | | 2362 | struct tree_entry *te; |
2338 | | | 2363 | |
2339 | t->path.s[t->dirname_length] = '\0'; | | 2364 | t->path.s[t->dirname_length] = '\0'; |
2340 | t->path.length = t->dirname_length; | | 2365 | t->path.length = t->dirname_length; |
2341 | if (t->stack == t->current && t->current != NULL) | | 2366 | if (t->stack == t->current && t->current != NULL) |
2342 | t->current = t->current->parent; | | 2367 | t->current = t->current->parent; |
2343 | te = t->stack; | | 2368 | te = t->stack; |
2344 | t->stack = te->next; | | 2369 | t->stack = te->next; |
2345 | t->dirname_length = te->dirname_length; | | 2370 | t->dirname_length = te->dirname_length; |
2346 | t->basename = t->path.s + t->dirname_length; | | 2371 | t->basename = t->path.s + t->dirname_length; |
2347 | while (t->basename[0] == '/') | | 2372 | while (t->basename[0] == '/') |
2348 | t->basename++; | | 2373 | t->basename++; |
2349 | archive_string_free(&te->name); | | 2374 | archive_string_free(&te->name); |
2350 | free(te); | | 2375 | free(te); |
2351 | } | | 2376 | } |
2352 | | | 2377 | |
2353 | /* | | 2378 | /* |
2354 | * Get the next item in the tree traversal. | | 2379 | * Get the next item in the tree traversal. |
2355 | */ | | 2380 | */ |
2356 | static int | | 2381 | static int |
2357 | tree_next(struct tree *t) | | 2382 | tree_next(struct tree *t) |
2358 | { | | 2383 | { |
2359 | int r; | | 2384 | int r; |
2360 | | | 2385 | |
2361 | while (t->stack != NULL) { | | 2386 | while (t->stack != NULL) { |
2362 | /* If there's an open dir, get the next entry from there. */ | | 2387 | /* If there's an open dir, get the next entry from there. */ |
2363 | if (t->d != INVALID_DIR_HANDLE) { | | 2388 | if (t->d != INVALID_DIR_HANDLE) { |
2364 | r = tree_dir_next_posix(t); | | 2389 | r = tree_dir_next_posix(t); |
2365 | if (r == 0) | | 2390 | if (r == 0) |
2366 | continue; | | 2391 | continue; |
2367 | return (r); | | 2392 | return (r); |
2368 | } | | 2393 | } |
2369 | | | 2394 | |
2370 | if (t->stack->flags & needsFirstVisit) { | | 2395 | if (t->stack->flags & needsFirstVisit) { |
2371 | /* Top stack item needs a regular visit. */ | | 2396 | /* Top stack item needs a regular visit. */ |
2372 | t->current = t->stack; | | 2397 | t->current = t->stack; |
2373 | tree_append(t, t->stack->name.s, | | 2398 | tree_append(t, t->stack->name.s, |
2374 | archive_strlen(&(t->stack->name))); | | 2399 | archive_strlen(&(t->stack->name))); |
2375 | /* t->dirname_length = t->path_length; */ | | 2400 | /* t->dirname_length = t->path_length; */ |
2376 | /* tree_pop(t); */ | | 2401 | /* tree_pop(t); */ |
2377 | t->stack->flags &= ~needsFirstVisit; | | 2402 | t->stack->flags &= ~needsFirstVisit; |
2378 | return (t->visit_type = TREE_REGULAR); | | 2403 | return (t->visit_type = TREE_REGULAR); |
2379 | } else if (t->stack->flags & needsDescent) { | | 2404 | } else if (t->stack->flags & needsDescent) { |
2380 | /* Top stack item is dir to descend into. */ | | 2405 | /* Top stack item is dir to descend into. */ |
2381 | t->current = t->stack; | | 2406 | t->current = t->stack; |
2382 | tree_append(t, t->stack->name.s, | | 2407 | tree_append(t, t->stack->name.s, |
2383 | archive_strlen(&(t->stack->name))); | | 2408 | archive_strlen(&(t->stack->name))); |
2384 | t->stack->flags &= ~needsDescent; | | 2409 | t->stack->flags &= ~needsDescent; |
2385 | r = tree_descent(t); | | 2410 | r = tree_descent(t); |
2386 | if (r != 0) { | | 2411 | if (r != 0) { |
2387 | tree_pop(t); | | 2412 | tree_pop(t); |
2388 | t->visit_type = r; | | 2413 | t->visit_type = r; |
2389 | } else | | 2414 | } else |
2390 | t->visit_type = TREE_POSTDESCENT; | | 2415 | t->visit_type = TREE_POSTDESCENT; |
2391 | return (t->visit_type); | | 2416 | return (t->visit_type); |
2392 | } else if (t->stack->flags & needsOpen) { | | 2417 | } else if (t->stack->flags & needsOpen) { |
2393 | t->stack->flags &= ~needsOpen; | | 2418 | t->stack->flags &= ~needsOpen; |
2394 | r = tree_dir_next_posix(t); | | 2419 | r = tree_dir_next_posix(t); |
2395 | if (r == 0) | | 2420 | if (r == 0) |
2396 | continue; | | 2421 | continue; |
2397 | return (r); | | 2422 | return (r); |
2398 | } else if (t->stack->flags & needsAscent) { | | 2423 | } else if (t->stack->flags & needsAscent) { |
2399 | /* Top stack item is dir and we're done with it. */ | | 2424 | /* Top stack item is dir and we're done with it. */ |
2400 | r = tree_ascend(t); | | 2425 | r = tree_ascend(t); |
2401 | tree_pop(t); | | 2426 | tree_pop(t); |
2402 | t->visit_type = r != 0 ? r : TREE_POSTASCENT; | | 2427 | t->visit_type = r != 0 ? r : TREE_POSTASCENT; |
2403 | return (t->visit_type); | | 2428 | return (t->visit_type); |
2404 | } else { | | 2429 | } else { |
2405 | /* Top item on stack is dead. */ | | 2430 | /* Top item on stack is dead. */ |
2406 | tree_pop(t); | | 2431 | tree_pop(t); |
2407 | t->flags &= ~hasLstat; | | 2432 | t->flags &= ~hasLstat; |
2408 | t->flags &= ~hasStat; | | 2433 | t->flags &= ~hasStat; |
2409 | } | | 2434 | } |
2410 | } | | 2435 | } |
2411 | return (t->visit_type = 0); | | 2436 | return (t->visit_type = 0); |
2412 | } | | 2437 | } |
2413 | | | 2438 | |
2414 | static int | | 2439 | static int |
2415 | tree_dir_next_posix(struct tree *t) | | 2440 | tree_dir_next_posix(struct tree *t) |
2416 | { | | 2441 | { |
2417 | int r; | | 2442 | int r; |
2418 | const char *name; | | 2443 | const char *name; |
2419 | size_t namelen; | | 2444 | size_t namelen; |
2420 | | | 2445 | |
2421 | if (t->d == NULL) { | | 2446 | if (t->d == NULL) { |
2422 | #if defined(USE_READDIR_R) | | 2447 | #if defined(USE_READDIR_R) |
2423 | size_t dirent_size; | | 2448 | size_t dirent_size; |
2424 | #endif | | 2449 | #endif |
2425 | | | 2450 | |
2426 | #if defined(HAVE_FDOPENDIR) | | 2451 | #if defined(HAVE_FDOPENDIR) |
2427 | t->d = fdopendir(tree_dup(t->working_dir_fd)); | | 2452 | t->d = fdopendir(tree_dup(t->working_dir_fd)); |
2428 | #else /* HAVE_FDOPENDIR */ | | 2453 | #else /* HAVE_FDOPENDIR */ |
2429 | if (tree_enter_working_dir(t) == 0) { | | 2454 | if (tree_enter_working_dir(t) == 0) { |
2430 | t->d = opendir("."); | | 2455 | t->d = opendir("."); |
2431 | #if HAVE_DIRFD || defined(dirfd) | | 2456 | #if HAVE_DIRFD || defined(dirfd) |
2432 | __archive_ensure_cloexec_flag(dirfd(t->d)); | | 2457 | __archive_ensure_cloexec_flag(dirfd(t->d)); |
2433 | #endif | | 2458 | #endif |
2434 | } | | 2459 | } |
2435 | #endif /* HAVE_FDOPENDIR */ | | 2460 | #endif /* HAVE_FDOPENDIR */ |
2436 | if (t->d == NULL) { | | 2461 | if (t->d == NULL) { |
2437 | r = tree_ascend(t); /* Undo "chdir" */ | | 2462 | r = tree_ascend(t); /* Undo "chdir" */ |
2438 | tree_pop(t); | | 2463 | tree_pop(t); |
2439 | t->tree_errno = errno; | | 2464 | t->tree_errno = errno; |
2440 | t->visit_type = r != 0 ? r : TREE_ERROR_DIR; | | 2465 | t->visit_type = r != 0 ? r : TREE_ERROR_DIR; |
2441 | return (t->visit_type); | | 2466 | return (t->visit_type); |
2442 | } | | 2467 | } |
2443 | #if defined(USE_READDIR_R) | | 2468 | #if defined(USE_READDIR_R) |
2444 | dirent_size = offsetof(struct dirent, d_name) + | | 2469 | dirent_size = offsetof(struct dirent, d_name) + |
2445 | t->filesystem_table[t->current->filesystem_id].name_max + 1; | | 2470 | t->filesystem_table[t->current->filesystem_id].name_max + 1; |
2446 | if (t->dirent == NULL || t->dirent_allocated < dirent_size) { | | 2471 | if (t->dirent == NULL || t->dirent_allocated < dirent_size) { |
2447 | free(t->dirent); | | 2472 | free(t->dirent); |
2448 | t->dirent = malloc(dirent_size); | | 2473 | t->dirent = malloc(dirent_size); |
2449 | if (t->dirent == NULL) { | | 2474 | if (t->dirent == NULL) { |
2450 | closedir(t->d); | | 2475 | closedir(t->d); |
2451 | t->d = INVALID_DIR_HANDLE; | | 2476 | t->d = INVALID_DIR_HANDLE; |
2452 | (void)tree_ascend(t); | | 2477 | (void)tree_ascend(t); |
2453 | tree_pop(t); | | 2478 | tree_pop(t); |
2454 | t->tree_errno = ENOMEM; | | 2479 | t->tree_errno = ENOMEM; |
2455 | t->visit_type = TREE_ERROR_DIR; | | 2480 | t->visit_type = TREE_ERROR_DIR; |
2456 | return (t->visit_type); | | 2481 | return (t->visit_type); |
2457 | } | | 2482 | } |
2458 | t->dirent_allocated = dirent_size; | | 2483 | t->dirent_allocated = dirent_size; |
2459 | } | | 2484 | } |
2460 | #endif /* USE_READDIR_R */ | | 2485 | #endif /* USE_READDIR_R */ |
2461 | } | | 2486 | } |
2462 | for (;;) { | | 2487 | for (;;) { |
2463 | errno = 0; | | 2488 | errno = 0; |
2464 | #if defined(USE_READDIR_R) | | 2489 | #if defined(USE_READDIR_R) |
2465 | r = readdir_r(t->d, t->dirent, &t->de); | | 2490 | r = readdir_r(t->d, t->dirent, &t->de); |
2466 | #ifdef _AIX | | 2491 | #ifdef _AIX |
2467 | /* Note: According to the man page, return value 9 indicates | | 2492 | /* Note: According to the man page, return value 9 indicates |
2468 | * that the readdir_r was not successful and the error code | | 2493 | * that the readdir_r was not successful and the error code |
2469 | * is set to the global errno variable. And then if the end | | 2494 | * is set to the global errno variable. And then if the end |
2470 | * of directory entries was reached, the return value is 9 | | 2495 | * of directory entries was reached, the return value is 9 |
2471 | * and the third parameter is set to NULL and errno is | | 2496 | * and the third parameter is set to NULL and errno is |
2472 | * unchanged. */ | | 2497 | * unchanged. */ |
2473 | if (r == 9) | | 2498 | if (r == 9) |
2474 | r = errno; | | 2499 | r = errno; |
2475 | #endif /* _AIX */ | | 2500 | #endif /* _AIX */ |
2476 | if (r != 0 || t->de == NULL) { | | 2501 | if (r != 0 || t->de == NULL) { |
2477 | #else | | 2502 | #else |
2478 | t->de = readdir(t->d); | | 2503 | t->de = readdir(t->d); |
2479 | if (t->de == NULL) { | | 2504 | if (t->de == NULL) { |
2480 | r = errno; | | 2505 | r = errno; |
2481 | #endif | | 2506 | #endif |
2482 | closedir(t->d); | | 2507 | closedir(t->d); |
2483 | t->d = INVALID_DIR_HANDLE; | | 2508 | t->d = INVALID_DIR_HANDLE; |
2484 | if (r != 0) { | | 2509 | if (r != 0) { |
2485 | t->tree_errno = r; | | 2510 | t->tree_errno = r; |
2486 | t->visit_type = TREE_ERROR_DIR; | | 2511 | t->visit_type = TREE_ERROR_DIR; |
2487 | return (t->visit_type); | | 2512 | return (t->visit_type); |
2488 | } else | | 2513 | } else |
2489 | return (0); | | 2514 | return (0); |
2490 | } | | 2515 | } |
2491 | name = t->de->d_name; | | 2516 | name = t->de->d_name; |
2492 | namelen = D_NAMELEN(t->de); | | 2517 | namelen = D_NAMELEN(t->de); |
2493 | t->flags &= ~hasLstat; | | 2518 | t->flags &= ~hasLstat; |
2494 | t->flags &= ~hasStat; | | 2519 | t->flags &= ~hasStat; |
2495 | if (name[0] == '.' && name[1] == '\0') | | 2520 | if (name[0] == '.' && name[1] == '\0') |
2496 | continue; | | 2521 | continue; |
2497 | if (name[0] == '.' && name[1] == '.' && name[2] == '\0') | | 2522 | if (name[0] == '.' && name[1] == '.' && name[2] == '\0') |
2498 | continue; | | 2523 | continue; |
2499 | tree_append(t, name, namelen); | | 2524 | tree_append(t, name, namelen); |
2500 | return (t->visit_type = TREE_REGULAR); | | 2525 | return (t->visit_type = TREE_REGULAR); |
2501 | } | | 2526 | } |
2502 | } | | 2527 | } |
2503 | | | 2528 | |
2504 | | | 2529 | |
2505 | /* | | 2530 | /* |
2506 | * Get the stat() data for the entry just returned from tree_next(). | | 2531 | * Get the stat() data for the entry just returned from tree_next(). |
2507 | */ | | 2532 | */ |
2508 | static const struct stat * | | 2533 | static const struct stat * |
2509 | tree_current_stat(struct tree *t) | | 2534 | tree_current_stat(struct tree *t) |
2510 | { | | 2535 | { |
2511 | if (!(t->flags & hasStat)) { | | 2536 | if (!(t->flags & hasStat)) { |
2512 | #ifdef HAVE_FSTATAT | | 2537 | #ifdef HAVE_FSTATAT |
2513 | if (fstatat(tree_current_dir_fd(t), | | 2538 | if (fstatat(tree_current_dir_fd(t), |
2514 | tree_current_access_path(t), &t->st, 0) != 0) | | 2539 | tree_current_access_path(t), &t->st, 0) != 0) |
2515 | #else | | 2540 | #else |
2516 | if (tree_enter_working_dir(t) != 0) | | 2541 | if (tree_enter_working_dir(t) != 0) |
2517 | return NULL; | | 2542 | return NULL; |
2518 | if (la_stat(tree_current_access_path(t), &t->st) != 0) | | 2543 | if (la_stat(tree_current_access_path(t), &t->st) != 0) |
2519 | #endif | | 2544 | #endif |
2520 | return NULL; | | 2545 | return NULL; |
2521 | t->flags |= hasStat; | | 2546 | t->flags |= hasStat; |
2522 | } | | 2547 | } |
2523 | return (&t->st); | | 2548 | return (&t->st); |
2524 | } | | 2549 | } |
2525 | | | 2550 | |
2526 | /* | | 2551 | /* |
2527 | * Get the lstat() data for the entry just returned from tree_next(). | | 2552 | * Get the lstat() data for the entry just returned from tree_next(). |
2528 | */ | | 2553 | */ |
2529 | static const struct stat * | | 2554 | static const struct stat * |
2530 | tree_current_lstat(struct tree *t) | | 2555 | tree_current_lstat(struct tree *t) |
2531 | { | | 2556 | { |
2532 | if (!(t->flags & hasLstat)) { | | 2557 | if (!(t->flags & hasLstat)) { |
2533 | #ifdef HAVE_FSTATAT | | 2558 | #ifdef HAVE_FSTATAT |
2534 | if (fstatat(tree_current_dir_fd(t), | | 2559 | if (fstatat(tree_current_dir_fd(t), |
2535 | tree_current_access_path(t), &t->lst, | | 2560 | tree_current_access_path(t), &t->lst, |
2536 | AT_SYMLINK_NOFOLLOW) != 0) | | 2561 | AT_SYMLINK_NOFOLLOW) != 0) |
2537 | #else | | 2562 | #else |
2538 | if (tree_enter_working_dir(t) != 0) | | 2563 | if (tree_enter_working_dir(t) != 0) |
2539 | return NULL; | | 2564 | return NULL; |
2540 | if (lstat(tree_current_access_path(t), &t->lst) != 0) | | 2565 | if (lstat(tree_current_access_path(t), &t->lst) != 0) |
2541 | #endif | | 2566 | #endif |
2542 | return NULL; | | 2567 | return NULL; |
2543 | t->flags |= hasLstat; | | 2568 | t->flags |= hasLstat; |
2544 | } | | 2569 | } |
2545 | return (&t->lst); | | 2570 | return (&t->lst); |
2546 | } | | 2571 | } |
2547 | | | 2572 | |
2548 | /* | | 2573 | /* |
2549 | * Test whether current entry is a dir or link to a dir. | | 2574 | * Test whether current entry is a dir or link to a dir. |
2550 | */ | | 2575 | */ |
2551 | static int | | 2576 | static int |
2552 | tree_current_is_dir(struct tree *t) | | 2577 | tree_current_is_dir(struct tree *t) |
2553 | { | | 2578 | { |
2554 | const struct stat *st; | | 2579 | const struct stat *st; |
2555 | /* | | 2580 | /* |
2556 | * If we already have lstat() info, then try some | | 2581 | * If we already have lstat() info, then try some |
2557 | * cheap tests to determine if this is a dir. | | 2582 | * cheap tests to determine if this is a dir. |
2558 | */ | | 2583 | */ |
2559 | if (t->flags & hasLstat) { | | 2584 | if (t->flags & hasLstat) { |
2560 | /* If lstat() says it's a dir, it must be a dir. */ | | 2585 | /* If lstat() says it's a dir, it must be a dir. */ |
2561 | st = tree_current_lstat(t); | | 2586 | st = tree_current_lstat(t); |
2562 | if (st == NULL) | | 2587 | if (st == NULL) |
2563 | return 0; | | 2588 | return 0; |
2564 | if (S_ISDIR(st->st_mode)) | | 2589 | if (S_ISDIR(st->st_mode)) |
2565 | return 1; | | 2590 | return 1; |
2566 | /* Not a dir; might be a link to a dir. */ | | 2591 | /* Not a dir; might be a link to a dir. */ |
2567 | /* If it's not a link, then it's not a link to a dir. */ | | 2592 | /* If it's not a link, then it's not a link to a dir. */ |
2568 | if (!S_ISLNK(st->st_mode)) | | 2593 | if (!S_ISLNK(st->st_mode)) |
2569 | return 0; | | 2594 | return 0; |
2570 | /* | | 2595 | /* |
2571 | * It's a link, but we don't know what it's a link to, | | 2596 | * It's a link, but we don't know what it's a link to, |
2572 | * so we'll have to use stat(). | | 2597 | * so we'll have to use stat(). |
2573 | */ | | 2598 | */ |
2574 | } | | 2599 | } |
2575 | | | 2600 | |
2576 | st = tree_current_stat(t); | | 2601 | st = tree_current_stat(t); |
2577 | /* If we can't stat it, it's not a dir. */ | | 2602 | /* If we can't stat it, it's not a dir. */ |
2578 | if (st == NULL) | | 2603 | if (st == NULL) |
2579 | return 0; | | 2604 | return 0; |
2580 | /* Use the definitive test. Hopefully this is cached. */ | | 2605 | /* Use the definitive test. Hopefully this is cached. */ |
2581 | return (S_ISDIR(st->st_mode)); | | 2606 | return (S_ISDIR(st->st_mode)); |
2582 | } | | 2607 | } |
2583 | | | 2608 | |
2584 | /* | | 2609 | /* |
2585 | * Test whether current entry is a physical directory. Usually, we | | 2610 | * Test whether current entry is a physical directory. Usually, we |
2586 | * already have at least one of stat() or lstat() in memory, so we | | 2611 | * already have at least one of stat() or lstat() in memory, so we |
2587 | * use tricks to try to avoid an extra trip to the disk. | | 2612 | * use tricks to try to avoid an extra trip to the disk. |
2588 | */ | | 2613 | */ |
2589 | static int | | 2614 | static int |
2590 | tree_current_is_physical_dir(struct tree *t) | | 2615 | tree_current_is_physical_dir(struct tree *t) |
2591 | { | | 2616 | { |
2592 | const struct stat *st; | | 2617 | const struct stat *st; |
2593 | | | 2618 | |
2594 | /* | | 2619 | /* |
2595 | * If stat() says it isn't a dir, then it's not a dir. | | 2620 | * If stat() says it isn't a dir, then it's not a dir. |
2596 | * If stat() data is cached, this check is free, so do it first. | | 2621 | * If stat() data is cached, this check is free, so do it first. |
2597 | */ | | 2622 | */ |
2598 | if (t->flags & hasStat) { | | 2623 | if (t->flags & hasStat) { |
2599 | st = tree_current_stat(t); | | 2624 | st = tree_current_stat(t); |
2600 | if (st == NULL) | | 2625 | if (st == NULL) |
2601 | return (0); | | 2626 | return (0); |
2602 | if (!S_ISDIR(st->st_mode)) | | 2627 | if (!S_ISDIR(st->st_mode)) |
2603 | return (0); | | 2628 | return (0); |
2604 | } | | 2629 | } |
2605 | | | 2630 | |
2606 | /* | | 2631 | /* |
2607 | * Either stat() said it was a dir (in which case, we have | | 2632 | * Either stat() said it was a dir (in which case, we have |
2608 | * to determine whether it's really a link to a dir) or | | 2633 | * to determine whether it's really a link to a dir) or |
2609 | * stat() info wasn't available. So we use lstat(), which | | 2634 | * stat() info wasn't available. So we use lstat(), which |
2610 | * hopefully is already cached. | | 2635 | * hopefully is already cached. |
2611 | */ | | 2636 | */ |
2612 | | | 2637 | |
2613 | st = tree_current_lstat(t); | | 2638 | st = tree_current_lstat(t); |
2614 | /* If we can't stat it, it's not a dir. */ | | 2639 | /* If we can't stat it, it's not a dir. */ |
2615 | if (st == NULL) | | 2640 | if (st == NULL) |
2616 | return 0; | | 2641 | return 0; |
2617 | /* Use the definitive test. Hopefully this is cached. */ | | 2642 | /* Use the definitive test. Hopefully this is cached. */ |
2618 | return (S_ISDIR(st->st_mode)); | | 2643 | return (S_ISDIR(st->st_mode)); |
2619 | } | | 2644 | } |
2620 | | | 2645 | |
2621 | /* | | 2646 | /* |
2622 | * Test whether the same file has been in the tree as its parent. | | 2647 | * Test whether the same file has been in the tree as its parent. |
2623 | */ | | 2648 | */ |
2624 | static int | | 2649 | static int |
2625 | tree_target_is_same_as_parent(struct tree *t, const struct stat *st) | | 2650 | tree_target_is_same_as_parent(struct tree *t, const struct stat *st) |
2626 | { | | 2651 | { |
2627 | struct tree_entry *te; | | 2652 | struct tree_entry *te; |
2628 | | | 2653 | |
2629 | for (te = t->current->parent; te != NULL; te = te->parent) { | | 2654 | for (te = t->current->parent; te != NULL; te = te->parent) { |
2630 | if (te->dev == (int64_t)st->st_dev && | | 2655 | if (te->dev == (int64_t)st->st_dev && |
2631 | te->ino == (int64_t)st->st_ino) | | 2656 | te->ino == (int64_t)st->st_ino) |
2632 | return (1); | | 2657 | return (1); |
2633 | } | | 2658 | } |
2634 | return (0); | | 2659 | return (0); |
2635 | } | | 2660 | } |
2636 | | | 2661 | |
2637 | /* | | 2662 | /* |
2638 | * Test whether the current file is symbolic link target and | | 2663 | * Test whether the current file is symbolic link target and |
2639 | * on the other filesystem. | | 2664 | * on the other filesystem. |
2640 | */ | | 2665 | */ |
2641 | static int | | 2666 | static int |
2642 | tree_current_is_symblic_link_target(struct tree *t) | | 2667 | tree_current_is_symblic_link_target(struct tree *t) |
2643 | { | | 2668 | { |
2644 | static const struct stat *lst, *st; | | 2669 | static const struct stat *lst, *st; |
2645 | | | 2670 | |
2646 | lst = tree_current_lstat(t); | | 2671 | lst = tree_current_lstat(t); |
2647 | st = tree_current_stat(t); | | 2672 | st = tree_current_stat(t); |
2648 | return (st != NULL && lst != NULL && | | 2673 | return (st != NULL && lst != NULL && |
2649 | (int64_t)st->st_dev == t->current_filesystem->dev && | | 2674 | (int64_t)st->st_dev == t->current_filesystem->dev && |
2650 | st->st_dev != lst->st_dev); | | 2675 | st->st_dev != lst->st_dev); |
2651 | } | | 2676 | } |
2652 | | | 2677 | |
2653 | /* | | 2678 | /* |
2654 | * Return the access path for the entry just returned from tree_next(). | | 2679 | * Return the access path for the entry just returned from tree_next(). |
2655 | */ | | 2680 | */ |
2656 | static const char * | | 2681 | static const char * |
2657 | tree_current_access_path(struct tree *t) | | 2682 | tree_current_access_path(struct tree *t) |
2658 | { | | 2683 | { |
2659 | return (t->basename); | | 2684 | return (t->basename); |
2660 | } | | 2685 | } |
2661 | | | 2686 | |
2662 | /* | | 2687 | /* |
2663 | * Return the full path for the entry just returned from tree_next(). | | 2688 | * Return the full path for the entry just returned from tree_next(). |
2664 | */ | | 2689 | */ |
2665 | static const char * | | 2690 | static const char * |
2666 | tree_current_path(struct tree *t) | | 2691 | tree_current_path(struct tree *t) |
2667 | { | | 2692 | { |
2668 | return (t->path.s); | | 2693 | return (t->path.s); |
2669 | } | | 2694 | } |
2670 | | | 2695 | |
2671 | /* | | 2696 | /* |
2672 | * Terminate the traversal. | | 2697 | * Terminate the traversal. |
2673 | */ | | 2698 | */ |
2674 | static void | | 2699 | static void |
2675 | tree_close(struct tree *t) | | 2700 | tree_close(struct tree *t) |
2676 | { | | 2701 | { |
2677 | | | 2702 | |
2678 | if (t == NULL) | | 2703 | if (t == NULL) |
2679 | return; | | 2704 | return; |
2680 | if (t->entry_fd >= 0) { | | 2705 | if (t->entry_fd >= 0) { |
2681 | close_and_restore_time(t->entry_fd, t, &t->restore_time); | | 2706 | close_and_restore_time(t->entry_fd, t, &t->restore_time); |
2682 | t->entry_fd = -1; | | 2707 | t->entry_fd = -1; |
2683 | } | | 2708 | } |
2684 | /* Close the handle of readdir(). */ | | 2709 | /* Close the handle of readdir(). */ |
2685 | if (t->d != INVALID_DIR_HANDLE) { | | 2710 | if (t->d != INVALID_DIR_HANDLE) { |
2686 | closedir(t->d); | | 2711 | closedir(t->d); |
2687 | t->d = INVALID_DIR_HANDLE; | | 2712 | t->d = INVALID_DIR_HANDLE; |
2688 | } | | 2713 | } |
2689 | /* Release anything remaining in the stack. */ | | 2714 | /* Release anything remaining in the stack. */ |
2690 | while (t->stack != NULL) { | | 2715 | while (t->stack != NULL) { |
2691 | if (t->stack->flags & isDirLink) | | 2716 | if (t->stack->flags & isDirLink) |
2692 | close(t->stack->symlink_parent_fd); | | 2717 | close(t->stack->symlink_parent_fd); |
2693 | tree_pop(t); | | 2718 | tree_pop(t); |
2694 | } | | 2719 | } |
2695 | if (t->working_dir_fd >= 0) { | | 2720 | if (t->working_dir_fd >= 0) { |
2696 | close(t->working_dir_fd); | | 2721 | close(t->working_dir_fd); |
2697 | t->working_dir_fd = -1; | | 2722 | t->working_dir_fd = -1; |
2698 | } | | 2723 | } |
2699 | if (t->initial_dir_fd >= 0) { | | 2724 | if (t->initial_dir_fd >= 0) { |
2700 | close(t->initial_dir_fd); | | 2725 | close(t->initial_dir_fd); |
2701 | t->initial_dir_fd = -1; | | 2726 | t->initial_dir_fd = -1; |
2702 | } | | 2727 | } |
2703 | } | | 2728 | } |
2704 | | | 2729 | |
2705 | /* | | 2730 | /* |
2706 | * Release any resources. | | 2731 | * Release any resources. |
2707 | */ | | 2732 | */ |
2708 | static void | | 2733 | static void |
2709 | tree_free(struct tree *t) | | 2734 | tree_free(struct tree *t) |
2710 | { | | 2735 | { |
2711 | int i; | | 2736 | int i; |
2712 | | | 2737 | |
2713 | if (t == NULL) | | 2738 | if (t == NULL) |
2714 | return; | | 2739 | return; |
2715 | archive_string_free(&t->path); | | 2740 | archive_string_free(&t->path); |
2716 | #if defined(USE_READDIR_R) | | 2741 | #if defined(USE_READDIR_R) |
2717 | free(t->dirent); | | 2742 | free(t->dirent); |
2718 | #endif | | 2743 | #endif |
2719 | free(t->sparse_list); | | 2744 | free(t->sparse_list); |
2720 | for (i = 0; i < t->max_filesystem_id; i++) | | 2745 | for (i = 0; i < t->max_filesystem_id; i++) |
2721 | free(t->filesystem_table[i].allocation_ptr); | | 2746 | free(t->filesystem_table[i].allocation_ptr); |
2722 | free(t->filesystem_table); | | 2747 | free(t->filesystem_table); |
2723 | free(t); | | 2748 | free(t); |
2724 | } | | 2749 | } |
2725 | | | 2750 | |
2726 | #endif | | 2751 | #endif |