aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2015-10-22 13:30:34 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2015-10-22 13:30:34 +0200
commitf167e4503d08561054e75deb2ff123be2b30afa5 (patch)
tree9b5d8c110cdf4438d59df874f70204da8c55003b
parent62ae323df0856546754ecfe226fc9bf0dc16bcb8 (diff)
downloadbusybox-w32-f167e4503d08561054e75deb2ff123be2b30afa5.tar.gz
busybox-w32-f167e4503d08561054e75deb2ff123be2b30afa5.tar.bz2
busybox-w32-f167e4503d08561054e75deb2ff123be2b30afa5.zip
tar: shrink hardlink name handling code
function old new delta data_extract_all 1069 1040 -29 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--archival/libarchive/data_extract_all.c43
1 files changed, 17 insertions, 26 deletions
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c
index bd51d2ad3..cf821c9de 100644
--- a/archival/libarchive/data_extract_all.c
+++ b/archival/libarchive/data_extract_all.c
@@ -12,12 +12,11 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
12 file_header_t *file_header = archive_handle->file_header; 12 file_header_t *file_header = archive_handle->file_header;
13 int dst_fd; 13 int dst_fd;
14 int res; 14 int res;
15 char *hard_link;
15#if ENABLE_FEATURE_TAR_LONG_OPTIONS 16#if ENABLE_FEATURE_TAR_LONG_OPTIONS
16 char *dst_name; 17 char *dst_name;
17 char *dst_link;
18#else 18#else
19# define dst_name (file_header->name) 19# define dst_name (file_header->name)
20# define dst_link (file_header->link_target)
21#endif 20#endif
22 21
23#if ENABLE_FEATURE_TAR_SELINUX 22#if ENABLE_FEATURE_TAR_SELINUX
@@ -31,9 +30,14 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
31 } 30 }
32#endif 31#endif
33 32
33 /* Hard links are encoded as regular files of size 0
34 * with a nonempty link field */
35 hard_link = NULL;
36 if (S_ISREG(file_header->mode) && file_header->size == 0)
37 hard_link = file_header->link_target;
38
34#if ENABLE_FEATURE_TAR_LONG_OPTIONS 39#if ENABLE_FEATURE_TAR_LONG_OPTIONS
35 dst_name = file_header->name; 40 dst_name = file_header->name;
36 dst_link = file_header->link_target;
37 if (archive_handle->tar__strip_components) { 41 if (archive_handle->tar__strip_components) {
38 unsigned n = archive_handle->tar__strip_components; 42 unsigned n = archive_handle->tar__strip_components;
39 do { 43 do {
@@ -47,21 +51,18 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
47 * Link target is shortened only for hardlinks: 51 * Link target is shortened only for hardlinks:
48 * softlinks restored unchanged. 52 * softlinks restored unchanged.
49 */ 53 */
50 if (S_ISREG(file_header->mode) 54 if (hard_link) {
51 && file_header->size == 0
52 && dst_link
53 ) {
54// GNU tar 1.26 does not check that we reached end of link name: 55// GNU tar 1.26 does not check that we reached end of link name:
55// if "dir/hardlink" is hardlinked to "file", 56// if "dir/hardlink" is hardlinked to "file",
56// tar xvf a.tar --strip-components=1 says: 57// tar xvf a.tar --strip-components=1 says:
57// tar: hardlink: Cannot hard link to '': No such file or directory 58// tar: hardlink: Cannot hard link to '': No such file or directory
58// and continues processing. We silently skip such entries. 59// and continues processing. We silently skip such entries.
59 dst_link = strchr(dst_link, '/'); 60 hard_link = strchr(hard_link, '/');
60 if (!dst_link || dst_link[1] == '\0') { 61 if (!hard_link || hard_link[1] == '\0') {
61 data_skip(archive_handle); 62 data_skip(archive_handle);
62 return; 63 return;
63 } 64 }
64 dst_link++; 65 hard_link++;
65 } 66 }
66 } while (--n != 0); 67 } while (--n != 0);
67 } 68 }
@@ -79,12 +80,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
79 if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) { 80 if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) {
80 /* Remove the entry if it exists */ 81 /* Remove the entry if it exists */
81 if (!S_ISDIR(file_header->mode)) { 82 if (!S_ISDIR(file_header->mode)) {
82 /* Is it hardlink? 83 if (hard_link) {
83 * We encode hard links as regular files of size 0 with a symlink */
84 if (S_ISREG(file_header->mode)
85 && file_header->size == 0
86 && dst_link
87 ) {
88 /* Ugly special case: 84 /* Ugly special case:
89 * tar cf t.tar hardlink1 hardlink2 hardlink1 85 * tar cf t.tar hardlink1 hardlink2 hardlink1
90 * results in this tarball structure: 86 * results in this tarball structure:
@@ -92,7 +88,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
92 * hardlink2 -> hardlink1 88 * hardlink2 -> hardlink1
93 * hardlink1 -> hardlink1 <== !!! 89 * hardlink1 -> hardlink1 <== !!!
94 */ 90 */
95 if (strcmp(dst_link, dst_name) == 0) 91 if (strcmp(hard_link, dst_name) == 0)
96 goto ret; 92 goto ret;
97 } 93 }
98 /* Proceed with deleting */ 94 /* Proceed with deleting */
@@ -128,19 +124,14 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
128 } 124 }
129 } 125 }
130 126
131 /* Handle hard links separately 127 /* Handle hard links separately */
132 * We encode hard links as regular files of size 0 with a symlink */ 128 if (hard_link) {
133 if (S_ISREG(file_header->mode) 129 res = link(hard_link, dst_name);
134 && file_header->size == 0
135 && dst_link
136 ) {
137 /* Hard link */
138 res = link(dst_link, dst_name);
139 if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { 130 if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
140 bb_perror_msg("can't create %slink " 131 bb_perror_msg("can't create %slink "
141 "from %s to %s", "hard", 132 "from %s to %s", "hard",
142 dst_name, 133 dst_name,
143 dst_link); 134 hard_link);
144 } 135 }
145 /* Hardlinks have no separate mode/ownership, skip chown/chmod */ 136 /* Hardlinks have no separate mode/ownership, skip chown/chmod */
146 goto ret; 137 goto ret;