1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <fcntl.h> |
3 | #include <stdio.h> |
4 | #include <string.h> |
5 | #include <unistd.h> |
6 | #include <sys/stat.h> |
7 | #include <sys/mman.h> |
8 | #include <zlib.h> |
9 | #include <linux/compiler.h> |
10 | #include <internal/lib.h> |
11 | |
12 | #include "util/compress.h" |
13 | |
14 | #define CHUNK_SIZE 16384 |
15 | |
16 | int gzip_decompress_to_file(const char *input, int output_fd) |
17 | { |
18 | int ret = Z_STREAM_ERROR; |
19 | int input_fd; |
20 | void *ptr; |
21 | int len; |
22 | struct stat stbuf; |
23 | unsigned char buf[CHUNK_SIZE]; |
24 | z_stream zs = { |
25 | .zalloc = Z_NULL, |
26 | .zfree = Z_NULL, |
27 | .opaque = Z_NULL, |
28 | .avail_in = 0, |
29 | .next_in = Z_NULL, |
30 | }; |
31 | |
32 | input_fd = open(input, O_RDONLY); |
33 | if (input_fd < 0) |
34 | return -1; |
35 | |
36 | if (fstat(input_fd, &stbuf) < 0) |
37 | goto out_close; |
38 | |
39 | ptr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0); |
40 | if (ptr == MAP_FAILED) |
41 | goto out_close; |
42 | |
43 | if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK) |
44 | goto out_unmap; |
45 | |
46 | zs.next_in = ptr; |
47 | zs.avail_in = stbuf.st_size; |
48 | |
49 | do { |
50 | zs.next_out = buf; |
51 | zs.avail_out = CHUNK_SIZE; |
52 | |
53 | ret = inflate(&zs, Z_NO_FLUSH); |
54 | switch (ret) { |
55 | case Z_NEED_DICT: |
56 | ret = Z_DATA_ERROR; |
57 | /* fall through */ |
58 | case Z_DATA_ERROR: |
59 | case Z_MEM_ERROR: |
60 | goto out; |
61 | default: |
62 | break; |
63 | } |
64 | |
65 | len = CHUNK_SIZE - zs.avail_out; |
66 | if (writen(output_fd, buf, len) != len) { |
67 | ret = Z_DATA_ERROR; |
68 | goto out; |
69 | } |
70 | |
71 | } while (ret != Z_STREAM_END); |
72 | |
73 | out: |
74 | inflateEnd(&zs); |
75 | out_unmap: |
76 | munmap(ptr, stbuf.st_size); |
77 | out_close: |
78 | close(input_fd); |
79 | |
80 | return ret == Z_STREAM_END ? 0 : -1; |
81 | } |
82 | |
83 | bool gzip_is_compressed(const char *input) |
84 | { |
85 | int fd = open(input, O_RDONLY); |
86 | const uint8_t magic[2] = { 0x1f, 0x8b }; |
87 | char buf[2] = { 0 }; |
88 | ssize_t rc; |
89 | |
90 | if (fd < 0) |
91 | return -1; |
92 | |
93 | rc = read(fd, buf, sizeof(buf)); |
94 | close(fd); |
95 | return rc == sizeof(buf) ? |
96 | memcmp(buf, magic, sizeof(buf)) == 0 : false; |
97 | } |
98 | |