Blame view

lib/decompress_inflate.c 4.42 KB
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
1
  #ifdef STATIC
2d3862d26   Yinghai Lu   lib/decompressors...
2
  #define PREBOOT
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  /* Pre-boot environment: included */
  
  /* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots
   * errors about console_printk etc... on ARM */
  #define _LINUX_KERNEL_H
  
  #include "zlib_inflate/inftrees.c"
  #include "zlib_inflate/inffast.c"
  #include "zlib_inflate/inflate.c"
  
  #else /* STATIC */
  /* initramfs et al: linked */
  
  #include <linux/zutil.h>
  
  #include "zlib_inflate/inftrees.h"
  #include "zlib_inflate/inffast.h"
  #include "zlib_inflate/inflate.h"
  
  #include "zlib_inflate/infutil.h"
af661e836   Rashika Kheria   lib/decompress_in...
23
  #include <linux/decompress/inflate.h>
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
24
25
26
27
  
  #endif /* STATIC */
  
  #include <linux/decompress/mm.h>
daeb6b6fb   Phillip Lougher   bzip2/lzma/gzip: ...
28
  #define GZIP_IOBUF_SIZE (16*1024)
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
29

d97b07c54   Yinghai Lu   initramfs: suppor...
30
  static long INIT nofill(void *buffer, unsigned long len)
6a8811629   Phillip Lougher   lzma/gzip: fix po...
31
32
33
  {
  	return -1;
  }
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
34
  /* Included from initramfs et al code */
2d3862d26   Yinghai Lu   lib/decompressors...
35
  STATIC int INIT __gunzip(unsigned char *buf, long len,
d97b07c54   Yinghai Lu   initramfs: suppor...
36
37
  		       long (*fill)(void*, unsigned long),
  		       long (*flush)(void*, unsigned long),
2d3862d26   Yinghai Lu   lib/decompressors...
38
  		       unsigned char *out_buf, long out_len,
d97b07c54   Yinghai Lu   initramfs: suppor...
39
  		       long *pos,
93685ad24   Lasse Collin   Decompressors: ge...
40
  		       void(*error)(char *x)) {
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
41
42
43
  	u8 *zbuf;
  	struct z_stream_s *strm;
  	int rc;
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
44

bc22c17e1   Alain Knaff   bzip2/lzma: libra...
45
46
  	rc = -1;
  	if (flush) {
5619448fc   H. Peter Anvin   bzip2/lzma: fix c...
47
  		out_len = 0x8000; /* 32 K */
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
48
49
  		out_buf = malloc(out_len);
  	} else {
2d3862d26   Yinghai Lu   lib/decompressors...
50
51
  		if (!out_len)
  			out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
52
53
54
55
56
57
58
59
60
  	}
  	if (!out_buf) {
  		error("Out of memory while allocating output buffer");
  		goto gunzip_nomem1;
  	}
  
  	if (buf)
  		zbuf = buf;
  	else {
daeb6b6fb   Phillip Lougher   bzip2/lzma/gzip: ...
61
  		zbuf = malloc(GZIP_IOBUF_SIZE);
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  		len = 0;
  	}
  	if (!zbuf) {
  		error("Out of memory while allocating input buffer");
  		goto gunzip_nomem2;
  	}
  
  	strm = malloc(sizeof(*strm));
  	if (strm == NULL) {
  		error("Out of memory while allocating z_stream");
  		goto gunzip_nomem3;
  	}
  
  	strm->workspace = malloc(flush ? zlib_inflate_workspacesize() :
  				 sizeof(struct inflate_state));
  	if (strm->workspace == NULL) {
  		error("Out of memory while allocating workspace");
  		goto gunzip_nomem4;
  	}
6a8811629   Phillip Lougher   lzma/gzip: fix po...
81
82
  	if (!fill)
  		fill = nofill;
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
83
  	if (len == 0)
daeb6b6fb   Phillip Lougher   bzip2/lzma/gzip: ...
84
  		len = fill(zbuf, GZIP_IOBUF_SIZE);
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  
  	/* verify the gzip header */
  	if (len < 10 ||
  	   zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) {
  		if (pos)
  			*pos = 0;
  		error("Not a gzip file");
  		goto gunzip_5;
  	}
  
  	/* skip over gzip header (1f,8b,08... 10 bytes total +
  	 * possible asciz filename)
  	 */
  	strm->next_in = zbuf + 10;
1da914e06   Lasse Collin   decompressors: ch...
99
  	strm->avail_in = len - 10;
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
100
101
  	/* skip over asciz filename */
  	if (zbuf[3] & 0x8) {
1da914e06   Lasse Collin   decompressors: ch...
102
103
104
105
106
107
108
109
110
111
112
113
  		do {
  			/*
  			 * If the filename doesn't fit into the buffer,
  			 * the file is very probably corrupt. Don't try
  			 * to read more data.
  			 */
  			if (strm->avail_in == 0) {
  				error("header error");
  				goto gunzip_5;
  			}
  			--strm->avail_in;
  		} while (*strm->next_in++);
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
114
  	}
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  
  	strm->next_out = out_buf;
  	strm->avail_out = out_len;
  
  	rc = zlib_inflateInit2(strm, -MAX_WBITS);
  
  	if (!flush) {
  		WS(strm)->inflate_state.wsize = 0;
  		WS(strm)->inflate_state.window = NULL;
  	}
  
  	while (rc == Z_OK) {
  		if (strm->avail_in == 0) {
  			/* TODO: handle case where both pos and fill are set */
daeb6b6fb   Phillip Lougher   bzip2/lzma/gzip: ...
129
  			len = fill(zbuf, GZIP_IOBUF_SIZE);
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
130
131
132
133
134
135
136
137
138
139
140
141
  			if (len < 0) {
  				rc = -1;
  				error("read error");
  				break;
  			}
  			strm->next_in = zbuf;
  			strm->avail_in = len;
  		}
  		rc = zlib_inflate(strm, 0);
  
  		/* Write any data generated */
  		if (flush && strm->next_out > out_buf) {
d97b07c54   Yinghai Lu   initramfs: suppor...
142
  			long l = strm->next_out - out_buf;
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  			if (l != flush(out_buf, l)) {
  				rc = -1;
  				error("write error");
  				break;
  			}
  			strm->next_out = out_buf;
  			strm->avail_out = out_len;
  		}
  
  		/* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
  		if (rc == Z_STREAM_END) {
  			rc = 0;
  			break;
  		} else if (rc != Z_OK) {
  			error("uncompression error");
  			rc = -1;
  		}
  	}
  
  	zlib_inflateEnd(strm);
  	if (pos)
  		/* add + 8 to skip over trailer */
  		*pos = strm->next_in - zbuf+8;
  
  gunzip_5:
  	free(strm->workspace);
  gunzip_nomem4:
  	free(strm);
  gunzip_nomem3:
  	if (!buf)
  		free(zbuf);
  gunzip_nomem2:
  	if (flush)
  		free(out_buf);
  gunzip_nomem1:
  	return rc; /* returns Z_OK (0) if successful */
  }
2d3862d26   Yinghai Lu   lib/decompressors...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
  #ifndef PREBOOT
  STATIC int INIT gunzip(unsigned char *buf, long len,
  		       long (*fill)(void*, unsigned long),
  		       long (*flush)(void*, unsigned long),
  		       unsigned char *out_buf,
  		       long *pos,
  		       void (*error)(char *x))
  {
  	return __gunzip(buf, len, fill, flush, out_buf, 0, pos, error);
  }
  #else
  STATIC int INIT __decompress(unsigned char *buf, long len,
  			   long (*fill)(void*, unsigned long),
  			   long (*flush)(void*, unsigned long),
  			   unsigned char *out_buf, long out_len,
  			   long *pos,
  			   void (*error)(char *x))
  {
  	return __gunzip(buf, len, fill, flush, out_buf, out_len, pos, error);
  }
  #endif