Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / bsd / pkg_install / dist / lib / decompress.c
blob31500f2580d06bf8ac614d5f3d6ce419d6265216
1 /* $NetBSD: decompress.c,v 1.3 2009/08/02 17:56:45 joerg Exp $ */
3 /*-
4 * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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
16 * distribution.
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
29 * SUCH DAMAGE.
32 #if HAVE_CONFIG_H
33 #include "config.h"
34 #endif
36 #include <nbcompat.h>
38 #if HAVE_SYS_CDEFS_H
39 #include <sys/cdefs.h>
40 #endif
42 __RCSID("$NetBSD: decompress.c,v 1.3 2009/08/02 17:56:45 joerg Exp $");
44 #ifdef BOOTSTRAP
45 #include "lib.h"
47 int
48 decompress_buffer(const char *input, size_t input_len, char **output,
49 size_t *output_len)
51 return 0;
54 #else
56 #include <bzlib.h>
57 #if HAVE_ERR_H
58 #include <err.h>
59 #endif
60 #include <limits.h>
61 #include <stdlib.h>
62 #include <zlib.h>
64 #include "lib.h"
66 static void
67 decompress_bzip2(const char *in, size_t in_len, char **out, size_t *out_len)
69 bz_stream stream;
70 size_t output_produced;
72 if (in_len < SSIZE_MAX / 10)
73 *out_len = in_len * 10;
74 else
75 *out_len = in_len;
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;
82 output_produced = 0;
83 stream.bzalloc = NULL;
84 stream.bzfree = NULL;
85 stream.opaque = NULL;
87 if (BZ2_bzDecompressInit(&stream, 0, 0) != BZ_OK)
88 errx(EXIT_FAILURE, "BZ2_bzDecompressInit failed");
90 for (;;) {
91 switch (BZ2_bzDecompress(&stream)) {
92 case BZ_STREAM_END:
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';
99 return;
100 case BZ_OK:
101 output_produced = *out_len - stream.avail_out;
102 if (*out_len <= SSIZE_MAX / 2)
103 *out_len *= 2;
104 else
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;
109 break;
110 default:
111 errx(EXIT_FAILURE, "inflate failed");
116 static void
117 decompress_zlib(const char *in, size_t in_len, char **out, size_t *out_len)
119 z_stream stream;
120 size_t output_produced;
122 if (in_len < SSIZE_MAX / 10)
123 *out_len = in_len * 10;
124 else
125 *out_len = in_len;
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;
132 output_produced = 0;
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");
140 for (;;) {
141 switch (inflate(&stream, Z_FINISH)) {
142 case Z_STREAM_END:
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';
149 return;
150 case Z_OK:
151 output_produced = *out_len - stream.avail_out;
152 if (*out_len < SSIZE_MAX / 2)
153 *out_len *= 2;
154 else if (*out_len == SSIZE_MAX - 1)
155 errx(EXIT_FAILURE, "input too large");
156 else
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;
161 break;
162 default:
163 errx(EXIT_FAILURE, "inflate failed");
169 decompress_buffer(const char *input, size_t input_len, char **output,
170 size_t *output_len)
172 if (input_len < 4)
173 return 0;
174 if (input[0] == 'B' && input[1] == 'Z' && input[2] == 'h' &&
175 input[3] >= '1' && input[3] <= '9') {
176 /* Normal bzip2. */
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 */
183 return 0;
184 return 1;
186 #endif /* BOOTSTRAP */