~ubuntu-branches/ubuntu/vivid/silversearcher-ag/vivid-proposed

« back to all changes in this revision

Viewing changes to src/decompress.c

  • Committer: Package Import Robot
  • Author(s): Hajime Mizuno
  • Date: 2013-02-13 20:31:42 UTC
  • Revision ID: package-import@ubuntu.com-20130213203142-drq8ipcuy51r5kyp
Tags: upstream-0.0~20130213+git55028b4e
ImportĀ upstreamĀ versionĀ 0.0~20130213+git55028b4e

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <zlib.h>
 
2
 
 
3
#include "decompress.h"
 
4
 
 
5
/* Code in decompress_zlib from
 
6
 *
 
7
 * https://raw.github.com/madler/zlib/master/examples/zpipe.c
 
8
 *
 
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 
 
12
 */
 
13
 
 
14
 
 
15
static void* decompress_zlib(const void* buf, const int buf_len,
 
16
                             const char* dir_full_path, int* new_buf_len) {
 
17
    int ret = 0;
 
18
    unsigned char* result = NULL;
 
19
    size_t result_size = 0;
 
20
    size_t pagesize = 0;
 
21
    z_stream stream;
 
22
 
 
23
    log_debug("Decompressing zlib file %s", dir_full_path);
 
24
 
 
25
    /* allocate inflate state */
 
26
    stream.zalloc = Z_NULL;
 
27
    stream.zfree = Z_NULL;
 
28
    stream.opaque = Z_NULL;
 
29
    stream.avail_in = 0;
 
30
    stream.next_in = Z_NULL;
 
31
 
 
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);
 
35
        goto error_out;
 
36
    }
 
37
 
 
38
    stream.avail_in = buf_len;
 
39
    stream.next_in = (void*)buf;
 
40
 
 
41
    pagesize = getpagesize();
 
42
    result_size = ((buf_len + pagesize - 1) & ~(pagesize - 1));
 
43
    do {
 
44
        do {
 
45
            /* Double the buffer size and realloc */
 
46
            result_size *= 2;
 
47
            result = (unsigned char*)realloc(result, result_size * sizeof(unsigned char));
 
48
            if(result == NULL) {
 
49
                log_err("Unable to allocate %d bytes to decompress file %s", result_size * sizeof(unsigned char), dir_full_path);
 
50
                inflateEnd(&stream);
 
51
                goto error_out;
 
52
            }
 
53
 
 
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);
 
58
            switch(ret) {
 
59
                case Z_STREAM_ERROR: {
 
60
                    log_err("Found stream error while decompressing zlib stream: %s", stream.msg);
 
61
                    inflateEnd(&stream);
 
62
                    goto error_out;
 
63
                }
 
64
                case Z_NEED_DICT:
 
65
                case Z_DATA_ERROR:
 
66
                case Z_MEM_ERROR: {
 
67
                    log_err("Found mem/data error while decompressing zlib stream: %s", stream.msg);
 
68
                    inflateEnd(&stream);
 
69
                    goto error_out;
 
70
                }
 
71
            }
 
72
        } while(stream.avail_out == 0);
 
73
    } while(ret == Z_OK);
 
74
 
 
75
    *new_buf_len = stream.total_out;
 
76
    inflateEnd(&stream);
 
77
 
 
78
    if(ret == Z_STREAM_END) {
 
79
        return result;
 
80
    }
 
81
 
 
82
error_out:
 
83
    *new_buf_len = 0;
 
84
    return NULL;
 
85
}
 
86
 
 
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);
 
91
    *new_buf_len = 0;
 
92
    return NULL;
 
93
}
 
94
 
 
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);
 
99
    *new_buf_len = 0;
 
100
    return NULL;
 
101
}
 
102
 
 
103
 
 
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) {
 
107
 
 
108
    switch(zip_type) {
 
109
        case AG_GZIP:
 
110
             return decompress_zlib(buf, buf_len, dir_full_path, new_buf_len);
 
111
        case AG_COMPRESS:
 
112
             return decompress_lwz(buf, buf_len, dir_full_path, new_buf_len);
 
113
        case AG_ZIP:
 
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);
 
117
            break;
 
118
        default:
 
119
            log_err("Unsupported compression type: %d", zip_type);
 
120
    }
 
121
 
 
122
    *new_buf_len = 0;
 
123
    return NULL;
 
124
}
 
125
 
 
126
 
 
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) {
 
129
    /* Zip magic numbers
 
130
     * compressed file: { 0x1F, 0x9B }
 
131
     * http://en.wikipedia.org/wiki/Compress
 
132
     * 
 
133
     * gzip file:       { 0x1F, 0x8B }
 
134
     * http://www.gzip.org/zlib/rfc-gzip.html#file-format
 
135
     *
 
136
     * zip file:        { 0x50, 0x4B, 0x03, 0x04 }
 
137
     * http://www.pkware.com/documents/casestudies/APPNOTE.TXT (Section 4.3)
 
138
     */ 
 
139
 
 
140
    const unsigned char *buf_c = buf;
 
141
 
 
142
    if(buf_len == 0) {
 
143
        return AG_NO_COMPRESSION;
 
144
    }
 
145
 
 
146
    /* Check for gzip & compress */
 
147
    if(buf_len >= 2) {
 
148
        if(buf_c[0] == 0x1F) {
 
149
            if(buf_c[1] == 0x8B) {
 
150
                log_debug("Found gzip-based stream");
 
151
                return AG_GZIP;
 
152
            } else if(buf_c[1] == 0x9B) {
 
153
                log_debug("Found compress-based stream");
 
154
                return AG_COMPRESS;
 
155
            }
 
156
        }
 
157
    }
 
158
 
 
159
    /* Check for zip */
 
160
    if(buf_len >= 4) {
 
161
        if(buf_c[0] == 0x50 && buf_c[1] == 0x4B && buf_c[2] == 0x03 && buf_c[3] == 0x04)
 
162
        {
 
163
            log_debug("Found zip-based stream");
 
164
            return AG_ZIP;
 
165
        }
 
166
    }
 
167
 
 
168
    return AG_NO_COMPRESSION;
 
169
}
 
170