Blame view

lib/decompress_inflate.c 4.76 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
2
  #ifdef STATIC
2d3862d26   Yinghai Lu   lib/decompressors...
3
  #define PREBOOT
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
4
5
6
7
8
9
10
11
12
  /* 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"
126196100   Mikhail Zaslonko   lib/zlib: add s39...
13
14
15
16
  #ifdef CONFIG_ZLIB_DFLTCC
  #include "zlib_dfltcc/dfltcc.c"
  #include "zlib_dfltcc/dfltcc_inflate.c"
  #endif
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
17
18
19
20
21
22
23
24
25
26
27
  
  #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...
28
  #include <linux/decompress/inflate.h>
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
29
30
31
32
  
  #endif /* STATIC */
  
  #include <linux/decompress/mm.h>
daeb6b6fb   Phillip Lougher   bzip2/lzma/gzip: ...
33
  #define GZIP_IOBUF_SIZE (16*1024)
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
34

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

bc22c17e1   Alain Knaff   bzip2/lzma: libra...
50
51
  	rc = -1;
  	if (flush) {
5619448fc   H. Peter Anvin   bzip2/lzma: fix c...
52
  		out_len = 0x8000; /* 32 K */
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
53
54
  		out_buf = malloc(out_len);
  	} else {
2d3862d26   Yinghai Lu   lib/decompressors...
55
56
  		if (!out_len)
  			out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
57
58
59
60
61
62
63
64
65
  	}
  	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: ...
66
  		zbuf = malloc(GZIP_IOBUF_SIZE);
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
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() :
126196100   Mikhail Zaslonko   lib/zlib: add s39...
81
82
83
84
  #ifdef CONFIG_ZLIB_DFLTCC
  	/* Always allocate the full workspace for DFLTCC */
  				 zlib_inflate_workspacesize());
  #else
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
85
  				 sizeof(struct inflate_state));
126196100   Mikhail Zaslonko   lib/zlib: add s39...
86
  #endif
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
87
88
89
90
  	if (strm->workspace == NULL) {
  		error("Out of memory while allocating workspace");
  		goto gunzip_nomem4;
  	}
6a8811629   Phillip Lougher   lzma/gzip: fix po...
91
92
  	if (!fill)
  		fill = nofill;
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
93
  	if (len == 0)
daeb6b6fb   Phillip Lougher   bzip2/lzma/gzip: ...
94
  		len = fill(zbuf, GZIP_IOBUF_SIZE);
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  
  	/* 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...
109
  	strm->avail_in = len - 10;
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
110
111
  	/* skip over asciz filename */
  	if (zbuf[3] & 0x8) {
1da914e06   Lasse Collin   decompressors: ch...
112
113
114
115
116
117
118
119
120
121
122
123
  		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...
124
  	}
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
125
126
127
128
129
  
  	strm->next_out = out_buf;
  	strm->avail_out = out_len;
  
  	rc = zlib_inflateInit2(strm, -MAX_WBITS);
126196100   Mikhail Zaslonko   lib/zlib: add s39...
130
131
132
  #ifdef CONFIG_ZLIB_DFLTCC
  	/* Always keep the window for DFLTCC */
  #else
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
133
134
135
136
  	if (!flush) {
  		WS(strm)->inflate_state.wsize = 0;
  		WS(strm)->inflate_state.window = NULL;
  	}
126196100   Mikhail Zaslonko   lib/zlib: add s39...
137
  #endif
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
138
139
140
141
  
  	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: ...
142
  			len = fill(zbuf, GZIP_IOBUF_SIZE);
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
143
144
145
146
147
148
149
150
151
152
153
154
  			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...
155
  			long l = strm->next_out - out_buf;
bc22c17e1   Alain Knaff   bzip2/lzma: libra...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
  			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...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
  #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