xref: /minix3/usr.bin/gzip/unbzip2.c (revision 5a645f22a86f086849945a5dd6acbf59f38c913a)
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