aboutsummaryrefslogtreecommitdiff
path: root/archival/libunarchive
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-02-19 11:26:28 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-02-19 11:26:28 +0000
commit431a7c9c53b69a7416091721da673bcff7c91a02 (patch)
tree03cbe0e15af01d82b05138f0db41d44179262a3f /archival/libunarchive
parenta37e7134f76b7661b86bb9cc926f28f81b1e1109 (diff)
downloadbusybox-w32-431a7c9c53b69a7416091721da673bcff7c91a02.tar.gz
busybox-w32-431a7c9c53b69a7416091721da673bcff7c91a02.tar.bz2
busybox-w32-431a7c9c53b69a7416091721da673bcff7c91a02.zip
tar: optional autodetection of gz/bz2 compressed tarballs.
+130 bytes. Closes bug 992.
Diffstat (limited to 'archival/libunarchive')
-rw-r--r--archival/libunarchive/get_header_tar.c52
1 files changed, 44 insertions, 8 deletions
diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c
index 893cd5b79..54c8f7665 100644
--- a/archival/libunarchive/get_header_tar.c
+++ b/archival/libunarchive/get_header_tar.c
@@ -46,6 +46,9 @@ void BUG_tar_header_size(void);
46char get_header_tar(archive_handle_t *archive_handle) 46char get_header_tar(archive_handle_t *archive_handle)
47{ 47{
48 static smallint end; 48 static smallint end;
49#if ENABLE_FEATURE_TAR_AUTODETECT
50 static smallint not_first;
51#endif
49 52
50 file_header_t *file_header = archive_handle->file_header; 53 file_header_t *file_header = archive_handle->file_header;
51 struct { 54 struct {
@@ -115,7 +118,7 @@ char get_header_tar(archive_handle_t *archive_handle)
115 * Read until the end to empty the pipe from gz or bz2 118 * Read until the end to empty the pipe from gz or bz2
116 */ 119 */
117 while (full_read(archive_handle->src_fd, &tar, 512) == 512) 120 while (full_read(archive_handle->src_fd, &tar, 512) == 512)
118 /* repeat */; 121 continue;
119 return EXIT_FAILURE; 122 return EXIT_FAILURE;
120 } 123 }
121 end = 1; 124 end = 1;
@@ -123,16 +126,49 @@ char get_header_tar(archive_handle_t *archive_handle)
123 } 126 }
124 end = 0; 127 end = 0;
125 128
126 /* Check header has valid magic, "ustar" is for the proper tar 129 /* Check header has valid magic, "ustar" is for the proper tar,
127 * 0's are for the old tar format 130 * five NULs are for the old tar format */
128 */ 131 if (strncmp(tar.magic, "ustar", 5) != 0
129 if (strncmp(tar.magic, "ustar", 5) != 0) { 132 && (!ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY
130#if ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY 133 || memcmp(tar.magic, "\0\0\0\0", 5) != 0)
131 if (memcmp(tar.magic, "\0\0\0\0", 5) != 0) 134 ) {
135#if ENABLE_FEATURE_TAR_AUTODETECT
136 char (*get_header_ptr)(archive_handle_t *);
137
138 /* tar gz/bz autodetect: check for gz/bz2 magic.
139 * If it is the very first block, and we see the magic,
140 * we can switch to get_header_tar_gz/bz2/lzma().
141 * Needs seekable fd. I wish recv(MSG_PEEK) would work
142 * on any fd... */
143 if (not_first)
144 goto err;
145#if ENABLE_FEATURE_TAR_GZIP
146 if (tar.name[0] == 0x1f && tar.name[1] == 0x8b) { /* gzip */
147 get_header_ptr = get_header_tar_gz;
148 } else
132#endif 149#endif
133 bb_error_msg_and_die("invalid tar magic"); 150#if ENABLE_FEATURE_TAR_BZIP2
151 if (tar.name[0] == 'B' && tar.name[1] == 'Z'
152 && tar.name[2] == 'h' && isdigit(tar.name[3])
153 ) { /* bzip2 */
154 get_header_ptr = get_header_tar_bz2;
155 } else
156#endif
157 goto err;
158 if (lseek(archive_handle->src_fd, -512, SEEK_CUR) != 0)
159 goto err;
160 while (get_header_ptr(archive_handle) == EXIT_SUCCESS)
161 continue;
162 return EXIT_FAILURE;
163 err:
164#endif /* FEATURE_TAR_AUTODETECT */
165 bb_error_msg_and_die("invalid tar magic");
134 } 166 }
135 167
168#if ENABLE_FEATURE_TAR_AUTODETECT
169 not_first = 1;
170#endif
171
136 /* Do checksum on headers. 172 /* Do checksum on headers.
137 * POSIX says that checksum is done on unsigned bytes, but 173 * POSIX says that checksum is done on unsigned bytes, but
138 * Sun and HP-UX gets it wrong... more details in 174 * Sun and HP-UX gets it wrong... more details in