1*5a645f22SBen Gras /* $NetBSD: unbzip2.c,v 1.13 2009/12/05 03:23:37 mrg Exp $ */
2*5a645f22SBen Gras
3*5a645f22SBen Gras /*-
4*5a645f22SBen Gras * Copyright (c) 2006 The NetBSD Foundation, Inc.
5*5a645f22SBen Gras * All rights reserved.
6*5a645f22SBen Gras *
7*5a645f22SBen Gras * This code is derived from software contributed to The NetBSD Foundation
8*5a645f22SBen Gras * by Simon Burge.
9*5a645f22SBen Gras *
10*5a645f22SBen Gras * Redistribution and use in source and binary forms, with or without
11*5a645f22SBen Gras * modification, are permitted provided that the following conditions
12*5a645f22SBen Gras * are met:
13*5a645f22SBen Gras * 1. Redistributions of source code must retain the above copyright
14*5a645f22SBen Gras * notice, this list of conditions and the following disclaimer.
15*5a645f22SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
16*5a645f22SBen Gras * notice, this list of conditions and the following disclaimer in the
17*5a645f22SBen Gras * documentation and/or other materials provided with the distribution.
18*5a645f22SBen Gras *
19*5a645f22SBen Gras * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*5a645f22SBen Gras * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*5a645f22SBen Gras * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*5a645f22SBen Gras * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*5a645f22SBen Gras * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*5a645f22SBen Gras * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*5a645f22SBen Gras * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*5a645f22SBen Gras * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*5a645f22SBen Gras * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*5a645f22SBen Gras * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*5a645f22SBen Gras * POSSIBILITY OF SUCH DAMAGE.
30*5a645f22SBen Gras */
31*5a645f22SBen Gras
32*5a645f22SBen Gras /* This file is #included by gzip.c */
33*5a645f22SBen Gras
34*5a645f22SBen Gras static off_t
unbzip2(int in,int out,char * pre,size_t prelen,off_t * bytes_in)35*5a645f22SBen Gras unbzip2(int in, int out, char *pre, size_t prelen, off_t *bytes_in)
36*5a645f22SBen Gras {
37*5a645f22SBen Gras int ret, end_of_file, cold = 0;
38*5a645f22SBen Gras off_t bytes_out = 0;
39*5a645f22SBen Gras bz_stream bzs;
40*5a645f22SBen Gras static char *inbuf, *outbuf;
41*5a645f22SBen Gras
42*5a645f22SBen Gras if (inbuf == NULL)
43*5a645f22SBen Gras inbuf = malloc(BUFLEN);
44*5a645f22SBen Gras if (outbuf == NULL)
45*5a645f22SBen Gras outbuf = malloc(BUFLEN);
46*5a645f22SBen Gras if (inbuf == NULL || outbuf == NULL)
47*5a645f22SBen Gras maybe_err("malloc");
48*5a645f22SBen Gras
49*5a645f22SBen Gras bzs.bzalloc = NULL;
50*5a645f22SBen Gras bzs.bzfree = NULL;
51*5a645f22SBen Gras bzs.opaque = NULL;
52*5a645f22SBen Gras
53*5a645f22SBen Gras end_of_file = 0;
54*5a645f22SBen Gras ret = BZ2_bzDecompressInit(&bzs, 0, 0);
55*5a645f22SBen Gras if (ret != BZ_OK)
56*5a645f22SBen Gras maybe_errx("bzip2 init");
57*5a645f22SBen Gras
58*5a645f22SBen Gras /* Prepend. */
59*5a645f22SBen Gras bzs.avail_in = prelen;
60*5a645f22SBen Gras bzs.next_in = pre;
61*5a645f22SBen Gras
62*5a645f22SBen Gras if (bytes_in)
63*5a645f22SBen Gras *bytes_in = prelen;
64*5a645f22SBen Gras
65*5a645f22SBen Gras while (ret == BZ_OK) {
66*5a645f22SBen Gras if (bzs.avail_in == 0 && !end_of_file) {
67*5a645f22SBen Gras ssize_t n;
68*5a645f22SBen Gras
69*5a645f22SBen Gras n = read(in, inbuf, BUFLEN);
70*5a645f22SBen Gras if (n < 0)
71*5a645f22SBen Gras maybe_err("read");
72*5a645f22SBen Gras if (n == 0)
73*5a645f22SBen Gras end_of_file = 1;
74*5a645f22SBen Gras bzs.next_in = inbuf;
75*5a645f22SBen Gras bzs.avail_in = n;
76*5a645f22SBen Gras if (bytes_in)
77*5a645f22SBen Gras *bytes_in += n;
78*5a645f22SBen Gras }
79*5a645f22SBen Gras
80*5a645f22SBen Gras bzs.next_out = outbuf;
81*5a645f22SBen Gras bzs.avail_out = BUFLEN;
82*5a645f22SBen Gras ret = BZ2_bzDecompress(&bzs);
83*5a645f22SBen Gras
84*5a645f22SBen Gras switch (ret) {
85*5a645f22SBen Gras case BZ_STREAM_END:
86*5a645f22SBen Gras case BZ_OK:
87*5a645f22SBen Gras if (ret == BZ_OK && end_of_file) {
88*5a645f22SBen Gras /*
89*5a645f22SBen Gras * If we hit this after a stream end, consider
90*5a645f22SBen Gras * it as the end of the whole file and don't
91*5a645f22SBen Gras * bail out.
92*5a645f22SBen Gras */
93*5a645f22SBen Gras if (cold == 1)
94*5a645f22SBen Gras ret = BZ_STREAM_END;
95*5a645f22SBen Gras else
96*5a645f22SBen Gras maybe_errx("truncated file");
97*5a645f22SBen Gras }
98*5a645f22SBen Gras cold = 0;
99*5a645f22SBen Gras if (!tflag && bzs.avail_out != BUFLEN) {
100*5a645f22SBen Gras ssize_t n;
101*5a645f22SBen Gras
102*5a645f22SBen Gras n = write(out, outbuf, BUFLEN - bzs.avail_out);
103*5a645f22SBen Gras if (n < 0)
104*5a645f22SBen Gras maybe_err("write");
105*5a645f22SBen Gras bytes_out += n;
106*5a645f22SBen Gras }
107*5a645f22SBen Gras if (ret == BZ_STREAM_END && !end_of_file) {
108*5a645f22SBen Gras if (BZ2_bzDecompressEnd(&bzs) != BZ_OK ||
109*5a645f22SBen Gras BZ2_bzDecompressInit(&bzs, 0, 0) != BZ_OK)
110*5a645f22SBen Gras maybe_errx("bzip2 re-init");
111*5a645f22SBen Gras cold = 1;
112*5a645f22SBen Gras ret = BZ_OK;
113*5a645f22SBen Gras }
114*5a645f22SBen Gras break;
115*5a645f22SBen Gras
116*5a645f22SBen Gras case BZ_DATA_ERROR:
117*5a645f22SBen Gras maybe_warnx("bzip2 data integrity error");
118*5a645f22SBen Gras break;
119*5a645f22SBen Gras
120*5a645f22SBen Gras case BZ_DATA_ERROR_MAGIC:
121*5a645f22SBen Gras maybe_warnx("bzip2 magic number error");
122*5a645f22SBen Gras break;
123*5a645f22SBen Gras
124*5a645f22SBen Gras case BZ_MEM_ERROR:
125*5a645f22SBen Gras maybe_warnx("bzip2 out of memory");
126*5a645f22SBen Gras break;
127*5a645f22SBen Gras
128*5a645f22SBen Gras default:
129*5a645f22SBen Gras maybe_warnx("unknown bzip2 error: %d", ret);
130*5a645f22SBen Gras break;
131*5a645f22SBen Gras }
132*5a645f22SBen Gras }
133*5a645f22SBen Gras
134*5a645f22SBen Gras if (ret != BZ_STREAM_END || BZ2_bzDecompressEnd(&bzs) != BZ_OK)
135*5a645f22SBen Gras return (-1);
136*5a645f22SBen Gras
137*5a645f22SBen Gras return (bytes_out);
138*5a645f22SBen Gras }
139