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) |
