Root/lib/decompress_inflate.c

1#ifdef STATIC
2/* Pre-boot environment: included */
3
4/* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots
5 * errors about console_printk etc... on ARM */
6#define _LINUX_KERNEL_H
7
8#include "zlib_inflate/inftrees.c"
9#include "zlib_inflate/inffast.c"
10#include "zlib_inflate/inflate.c"
11
12#else /* STATIC */
13/* initramfs et al: linked */
14
15#include <linux/zutil.h>
16
17#include "zlib_inflate/inftrees.h"
18#include "zlib_inflate/inffast.h"
19#include "zlib_inflate/inflate.h"
20
21#include "zlib_inflate/infutil.h"
22#include <linux/slab.h>
23
24#endif /* STATIC */
25
26#include <linux/decompress/mm.h>
27
28#define GZIP_IOBUF_SIZE (16*1024)
29
30static int nofill(void *buffer, unsigned int len)
31{
32    return -1;
33}
34
35/* Included from initramfs et al code */
36STATIC int INIT gunzip(unsigned char *buf, int len,
37               int(*fill)(void*, unsigned int),
38               int(*flush)(void*, unsigned int),
39               unsigned char *out_buf,
40               int *pos,
41               void(*error_fn)(char *x)) {
42    u8 *zbuf;
43    struct z_stream_s *strm;
44    int rc;
45    size_t out_len;
46
47    set_error_fn(error_fn);
48    rc = -1;
49    if (flush) {
50        out_len = 0x8000; /* 32 K */
51        out_buf = malloc(out_len);
52    } else {
53        out_len = 0x7fffffff; /* no limit */
54    }
55    if (!out_buf) {
56        error("Out of memory while allocating output buffer");
57        goto gunzip_nomem1;
58    }
59
60    if (buf)
61        zbuf = buf;
62    else {
63        zbuf = malloc(GZIP_IOBUF_SIZE);
64        len = 0;
65    }
66    if (!zbuf) {
67        error("Out of memory while allocating input buffer");
68        goto gunzip_nomem2;
69    }
70
71    strm = malloc(sizeof(*strm));
72    if (strm == NULL) {
73        error("Out of memory while allocating z_stream");
74        goto gunzip_nomem3;
75    }
76
77    strm->workspace = malloc(flush ? zlib_inflate_workspacesize() :
78                 sizeof(struct inflate_state));
79    if (strm->workspace == NULL) {
80        error("Out of memory while allocating workspace");
81        goto gunzip_nomem4;
82    }
83
84    if (!fill)
85        fill = nofill;
86
87    if (len == 0)
88        len = fill(zbuf, GZIP_IOBUF_SIZE);
89
90    /* verify the gzip header */
91    if (len < 10 ||
92       zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) {
93        if (pos)
94            *pos = 0;
95        error("Not a gzip file");
96        goto gunzip_5;
97    }
98
99    /* skip over gzip header (1f,8b,08... 10 bytes total +
100     * possible asciz filename)
101     */
102    strm->next_in = zbuf + 10;
103    /* skip over asciz filename */
104    if (zbuf[3] & 0x8) {
105        while (strm->next_in[0])
106            strm->next_in++;
107        strm->next_in++;
108    }
109    strm->avail_in = len - (strm->next_in - zbuf);
110
111    strm->next_out = out_buf;
112    strm->avail_out = out_len;
113
114    rc = zlib_inflateInit2(strm, -MAX_WBITS);
115
116    if (!flush) {
117        WS(strm)->inflate_state.wsize = 0;
118        WS(strm)->inflate_state.window = NULL;
119    }
120
121    while (rc == Z_OK) {
122        if (strm->avail_in == 0) {
123            /* TODO: handle case where both pos and fill are set */
124            len = fill(zbuf, GZIP_IOBUF_SIZE);
125            if (len < 0) {
126                rc = -1;
127                error("read error");
128                break;
129            }
130            strm->next_in = zbuf;
131            strm->avail_in = len;
132        }
133        rc = zlib_inflate(strm, 0);
134
135        /* Write any data generated */
136        if (flush && strm->next_out > out_buf) {
137            int l = strm->next_out - out_buf;
138            if (l != flush(out_buf, l)) {
139                rc = -1;
140                error("write error");
141                break;
142            }
143            strm->next_out = out_buf;
144            strm->avail_out = out_len;
145        }
146
147        /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
148        if (rc == Z_STREAM_END) {
149            rc = 0;
150            break;
151        } else if (rc != Z_OK) {
152            error("uncompression error");
153            rc = -1;
154        }
155    }
156
157    zlib_inflateEnd(strm);
158    if (pos)
159        /* add + 8 to skip over trailer */
160        *pos = strm->next_in - zbuf+8;
161
162gunzip_5:
163    free(strm->workspace);
164gunzip_nomem4:
165    free(strm);
166gunzip_nomem3:
167    if (!buf)
168        free(zbuf);
169gunzip_nomem2:
170    if (flush)
171        free(out_buf);
172gunzip_nomem1:
173    return rc; /* returns Z_OK (0) if successful */
174}
175
176#define decompress gunzip
177

Archive Download this file



interactive