diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-19 11:26:28 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-19 11:26:28 +0000 |
commit | 431a7c9c53b69a7416091721da673bcff7c91a02 (patch) | |
tree | 03cbe0e15af01d82b05138f0db41d44179262a3f /archival/libunarchive | |
parent | a37e7134f76b7661b86bb9cc926f28f81b1e1109 (diff) | |
download | busybox-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.c | 52 |
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); | |||
46 | char get_header_tar(archive_handle_t *archive_handle) | 46 | char 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 |