xref: /netbsd/usr.bin/gzip/unbzip2.c (revision 1be7cf88)
1*1be7cf88Smrg /*	$NetBSD: unbzip2.c,v 1.14 2017/08/04 07:27:08 mrg Exp $	*/
2bca6df8eSsimonb 
3bca6df8eSsimonb /*-
4bca6df8eSsimonb  * Copyright (c) 2006 The NetBSD Foundation, Inc.
5bca6df8eSsimonb  * All rights reserved.
6bca6df8eSsimonb  *
7bca6df8eSsimonb  * This code is derived from software contributed to The NetBSD Foundation
8bca6df8eSsimonb  * by Simon Burge.
9bca6df8eSsimonb  *
10bca6df8eSsimonb  * Redistribution and use in source and binary forms, with or without
11bca6df8eSsimonb  * modification, are permitted provided that the following conditions
12bca6df8eSsimonb  * are met:
13bca6df8eSsimonb  * 1. Redistributions of source code must retain the above copyright
14bca6df8eSsimonb  *    notice, this list of conditions and the following disclaimer.
15bca6df8eSsimonb  * 2. Redistributions in binary form must reproduce the above copyright
16bca6df8eSsimonb  *    notice, this list of conditions and the following disclaimer in the
17bca6df8eSsimonb  *    documentation and/or other materials provided with the distribution.
18bca6df8eSsimonb  *
19bca6df8eSsimonb  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20bca6df8eSsimonb  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21bca6df8eSsimonb  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22bca6df8eSsimonb  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23bca6df8eSsimonb  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24bca6df8eSsimonb  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25bca6df8eSsimonb  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26bca6df8eSsimonb  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27bca6df8eSsimonb  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28bca6df8eSsimonb  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29bca6df8eSsimonb  * POSSIBILITY OF SUCH DAMAGE.
30bca6df8eSsimonb  */
31ecadec7fSmrg 
32ecadec7fSmrg /* This file is #included by gzip.c */
33ecadec7fSmrg 
34ecadec7fSmrg static off_t
unbzip2(int in,int out,char * pre,size_t prelen,off_t * bytes_in)351d0e9794Smrg unbzip2(int in, int out, char *pre, size_t prelen, off_t *bytes_in)
36ecadec7fSmrg {
3759c18d14Smrg 	int		ret, end_of_file, cold = 0;
38ecadec7fSmrg 	off_t		bytes_out = 0;
39ff930808Smrg 	bz_stream	bzs;
40ff930808Smrg 	static char	*inbuf, *outbuf;
41ecadec7fSmrg 
42754b92f9Sdsl 	if (inbuf == NULL)
43754b92f9Sdsl 		inbuf = malloc(BUFLEN);
44754b92f9Sdsl 	if (outbuf == NULL)
45754b92f9Sdsl 		outbuf = malloc(BUFLEN);
46754b92f9Sdsl 	if (inbuf == NULL || outbuf == NULL)
472d5e05afSmrg 	        maybe_err("malloc");
48ecadec7fSmrg 
49ff930808Smrg 	bzs.bzalloc = NULL;
50ff930808Smrg 	bzs.bzfree = NULL;
51ff930808Smrg 	bzs.opaque = NULL;
52ecadec7fSmrg 
53ff930808Smrg 	end_of_file = 0;
54ff930808Smrg 	ret = BZ2_bzDecompressInit(&bzs, 0, 0);
55ff930808Smrg 	if (ret != BZ_OK)
562d5e05afSmrg 	        maybe_errx("bzip2 init");
57ecadec7fSmrg 
581d0e9794Smrg 	/* Prepend. */
591d0e9794Smrg 	bzs.avail_in = prelen;
601d0e9794Smrg 	bzs.next_in = pre;
611d0e9794Smrg 
621d0e9794Smrg 	if (bytes_in)
631d0e9794Smrg 		*bytes_in = prelen;
64ecadec7fSmrg 
65628b55bbSmrg 	while (ret == BZ_OK) {
66*1be7cf88Smrg 		check_siginfo();
67ff930808Smrg 	        if (bzs.avail_in == 0 && !end_of_file) {
685c0ab9e0Smrg 			ssize_t	n;
695c0ab9e0Smrg 
701d0e9794Smrg 	                n = read(in, inbuf, BUFLEN);
71ff930808Smrg 	                if (n < 0)
722d5e05afSmrg 	                        maybe_err("read");
73ff930808Smrg 	                if (n == 0)
74ff930808Smrg 	                        end_of_file = 1;
75*1be7cf88Smrg 			infile_newdata(n);
76ff930808Smrg 	                bzs.next_in = inbuf;
77ff930808Smrg 	                bzs.avail_in = n;
781d0e9794Smrg 			if (bytes_in)
791d0e9794Smrg 				*bytes_in += n;
801d0e9794Smrg 	        }
81ff930808Smrg 
82ff930808Smrg 	        bzs.next_out = outbuf;
831d0e9794Smrg 	        bzs.avail_out = BUFLEN;
84ff930808Smrg 	        ret = BZ2_bzDecompress(&bzs);
85ff930808Smrg 
86ff930808Smrg 	        switch (ret) {
87ff930808Smrg 	        case BZ_STREAM_END:
88ff930808Smrg 	        case BZ_OK:
8959c18d14Smrg 	                if (ret == BZ_OK && end_of_file) {
9059c18d14Smrg 				/*
9159c18d14Smrg 				 * If we hit this after a stream end, consider
9259c18d14Smrg 				 * it as the end of the whole file and don't
9359c18d14Smrg 				 * bail out.
9459c18d14Smrg 				 */
9559c18d14Smrg 				if (cold == 1)
9659c18d14Smrg 					ret = BZ_STREAM_END;
9759c18d14Smrg 				else
9859c18d14Smrg 					maybe_errx("truncated file");
9959c18d14Smrg 			}
10059c18d14Smrg 			cold = 0;
101628b55bbSmrg 	                if (!tflag && bzs.avail_out != BUFLEN) {
1025c0ab9e0Smrg 				ssize_t	n;
1035c0ab9e0Smrg 
1041d0e9794Smrg 	                        n = write(out, outbuf, BUFLEN - bzs.avail_out);
105ff930808Smrg 	                        if (n < 0)
1062d5e05afSmrg 	                                maybe_err("write");
107ff930808Smrg 	                	bytes_out += n;
1085c0ab9e0Smrg 	                }
109628b55bbSmrg 			if (ret == BZ_STREAM_END && !end_of_file) {
110628b55bbSmrg 				if (BZ2_bzDecompressEnd(&bzs) != BZ_OK ||
111628b55bbSmrg 				    BZ2_bzDecompressInit(&bzs, 0, 0) != BZ_OK)
112628b55bbSmrg 					maybe_errx("bzip2 re-init");
11359c18d14Smrg 				cold = 1;
114628b55bbSmrg 				ret = BZ_OK;
115628b55bbSmrg 			}
116ff930808Smrg 			break;
117ff930808Smrg 
118ecadec7fSmrg 	        case BZ_DATA_ERROR:
119754b92f9Sdsl 	                maybe_warnx("bzip2 data integrity error");
1202d5e05afSmrg 			break;
1212d5e05afSmrg 
122ecadec7fSmrg 	        case BZ_DATA_ERROR_MAGIC:
123754b92f9Sdsl 	                maybe_warnx("bzip2 magic number error");
1242d5e05afSmrg 			break;
1252d5e05afSmrg 
126ecadec7fSmrg 	        case BZ_MEM_ERROR:
127754b92f9Sdsl 	                maybe_warnx("bzip2 out of memory");
1282d5e05afSmrg 			break;
1292d5e05afSmrg 
130628b55bbSmrg 		default:
131628b55bbSmrg 			maybe_warnx("unknown bzip2 error: %d", ret);
132628b55bbSmrg 			break;
133ff930808Smrg 	        }
134ecadec7fSmrg 	}
135ecadec7fSmrg 
1362d5e05afSmrg 	if (ret != BZ_STREAM_END || BZ2_bzDecompressEnd(&bzs) != BZ_OK)
1372d5e05afSmrg 	        return (-1);
138ecadec7fSmrg 
139ecadec7fSmrg 	return (bytes_out);
140ecadec7fSmrg }
141