diff options
Diffstat (limited to 'archival/libarchive/open_transformer.c')
-rw-r--r-- | archival/libarchive/open_transformer.c | 44 |
1 files changed, 27 insertions, 17 deletions
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index 69f3ecc66..3a0fc4712 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c | |||
@@ -180,47 +180,44 @@ void FAST_FUNC fork_transformer(int fd, const char *transform_prog) | |||
180 | */ | 180 | */ |
181 | static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed) | 181 | static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed) |
182 | { | 182 | { |
183 | union { | ||
184 | uint8_t b[4]; | ||
185 | uint16_t b16[2]; | ||
186 | uint32_t b32[1]; | ||
187 | } magic; | ||
188 | transformer_state_t *xstate; | 183 | transformer_state_t *xstate; |
189 | 184 | ||
190 | xstate = xzalloc(sizeof(*xstate)); | 185 | xstate = xzalloc(sizeof(*xstate)); |
191 | xstate->src_fd = fd; | 186 | xstate->src_fd = fd; |
192 | xstate->signature_skipped = 2; | ||
193 | 187 | ||
194 | /* .gz and .bz2 both have 2-byte signature, and their | 188 | /* .gz and .bz2 both have 2-byte signature, and their |
195 | * unpack_XXX_stream wants this header skipped. */ | 189 | * unpack_XXX_stream wants this header skipped. */ |
196 | xread(fd, magic.b16, sizeof(magic.b16[0])); | 190 | xstate->signature_skipped = 2; |
191 | xread(fd, xstate->magic.b16, 2); | ||
197 | if (ENABLE_FEATURE_SEAMLESS_GZ | 192 | if (ENABLE_FEATURE_SEAMLESS_GZ |
198 | && magic.b16[0] == GZIP_MAGIC | 193 | && xstate->magic.b16[0] == GZIP_MAGIC |
199 | ) { | 194 | ) { |
200 | xstate->xformer = unpack_gz_stream; | 195 | xstate->xformer = unpack_gz_stream; |
201 | USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";) | 196 | USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";) |
202 | goto found_magic; | 197 | goto found_magic; |
203 | } | 198 | } |
204 | if (ENABLE_FEATURE_SEAMLESS_Z | 199 | if (ENABLE_FEATURE_SEAMLESS_Z |
205 | && magic.b16[0] == COMPRESS_MAGIC | 200 | && xstate->magic.b16[0] == COMPRESS_MAGIC |
206 | ) { | 201 | ) { |
207 | xstate->xformer = unpack_Z_stream; | 202 | xstate->xformer = unpack_Z_stream; |
208 | USE_FOR_NOMMU(xstate->xformer_prog = "uncompress";) | 203 | USE_FOR_NOMMU(xstate->xformer_prog = "uncompress";) |
209 | goto found_magic; | 204 | goto found_magic; |
210 | } | 205 | } |
211 | if (ENABLE_FEATURE_SEAMLESS_BZ2 | 206 | if (ENABLE_FEATURE_SEAMLESS_BZ2 |
212 | && magic.b16[0] == BZIP2_MAGIC | 207 | && xstate->magic.b16[0] == BZIP2_MAGIC |
213 | ) { | 208 | ) { |
214 | xstate->xformer = unpack_bz2_stream; | 209 | xstate->xformer = unpack_bz2_stream; |
215 | USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";) | 210 | USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";) |
216 | goto found_magic; | 211 | goto found_magic; |
217 | } | 212 | } |
218 | if (ENABLE_FEATURE_SEAMLESS_XZ | 213 | if (ENABLE_FEATURE_SEAMLESS_XZ |
219 | && magic.b16[0] == XZ_MAGIC1 | 214 | && xstate->magic.b16[0] == XZ_MAGIC1 |
220 | ) { | 215 | ) { |
216 | uint32_t v32; | ||
221 | xstate->signature_skipped = 6; | 217 | xstate->signature_skipped = 6; |
222 | xread(fd, magic.b32, sizeof(magic.b32[0])); | 218 | xread(fd, &xstate->magic.b16[1], 4); |
223 | if (magic.b32[0] == XZ_MAGIC2) { | 219 | move_from_unaligned32(v32, &xstate->magic.b16[1]); |
220 | if (v32 == XZ_MAGIC2) { | ||
224 | xstate->xformer = unpack_xz_stream; | 221 | xstate->xformer = unpack_xz_stream; |
225 | USE_FOR_NOMMU(xstate->xformer_prog = "unxz";) | 222 | USE_FOR_NOMMU(xstate->xformer_prog = "unxz";) |
226 | goto found_magic; | 223 | goto found_magic; |
@@ -365,11 +362,24 @@ void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_ | |||
365 | *maxsz_p = xstate->mem_output_size; | 362 | *maxsz_p = xstate->mem_output_size; |
366 | } | 363 | } |
367 | } else { | 364 | } else { |
368 | /* File is not compressed */ | 365 | /* File is not compressed. |
369 | //FIXME: avoid seek | 366 | * We already read first few bytes, account for that. |
370 | xlseek(xstate->src_fd, - xstate->signature_skipped, SEEK_CUR); | 367 | * Example where it happens: |
368 | * "modinfo MODULE.ko" (not compressed) | ||
369 | * open("MODULE.ko", O_RDONLY|O_LARGEFILE) = 4 | ||
370 | * read(4, "\177E", 2) = 2 | ||
371 | * fstat64(4, ...) | ||
372 | * mmap(...) | ||
373 | * read(4, "LF\2\1\1\0\0\0\0"... | ||
374 | * ...and we avoided seeking on the fd! :) | ||
375 | */ | ||
376 | image = xmalloc_read_with_initial_buf( | ||
377 | xstate->src_fd, | ||
378 | maxsz_p, | ||
379 | xmemdup(&xstate->magic, xstate->signature_skipped), | ||
380 | xstate->signature_skipped | ||
381 | ); | ||
371 | xstate->signature_skipped = 0; | 382 | xstate->signature_skipped = 0; |
372 | image = xmalloc_read(xstate->src_fd, maxsz_p); | ||
373 | } | 383 | } |
374 | 384 | ||
375 | if (!image) | 385 | if (!image) |