Merge tag 'linux-kselftest-kunit-5.15-rc1' of git://git.kernel.org/pub/scm/linux...
[linux-2.6-microblaze.git] / tools / perf / util / zlib.c
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 }