| @@ -159,47 +159,44 @@ void FAST_FUNC fork_transformer(int fd, const char *transform_prog) |
| */ |
| static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed) |
| { |
| - | union { |
| - | uint8_t b[4]; |
| - | uint16_t b16[2]; |
| - | uint32_t b32[1]; |
| - | } magic; |
| transformer_state_t *xstate; |
| |
| xstate = xzalloc(sizeof(*xstate)); |
| xstate->src_fd = fd; |
| - | xstate->signature_skipped = 2; |
| |
| /* .gz and .bz2 both have 2-byte signature, and their |
| * unpack_XXX_stream wants this header skipped. */ |
| - | xread(fd, magic.b16, sizeof(magic.b16[0])); |
| + | xstate->signature_skipped = 2; |
| + | xread(fd, xstate->magic.b16, 2); |
| if (ENABLE_FEATURE_SEAMLESS_GZ |
| - | && magic.b16[0] == GZIP_MAGIC |
| + | && xstate->magic.b16[0] == GZIP_MAGIC |
| ) { |
| xstate->xformer = unpack_gz_stream; |
| USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";) |
| goto found_magic; |
| } |
| if (ENABLE_FEATURE_SEAMLESS_Z |
| - | && magic.b16[0] == COMPRESS_MAGIC |
| + | && xstate->magic.b16[0] == COMPRESS_MAGIC |
| ) { |
| xstate->xformer = unpack_Z_stream; |
| USE_FOR_NOMMU(xstate->xformer_prog = "uncompress";) |
| goto found_magic; |
| } |
| if (ENABLE_FEATURE_SEAMLESS_BZ2 |
| - | && magic.b16[0] == BZIP2_MAGIC |
| + | && xstate->magic.b16[0] == BZIP2_MAGIC |
| ) { |
| xstate->xformer = unpack_bz2_stream; |
| USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";) |
| goto found_magic; |
| } |
| if (ENABLE_FEATURE_SEAMLESS_XZ |
| - | && magic.b16[0] == XZ_MAGIC1 |
| + | && xstate->magic.b16[0] == XZ_MAGIC1 |
| ) { |
| + | uint32_t v32; |
| xstate->signature_skipped = 6; |
| - | xread(fd, magic.b32, sizeof(magic.b32[0])); |
| - | if (magic.b32[0] == XZ_MAGIC2) { |
| + | xread(fd, &xstate->magic.b16[1], 4); |
| + | move_from_unaligned32(v32, &xstate->magic.b16[1]); |
| + | if (v32 == XZ_MAGIC2) { |
| xstate->xformer = unpack_xz_stream; |
| USE_FOR_NOMMU(xstate->xformer_prog = "unxz";) |
| goto found_magic; |
| @@ -344,11 +341,24 @@ void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_ |
| *maxsz_p = xstate->mem_output_size; |
| } |
| } else { |
| - | /* File is not compressed */ |
| - | //FIXME: avoid seek |
| - | xlseek(xstate->src_fd, - xstate->signature_skipped, SEEK_CUR); |
| + | /* File is not compressed. |
| + | * We already read first few bytes, account for that. |
| + | * Exmaple where it happens: |
| + | * "modinfo MODULE.ko" (not compressed) |
| + | * open("MODULE.ko", O_RDONLY|O_LARGEFILE) = 4 |
| + | * read(4, "\177E", 2) = 2 |
| + | * fstat64(4, ...) |
| + | * mmap(...) |
| + | * read(4, "LF\2\1\1\0\0\0\0"... |
| + | * ...and we avoided seeking on the fd! :) |
| + | */ |
| xstate->signature_skipped = 0; |
| - | image = xmalloc_read(xstate->src_fd, maxsz_p); |
| + | image = xmalloc_read_with_initial_buf( |
| + | xstate->src_fd, |
| + | maxsz_p, |
| + | xmemdup(&xstate->magic, xstate->signature_skipped), |
| + | xstate->signature_skipped |
| + | ); |
| } |
| |
| if (!image) |