1 /* $NetBSD: decompress.c,v 1.3 2009/08/02 17:56:45 joerg Exp $ */
4 * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #include <sys/cdefs.h>
42 __RCSID("$NetBSD: decompress.c,v 1.3 2009/08/02 17:56:45 joerg Exp $");
48 decompress_buffer(const char *input
, size_t input_len
, char **output
,
67 decompress_bzip2(const char *in
, size_t in_len
, char **out
, size_t *out_len
)
70 size_t output_produced
;
72 if (in_len
< SSIZE_MAX
/ 10)
73 *out_len
= in_len
* 10;
76 *out
= xmalloc(*out_len
+ 1);
78 stream
.next_in
= __UNCONST(in
);
79 stream
.avail_in
= in_len
;
80 stream
.next_out
= *out
;
81 stream
.avail_out
= *out_len
;
83 stream
.bzalloc
= NULL
;
87 if (BZ2_bzDecompressInit(&stream
, 0, 0) != BZ_OK
)
88 errx(EXIT_FAILURE
, "BZ2_bzDecompressInit failed");
91 switch (BZ2_bzDecompress(&stream
)) {
93 if (BZ2_bzDecompressEnd(&stream
) != Z_OK
)
94 errx(EXIT_FAILURE
, "inflateEnd failed");
95 output_produced
= *out_len
- stream
.avail_out
;
96 *out
= xrealloc(*out
, output_produced
+ 1);
97 *out_len
= output_produced
;
98 (*out
)[*out_len
] = '\0';
101 output_produced
= *out_len
- stream
.avail_out
;
102 if (*out_len
<= SSIZE_MAX
/ 2)
105 errx(EXIT_FAILURE
, "input too large");
106 *out
= xrealloc(*out
, *out_len
+ 1);
107 stream
.next_out
= *out
+ output_produced
;
108 stream
.avail_out
= *out_len
- output_produced
;
111 errx(EXIT_FAILURE
, "inflate failed");
117 decompress_zlib(const char *in
, size_t in_len
, char **out
, size_t *out_len
)
120 size_t output_produced
;
122 if (in_len
< SSIZE_MAX
/ 10)
123 *out_len
= in_len
* 10;
126 *out
= xmalloc(*out_len
+ 1);
128 stream
.next_in
= __UNCONST(in
);
129 stream
.avail_in
= in_len
;
130 stream
.next_out
= (unsigned char *)*out
;
131 stream
.avail_out
= *out_len
;
133 stream
.zalloc
= Z_NULL
;
134 stream
.zfree
= Z_NULL
;
135 stream
.opaque
= NULL
;
137 if (inflateInit2(&stream
, 47) != Z_OK
)
138 errx(EXIT_FAILURE
, "inflateInit failed");
141 switch (inflate(&stream
, Z_FINISH
)) {
143 if (inflateEnd(&stream
) != Z_OK
)
144 errx(EXIT_FAILURE
, "inflateEnd failed");
145 output_produced
= *out_len
- stream
.avail_out
;
146 *out
= xrealloc(*out
, output_produced
+ 1);
147 *out_len
= output_produced
;
148 (*out
)[*out_len
] = '\0';
151 output_produced
= *out_len
- stream
.avail_out
;
152 if (*out_len
< SSIZE_MAX
/ 2)
154 else if (*out_len
== SSIZE_MAX
- 1)
155 errx(EXIT_FAILURE
, "input too large");
157 *out_len
= SSIZE_MAX
- 1;
158 *out
= xrealloc(*out
, *out_len
+ 1);
159 stream
.next_out
= (unsigned char *)*out
+ output_produced
;
160 stream
.avail_out
= *out_len
- output_produced
;
163 errx(EXIT_FAILURE
, "inflate failed");
169 decompress_buffer(const char *input
, size_t input_len
, char **output
,
174 if (input
[0] == 'B' && input
[1] == 'Z' && input
[2] == 'h' &&
175 input
[3] >= '1' && input
[3] <= '9') {
177 decompress_bzip2(input
, input_len
, output
, output_len
);
178 } else if (input
[0] == 037 && (unsigned char)input
[1] == 139 &&
179 input
[2] == 8 && (input
[3] & 0xe0) == 0) {
180 /* gzip header with Deflate method */
181 decompress_zlib(input
, input_len
, output
, output_len
);
182 } else /* plain text */
186 #endif /* BOOTSTRAP */