79 lines
		
	
	
	
		
			1.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			79 lines
		
	
	
	
		
			1.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
|   | #include <stdio.h>
 | ||
|  | #include <unistd.h>
 | ||
|  | #include <sys/stat.h>
 | ||
|  | #include <sys/mman.h>
 | ||
|  | #include <zlib.h>
 | ||
|  | 
 | ||
|  | #include "util/util.h"
 | ||
|  | #include "util/debug.h"
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #define CHUNK_SIZE  16384
 | ||
|  | 
 | ||
|  | int gzip_decompress_to_file(const char *input, int output_fd) | ||
|  | { | ||
|  | 	int ret = Z_STREAM_ERROR; | ||
|  | 	int input_fd; | ||
|  | 	void *ptr; | ||
|  | 	int len; | ||
|  | 	struct stat stbuf; | ||
|  | 	unsigned char buf[CHUNK_SIZE]; | ||
|  | 	z_stream zs = { | ||
|  | 		.zalloc		= Z_NULL, | ||
|  | 		.zfree		= Z_NULL, | ||
|  | 		.opaque		= Z_NULL, | ||
|  | 		.avail_in	= 0, | ||
|  | 		.next_in	= Z_NULL, | ||
|  | 	}; | ||
|  | 
 | ||
|  | 	input_fd = open(input, O_RDONLY); | ||
|  | 	if (input_fd < 0) | ||
|  | 		return -1; | ||
|  | 
 | ||
|  | 	if (fstat(input_fd, &stbuf) < 0) | ||
|  | 		goto out_close; | ||
|  | 
 | ||
|  | 	ptr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0); | ||
|  | 	if (ptr == MAP_FAILED) | ||
|  | 		goto out_close; | ||
|  | 
 | ||
|  | 	if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK) | ||
|  | 		goto out_unmap; | ||
|  | 
 | ||
|  | 	zs.next_in = ptr; | ||
|  | 	zs.avail_in = stbuf.st_size; | ||
|  | 
 | ||
|  | 	do { | ||
|  | 		zs.next_out = buf; | ||
|  | 		zs.avail_out = CHUNK_SIZE; | ||
|  | 
 | ||
|  | 		ret = inflate(&zs, Z_NO_FLUSH); | ||
|  | 		switch (ret) { | ||
|  | 		case Z_NEED_DICT: | ||
|  | 			ret = Z_DATA_ERROR; | ||
|  | 			/* fall through */ | ||
|  | 		case Z_DATA_ERROR: | ||
|  | 		case Z_MEM_ERROR: | ||
|  | 			goto out; | ||
|  | 		default: | ||
|  | 			break; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		len = CHUNK_SIZE - zs.avail_out; | ||
|  | 		if (writen(output_fd, buf, len) != len) { | ||
|  | 			ret = Z_DATA_ERROR; | ||
|  | 			goto out; | ||
|  | 		} | ||
|  | 
 | ||
|  | 	} while (ret != Z_STREAM_END); | ||
|  | 
 | ||
|  | out: | ||
|  | 	inflateEnd(&zs); | ||
|  | out_unmap: | ||
|  | 	munmap(ptr, stbuf.st_size); | ||
|  | out_close: | ||
|  | 	close(input_fd); | ||
|  | 
 | ||
|  | 	return ret == Z_STREAM_END ? 0 : -1; | ||
|  | } |