aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-04-09 14:11:45 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-04-09 14:11:45 +0200
commite69ad87802139b7b62fc06ff5d5d09cc4245d5fc (patch)
tree5140bc5e536c722f9aa5a0896a7229cf9b2148b0
parent02365a6ef73defb8689d3ed5228125d72993dec9 (diff)
downloadbusybox-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.c102
-rw-r--r--archival/libunarchive/header_verbose_list.c1
-rwxr-xr-xtestsuite/tar.tests29
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
72testing "tar symlinks mode" '\
73rm -rf input_* test.tar 2>/dev/null
74>input_file
75chmod 741 input_file
76ln -s input_file input_soft
77mkdir input_dir
78chmod 550 input_dir
79ln input_file input_dir
80ln input_soft input_dir
81tar cf test.tar input_*
82tar tvf test.tar | sed "s/.*[0-9] input/input/"
83tar xf test.tar 2>&1
84echo Ok: $?
85ls -l . input_dir/* | grep input_ | sed "s/\\(^[^ ]*\\) .* input/\\1 input/"
86' "\
87input_dir/
88input_dir/input_file
89input_dir/input_soft -> input_file
90input_file -> input_dir/input_file
91input_soft -> input_dir/input_soft
92Ok: 0
93-rwxr----x input_dir/input_file
94lrwxrwxrwx input_file
95dr-xr-x--- input_dir
96-rwxr----x input_file
97lrwxrwxrwx input_file
98" \
99"" ""
100
72optional FEATURE_TAR_LONG_OPTIONS 101optional FEATURE_TAR_LONG_OPTIONS
73testing "tar --overwrite" "\ 102testing "tar --overwrite" "\
74rm -rf input_* test.tar 2>/dev/null 103rm -rf input_* test.tar 2>/dev/null