diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-04-09 14:11:45 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-04-09 14:11:45 +0200 |
| commit | e69ad87802139b7b62fc06ff5d5d09cc4245d5fc (patch) | |
| tree | 5140bc5e536c722f9aa5a0896a7229cf9b2148b0 | |
| parent | 02365a6ef73defb8689d3ed5228125d72993dec9 (diff) | |
| download | busybox-w32-e69ad87802139b7b62fc06ff5d5d09cc4245d5fc.tar.gz busybox-w32-e69ad87802139b7b62fc06ff5d5d09cc4245d5fc.tar.bz2 busybox-w32-e69ad87802139b7b62fc06ff5d5d09cc4245d5fc.zip | |
tar: fix "hardlinks to symlinks chown" bug 1519.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | archival/libunarchive/data_extract_all.c | 102 | ||||
| -rw-r--r-- | archival/libunarchive/header_verbose_list.c | 1 | ||||
| -rwxr-xr-x | testsuite/tar.tests | 29 |
3 files changed, 82 insertions, 50 deletions
diff --git a/archival/libunarchive/data_extract_all.c b/archival/libunarchive/data_extract_all.c index de2367ac2..815261036 100644 --- a/archival/libunarchive/data_extract_all.c +++ b/archival/libunarchive/data_extract_all.c | |||
| @@ -96,58 +96,60 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
| 96 | file_header->name, | 96 | file_header->name, |
| 97 | file_header->link_target); | 97 | file_header->link_target); |
| 98 | } | 98 | } |
| 99 | } else { | 99 | /* Hardlinks have no separate mode/ownership, skip chown/chmod */ |
| 100 | /* Create the filesystem entry */ | 100 | goto ret; |
| 101 | switch (file_header->mode & S_IFMT) { | 101 | } |
| 102 | case S_IFREG: { | 102 | |
| 103 | /* Regular file */ | 103 | /* Create the filesystem entry */ |
| 104 | int flags = O_WRONLY | O_CREAT | O_EXCL; | 104 | switch (file_header->mode & S_IFMT) { |
| 105 | if (archive_handle->ah_flags & ARCHIVE_O_TRUNC) | 105 | case S_IFREG: { |
| 106 | flags = O_WRONLY | O_CREAT | O_TRUNC; | 106 | /* Regular file */ |
| 107 | dst_fd = xopen3(file_header->name, | 107 | int flags = O_WRONLY | O_CREAT | O_EXCL; |
| 108 | flags, | 108 | if (archive_handle->ah_flags & ARCHIVE_O_TRUNC) |
| 109 | file_header->mode | 109 | flags = O_WRONLY | O_CREAT | O_TRUNC; |
| 110 | ); | 110 | dst_fd = xopen3(file_header->name, |
| 111 | bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size); | 111 | flags, |
| 112 | close(dst_fd); | 112 | file_header->mode |
| 113 | break; | 113 | ); |
| 114 | bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size); | ||
| 115 | close(dst_fd); | ||
| 116 | break; | ||
| 117 | } | ||
| 118 | case S_IFDIR: | ||
| 119 | res = mkdir(file_header->name, file_header->mode); | ||
| 120 | if ((res == -1) | ||
| 121 | && (errno != EISDIR) /* btw, Linux doesn't return this */ | ||
| 122 | && (errno != EEXIST) | ||
| 123 | && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) | ||
| 124 | ) { | ||
| 125 | bb_perror_msg("can't make dir %s", file_header->name); | ||
| 114 | } | 126 | } |
| 115 | case S_IFDIR: | 127 | break; |
| 116 | res = mkdir(file_header->name, file_header->mode); | 128 | case S_IFLNK: |
| 117 | if ((res == -1) | 129 | /* Symlink */ |
| 118 | && (errno != EISDIR) /* btw, Linux doesn't return this */ | 130 | res = symlink(file_header->link_target, file_header->name); |
| 119 | && (errno != EEXIST) | 131 | if ((res == -1) |
| 120 | && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) | 132 | && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) |
| 121 | ) { | 133 | ) { |
| 122 | bb_perror_msg("can't make dir %s", file_header->name); | 134 | bb_perror_msg("can't create %slink " |
| 123 | } | 135 | "from %s to %s", "sym", |
| 124 | break; | 136 | file_header->name, |
| 125 | case S_IFLNK: | 137 | file_header->link_target); |
| 126 | /* Symlink */ | 138 | } |
| 127 | res = symlink(file_header->link_target, file_header->name); | 139 | break; |
| 128 | if ((res == -1) | 140 | case S_IFSOCK: |
| 129 | && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) | 141 | case S_IFBLK: |
| 130 | ) { | 142 | case S_IFCHR: |
| 131 | bb_perror_msg("can't create %slink " | 143 | case S_IFIFO: |
| 132 | "from %s to %s", "sym", | 144 | res = mknod(file_header->name, file_header->mode, file_header->device); |
| 133 | file_header->name, | 145 | if ((res == -1) |
| 134 | file_header->link_target); | 146 | && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) |
| 135 | } | 147 | ) { |
| 136 | break; | 148 | bb_perror_msg("can't create node %s", file_header->name); |
| 137 | case S_IFSOCK: | ||
| 138 | case S_IFBLK: | ||
| 139 | case S_IFCHR: | ||
| 140 | case S_IFIFO: | ||
| 141 | res = mknod(file_header->name, file_header->mode, file_header->device); | ||
| 142 | if ((res == -1) | ||
| 143 | && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) | ||
| 144 | ) { | ||
| 145 | bb_perror_msg("can't create node %s", file_header->name); | ||
| 146 | } | ||
| 147 | break; | ||
| 148 | default: | ||
| 149 | bb_error_msg_and_die("unrecognized file type"); | ||
| 150 | } | 149 | } |
| 150 | break; | ||
| 151 | default: | ||
| 152 | bb_error_msg_and_die("unrecognized file type"); | ||
| 151 | } | 153 | } |
| 152 | 154 | ||
| 153 | if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_OWNER)) { | 155 | if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_OWNER)) { |
diff --git a/archival/libunarchive/header_verbose_list.c b/archival/libunarchive/header_verbose_list.c index f6f04cfd5..3319e63a9 100644 --- a/archival/libunarchive/header_verbose_list.c +++ b/archival/libunarchive/header_verbose_list.c | |||
| @@ -61,6 +61,7 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header) | |||
| 61 | 61 | ||
| 62 | #endif /* FEATURE_TAR_UNAME_GNAME */ | 62 | #endif /* FEATURE_TAR_UNAME_GNAME */ |
| 63 | 63 | ||
| 64 | /* NB: GNU tar shows "->" for symlinks and "link to" for hardlinks */ | ||
| 64 | if (file_header->link_target) { | 65 | if (file_header->link_target) { |
| 65 | printf(" -> %s", file_header->link_target); | 66 | printf(" -> %s", file_header->link_target); |
| 66 | } | 67 | } |
diff --git a/testsuite/tar.tests b/testsuite/tar.tests index dd8f11062..a96382932 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests | |||
| @@ -69,6 +69,35 @@ dr-xr-x--- input_dir | |||
| 69 | " \ | 69 | " \ |
| 70 | "" "" | 70 | "" "" |
| 71 | 71 | ||
| 72 | testing "tar symlinks mode" '\ | ||
| 73 | rm -rf input_* test.tar 2>/dev/null | ||
| 74 | >input_file | ||
| 75 | chmod 741 input_file | ||
| 76 | ln -s input_file input_soft | ||
| 77 | mkdir input_dir | ||
| 78 | chmod 550 input_dir | ||
| 79 | ln input_file input_dir | ||
| 80 | ln input_soft input_dir | ||
| 81 | tar cf test.tar input_* | ||
| 82 | tar tvf test.tar | sed "s/.*[0-9] input/input/" | ||
| 83 | tar xf test.tar 2>&1 | ||
| 84 | echo Ok: $? | ||
| 85 | ls -l . input_dir/* | grep input_ | sed "s/\\(^[^ ]*\\) .* input/\\1 input/" | ||
| 86 | ' "\ | ||
| 87 | input_dir/ | ||
| 88 | input_dir/input_file | ||
| 89 | input_dir/input_soft -> input_file | ||
| 90 | input_file -> input_dir/input_file | ||
| 91 | input_soft -> input_dir/input_soft | ||
| 92 | Ok: 0 | ||
| 93 | -rwxr----x input_dir/input_file | ||
| 94 | lrwxrwxrwx input_file | ||
| 95 | dr-xr-x--- input_dir | ||
| 96 | -rwxr----x input_file | ||
| 97 | lrwxrwxrwx input_file | ||
| 98 | " \ | ||
| 99 | "" "" | ||
| 100 | |||
| 72 | optional FEATURE_TAR_LONG_OPTIONS | 101 | optional FEATURE_TAR_LONG_OPTIONS |
| 73 | testing "tar --overwrite" "\ | 102 | testing "tar --overwrite" "\ |
| 74 | rm -rf input_* test.tar 2>/dev/null | 103 | rm -rf input_* test.tar 2>/dev/null |
