zlib.c (1793B)
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 16int 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 73out: 74 inflateEnd(&zs); 75out_unmap: 76 munmap(ptr, stbuf.st_size); 77out_close: 78 close(input_fd); 79 80 return ret == Z_STREAM_END ? 0 : -1; 81} 82 83bool 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}