Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/lib/decompress_inflate.c
10811 views
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
23
#endif /* STATIC */
24
25
#include <linux/decompress/mm.h>
26
27
#define GZIP_IOBUF_SIZE (16*1024)
28
29
static int INIT nofill(void *buffer, unsigned int len)
30
{
31
return -1;
32
}
33
34
/* Included from initramfs et al code */
35
STATIC int INIT gunzip(unsigned char *buf, int len,
36
int(*fill)(void*, unsigned int),
37
int(*flush)(void*, unsigned int),
38
unsigned char *out_buf,
39
int *pos,
40
void(*error)(char *x)) {
41
u8 *zbuf;
42
struct z_stream_s *strm;
43
int rc;
44
size_t out_len;
45
46
rc = -1;
47
if (flush) {
48
out_len = 0x8000; /* 32 K */
49
out_buf = malloc(out_len);
50
} else {
51
out_len = 0x7fffffff; /* no limit */
52
}
53
if (!out_buf) {
54
error("Out of memory while allocating output buffer");
55
goto gunzip_nomem1;
56
}
57
58
if (buf)
59
zbuf = buf;
60
else {
61
zbuf = malloc(GZIP_IOBUF_SIZE);
62
len = 0;
63
}
64
if (!zbuf) {
65
error("Out of memory while allocating input buffer");
66
goto gunzip_nomem2;
67
}
68
69
strm = malloc(sizeof(*strm));
70
if (strm == NULL) {
71
error("Out of memory while allocating z_stream");
72
goto gunzip_nomem3;
73
}
74
75
strm->workspace = malloc(flush ? zlib_inflate_workspacesize() :
76
sizeof(struct inflate_state));
77
if (strm->workspace == NULL) {
78
error("Out of memory while allocating workspace");
79
goto gunzip_nomem4;
80
}
81
82
if (!fill)
83
fill = nofill;
84
85
if (len == 0)
86
len = fill(zbuf, GZIP_IOBUF_SIZE);
87
88
/* verify the gzip header */
89
if (len < 10 ||
90
zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) {
91
if (pos)
92
*pos = 0;
93
error("Not a gzip file");
94
goto gunzip_5;
95
}
96
97
/* skip over gzip header (1f,8b,08... 10 bytes total +
98
* possible asciz filename)
99
*/
100
strm->next_in = zbuf + 10;
101
strm->avail_in = len - 10;
102
/* skip over asciz filename */
103
if (zbuf[3] & 0x8) {
104
do {
105
/*
106
* If the filename doesn't fit into the buffer,
107
* the file is very probably corrupt. Don't try
108
* to read more data.
109
*/
110
if (strm->avail_in == 0) {
111
error("header error");
112
goto gunzip_5;
113
}
114
--strm->avail_in;
115
} while (*strm->next_in++);
116
}
117
118
strm->next_out = out_buf;
119
strm->avail_out = out_len;
120
121
rc = zlib_inflateInit2(strm, -MAX_WBITS);
122
123
if (!flush) {
124
WS(strm)->inflate_state.wsize = 0;
125
WS(strm)->inflate_state.window = NULL;
126
}
127
128
while (rc == Z_OK) {
129
if (strm->avail_in == 0) {
130
/* TODO: handle case where both pos and fill are set */
131
len = fill(zbuf, GZIP_IOBUF_SIZE);
132
if (len < 0) {
133
rc = -1;
134
error("read error");
135
break;
136
}
137
strm->next_in = zbuf;
138
strm->avail_in = len;
139
}
140
rc = zlib_inflate(strm, 0);
141
142
/* Write any data generated */
143
if (flush && strm->next_out > out_buf) {
144
int l = strm->next_out - out_buf;
145
if (l != flush(out_buf, l)) {
146
rc = -1;
147
error("write error");
148
break;
149
}
150
strm->next_out = out_buf;
151
strm->avail_out = out_len;
152
}
153
154
/* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
155
if (rc == Z_STREAM_END) {
156
rc = 0;
157
break;
158
} else if (rc != Z_OK) {
159
error("uncompression error");
160
rc = -1;
161
}
162
}
163
164
zlib_inflateEnd(strm);
165
if (pos)
166
/* add + 8 to skip over trailer */
167
*pos = strm->next_in - zbuf+8;
168
169
gunzip_5:
170
free(strm->workspace);
171
gunzip_nomem4:
172
free(strm);
173
gunzip_nomem3:
174
if (!buf)
175
free(zbuf);
176
gunzip_nomem2:
177
if (flush)
178
free(out_buf);
179
gunzip_nomem1:
180
return rc; /* returns Z_OK (0) if successful */
181
}
182
183
#define decompress gunzip
184
185