3
#include "decompress.h"
5
/* Code in decompress_zlib from
7
* https://raw.github.com/madler/zlib/master/examples/zpipe.c
9
* zpipe.c: example of proper use of zlib's inflate() and deflate()
10
* Not copyrighted -- provided to the public domain
11
* Version 1.4 11 December 2005 Mark Adler
15
static void* decompress_zlib(const void* buf, const int buf_len,
16
const char* dir_full_path, int* new_buf_len) {
18
unsigned char* result = NULL;
19
size_t result_size = 0;
23
log_debug("Decompressing zlib file %s", dir_full_path);
25
/* allocate inflate state */
26
stream.zalloc = Z_NULL;
27
stream.zfree = Z_NULL;
28
stream.opaque = Z_NULL;
30
stream.next_in = Z_NULL;
32
/* Add 32 to allow zlib and gzip format detection */
33
if(inflateInit2(&stream, 32 + 15) != Z_OK) {
34
log_err("Unable to initialize zlib: %s", stream.msg);
38
stream.avail_in = buf_len;
39
stream.next_in = (void*)buf;
41
pagesize = getpagesize();
42
result_size = ((buf_len + pagesize - 1) & ~(pagesize - 1));
45
/* Double the buffer size and realloc */
47
result = (unsigned char*)realloc(result, result_size * sizeof(unsigned char));
49
log_err("Unable to allocate %d bytes to decompress file %s", result_size * sizeof(unsigned char), dir_full_path);
54
stream.avail_out = result_size / 2;
55
stream.next_out = &result[stream.total_out];
56
ret = inflate(&stream, Z_SYNC_FLUSH);
57
log_debug("inflate ret = %d", ret);
59
case Z_STREAM_ERROR: {
60
log_err("Found stream error while decompressing zlib stream: %s", stream.msg);
67
log_err("Found mem/data error while decompressing zlib stream: %s", stream.msg);
72
} while(stream.avail_out == 0);
75
*new_buf_len = stream.total_out;
78
if(ret == Z_STREAM_END) {
87
static void* decompress_lwz(const void* buf, const int buf_len,
88
const char* dir_full_path, int* new_buf_len) {
89
(void)buf; (void)buf_len;
90
log_err("LWZ (UNIX compress) files not yet supported: %s", dir_full_path);
95
static void* decompress_zip(const void* buf, const int buf_len,
96
const char* dir_full_path, int* new_buf_len) {
97
(void)buf; (void)buf_len;
98
log_err("Zip files not yet supported: %s", dir_full_path);
104
/* This function is very hot. It's called on every file when zip is enabled. */
105
void* decompress(const ag_compression_type zip_type, const void* buf, const int buf_len,
106
const char* dir_full_path, int* new_buf_len) {
110
return decompress_zlib(buf, buf_len, dir_full_path, new_buf_len);
112
return decompress_lwz(buf, buf_len, dir_full_path, new_buf_len);
114
return decompress_zip(buf, buf_len, dir_full_path, new_buf_len);
115
case AG_NO_COMPRESSION:
116
log_err("File %s is not compressed", dir_full_path);
119
log_err("Unsupported compression type: %d", zip_type);
127
/* This function is very hot. It's called on every file. */
128
ag_compression_type is_zipped(const void* buf, const int buf_len) {
130
* compressed file: { 0x1F, 0x9B }
131
* http://en.wikipedia.org/wiki/Compress
133
* gzip file: { 0x1F, 0x8B }
134
* http://www.gzip.org/zlib/rfc-gzip.html#file-format
136
* zip file: { 0x50, 0x4B, 0x03, 0x04 }
137
* http://www.pkware.com/documents/casestudies/APPNOTE.TXT (Section 4.3)
140
const unsigned char *buf_c = buf;
143
return AG_NO_COMPRESSION;
146
/* Check for gzip & compress */
148
if(buf_c[0] == 0x1F) {
149
if(buf_c[1] == 0x8B) {
150
log_debug("Found gzip-based stream");
152
} else if(buf_c[1] == 0x9B) {
153
log_debug("Found compress-based stream");
161
if(buf_c[0] == 0x50 && buf_c[1] == 0x4B && buf_c[2] == 0x03 && buf_c[3] == 0x04)
163
log_debug("Found zip-based stream");
168
return AG_NO_COMPRESSION;