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