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