diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-04-09 10:52:52 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-04-09 10:52:52 +0200 |
commit | 02365a6ef73defb8689d3ed5228125d72993dec9 (patch) | |
tree | 26358e718c5232ee44ad750f1b386f0f4138512a /archival/libunarchive | |
parent | 823b636cd14d337ebb8766c5c181737fb3860b42 (diff) | |
download | busybox-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.c | 32 | ||||
-rw-r--r-- | archival/libunarchive/get_header_tar.c | 5 |
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 { |