aboutsummaryrefslogtreecommitdiff
path: root/archival/libunarchive
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-04-09 10:52:52 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-04-09 10:52:52 +0200
commit02365a6ef73defb8689d3ed5228125d72993dec9 (patch)
tree26358e718c5232ee44ad750f1b386f0f4138512a /archival/libunarchive
parent823b636cd14d337ebb8766c5c181737fb3860b42 (diff)
downloadbusybox-w32-02365a6ef73defb8689d3ed5228125d72993dec9.tar.gz
busybox-w32-02365a6ef73defb8689d3ed5228125d72993dec9.tar.bz2
busybox-w32-02365a6ef73defb8689d3ed5228125d72993dec9.zip
tar: fix mishandling of repeated hardlink in tarball; expand tests
function old new delta data_extract_all 727 767 +40 get_header_tar 1576 1572 -4 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'archival/libunarchive')
-rw-r--r--archival/libunarchive/data_extract_all.c32
-rw-r--r--archival/libunarchive/get_header_tar.c5
2 files changed, 28 insertions, 9 deletions
diff --git a/archival/libunarchive/data_extract_all.c b/archival/libunarchive/data_extract_all.c
index cc4894229..de2367ac2 100644
--- a/archival/libunarchive/data_extract_all.c
+++ b/archival/libunarchive/data_extract_all.c
@@ -34,12 +34,30 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
34 34
35 if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) { 35 if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) {
36 /* Remove the entry if it exists */ 36 /* Remove the entry if it exists */
37 if ((!S_ISDIR(file_header->mode)) 37 if (!S_ISDIR(file_header->mode)) {
38 && (unlink(file_header->name) == -1) 38 /* Is it hardlink?
39 && (errno != ENOENT) 39 * We encode hard links as regular files of size 0 with a symlink */
40 ) { 40 if (S_ISREG(file_header->mode)
41 bb_perror_msg_and_die("can't remove old file %s", 41 && file_header->link_target
42 file_header->name); 42 && file_header->size == 0
43 ) {
44 /* Ugly special case:
45 * tar cf t.tar hardlink1 hardlink2 hardlink1
46 * results in this tarball structure:
47 * hardlink1
48 * hardlink2 -> hardlink1
49 * hardlink1 -> hardlink1 <== !!!
50 */
51 if (strcmp(file_header->link_target, file_header->name) == 0)
52 goto ret;
53 }
54 /* Proceed with deleting */
55 if (unlink(file_header->name) == -1
56 && errno != ENOENT
57 ) {
58 bb_perror_msg_and_die("can't remove old file %s",
59 file_header->name);
60 }
43 } 61 }
44 } 62 }
45 else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) { 63 else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) {
@@ -65,7 +83,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
65 } 83 }
66 84
67 /* Handle hard links separately 85 /* Handle hard links separately
68 * We identified hard links as regular files of size 0 with a symlink */ 86 * We encode hard links as regular files of size 0 with a symlink */
69 if (S_ISREG(file_header->mode) 87 if (S_ISREG(file_header->mode)
70 && file_header->link_target 88 && file_header->link_target
71 && file_header->size == 0 89 && file_header->size == 0
diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c
index cf0b9ab02..adb4c157b 100644
--- a/archival/libunarchive/get_header_tar.c
+++ b/archival/libunarchive/get_header_tar.c
@@ -507,8 +507,9 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
507 archive_handle->action_header(/*archive_handle->*/ file_header); 507 archive_handle->action_header(/*archive_handle->*/ file_header);
508 /* Note that we kill the '/' only after action_header() */ 508 /* Note that we kill the '/' only after action_header() */
509 /* (like GNU tar 1.15.1: verbose mode outputs "dir/dir/") */ 509 /* (like GNU tar 1.15.1: verbose mode outputs "dir/dir/") */
510 if (cp) *cp = '\0'; 510 if (cp)
511 archive_handle->ah_flags |= ARCHIVE_EXTRACT_QUIET; 511 *cp = '\0';
512 //archive_handle->ah_flags |= ARCHIVE_EXTRACT_QUIET; // why??
512 archive_handle->action_data(archive_handle); 513 archive_handle->action_data(archive_handle);
513 llist_add_to(&(archive_handle->passed), file_header->name); 514 llist_add_to(&(archive_handle->passed), file_header->name);
514 } else { 515 } else {