aboutsummaryrefslogtreecommitdiff
path: root/archival
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 /archival
parent02365a6ef73defb8689d3ed5228125d72993dec9 (diff)
downloadbusybox-e69ad87802139b7b62fc06ff5d5d09cc4245d5fc.tar.gz
tar: fix "hardlinks to symlinks chown" bug 1519.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'archival')
-rw-r--r--archival/libunarchive/data_extract_all.c102
-rw-r--r--archival/libunarchive/header_verbose_list.c1
2 files changed, 53 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)
file_header->name,
file_header->link_target);
}
- } else {
- /* Create the filesystem entry */
- switch (file_header->mode & S_IFMT) {
- case S_IFREG: {
- /* Regular file */
- int flags = O_WRONLY | O_CREAT | O_EXCL;
- if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
- flags = O_WRONLY | O_CREAT | O_TRUNC;
- dst_fd = xopen3(file_header->name,
- flags,
- file_header->mode
- );
- bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
- close(dst_fd);
- break;
+ /* Hardlinks have no separate mode/ownership, skip chown/chmod */
+ goto ret;
+ }
+
+ /* Create the filesystem entry */
+ switch (file_header->mode & S_IFMT) {
+ case S_IFREG: {
+ /* Regular file */
+ int flags = O_WRONLY | O_CREAT | O_EXCL;
+ if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
+ flags = O_WRONLY | O_CREAT | O_TRUNC;
+ dst_fd = xopen3(file_header->name,
+ flags,
+ file_header->mode
+ );
+ bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
+ close(dst_fd);
+ break;
+ }
+ case S_IFDIR:
+ res = mkdir(file_header->name, file_header->mode);
+ if ((res == -1)
+ && (errno != EISDIR) /* btw, Linux doesn't return this */
+ && (errno != EEXIST)
+ && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
+ ) {
+ bb_perror_msg("can't make dir %s", file_header->name);
}
- case S_IFDIR:
- res = mkdir(file_header->name, file_header->mode);
- if ((res == -1)
- && (errno != EISDIR) /* btw, Linux doesn't return this */
- && (errno != EEXIST)
- && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
- ) {
- bb_perror_msg("can't make dir %s", file_header->name);
- }
- break;
- case S_IFLNK:
- /* Symlink */
- res = symlink(file_header->link_target, file_header->name);
- if ((res == -1)
- && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
- ) {
- bb_perror_msg("can't create %slink "
- "from %s to %s", "sym",
- file_header->name,
- file_header->link_target);
- }
- break;
- case S_IFSOCK:
- case S_IFBLK:
- case S_IFCHR:
- case S_IFIFO:
- res = mknod(file_header->name, file_header->mode, file_header->device);
- if ((res == -1)
- && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
- ) {
- bb_perror_msg("can't create node %s", file_header->name);
- }
- break;
- default:
- bb_error_msg_and_die("unrecognized file type");
+ break;
+ case S_IFLNK:
+ /* Symlink */
+ res = symlink(file_header->link_target, file_header->name);
+ if ((res == -1)
+ && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
+ ) {
+ bb_perror_msg("can't create %slink "
+ "from %s to %s", "sym",
+ file_header->name,
+ file_header->link_target);
+ }
+ break;
+ case S_IFSOCK:
+ case S_IFBLK:
+ case S_IFCHR:
+ case S_IFIFO:
+ res = mknod(file_header->name, file_header->mode, file_header->device);
+ if ((res == -1)
+ && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
+ ) {
+ bb_perror_msg("can't create node %s", file_header->name);
}
+ break;
+ default:
+ bb_error_msg_and_die("unrecognized file type");
}
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)
#endif /* FEATURE_TAR_UNAME_GNAME */
+ /* NB: GNU tar shows "->" for symlinks and "link to" for hardlinks */
if (file_header->link_target) {
printf(" -> %s", file_header->link_target);
}