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 /archival/libunarchive | |
parent | 02365a6ef73defb8689d3ed5228125d72993dec9 (diff) |
tar: fix "hardlinks to symlinks chown" bug 1519.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'archival/libunarchive')
-rw-r--r-- | archival/libunarchive/data_extract_all.c | 102 | ||||
-rw-r--r-- | archival/libunarchive/header_verbose_list.c | 1 |
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); } |