xref: /freebsd/usr.bin/gzip/unbzip2.c (revision 9a9ea25f4a3416fbc10f2a9fef3a482a1c4202e8)
19a9ea25fSXin LI /*	$NetBSD: unbzip2.c,v 1.10 2006/10/03 08:20:03 simonb Exp $	*/
29a9ea25fSXin LI 
39a9ea25fSXin LI /*-
49a9ea25fSXin LI  * Copyright (c) 2006 The NetBSD Foundation, Inc.
59a9ea25fSXin LI  * All rights reserved.
69a9ea25fSXin LI  *
79a9ea25fSXin LI  * This code is derived from software contributed to The NetBSD Foundation
89a9ea25fSXin LI  * by Simon Burge.
99a9ea25fSXin LI  *
109a9ea25fSXin LI  * Redistribution and use in source and binary forms, with or without
119a9ea25fSXin LI  * modification, are permitted provided that the following conditions
129a9ea25fSXin LI  * are met:
139a9ea25fSXin LI  * 1. Redistributions of source code must retain the above copyright
149a9ea25fSXin LI  *    notice, this list of conditions and the following disclaimer.
159a9ea25fSXin LI  * 2. Redistributions in binary form must reproduce the above copyright
169a9ea25fSXin LI  *    notice, this list of conditions and the following disclaimer in the
179a9ea25fSXin LI  *    documentation and/or other materials provided with the distribution.
189a9ea25fSXin LI  * 3. All advertising materials mentioning features or use of this software
199a9ea25fSXin LI  *    must display the following acknowledgement:
209a9ea25fSXin LI  *        This product includes software developed by the NetBSD
219a9ea25fSXin LI  *        Foundation, Inc. and its contributors.
229a9ea25fSXin LI  * 4. Neither the name of The NetBSD Foundation nor the names of its
239a9ea25fSXin LI  *    contributors may be used to endorse or promote products derived
249a9ea25fSXin LI  *    from this software without specific prior written permission.
259a9ea25fSXin LI  *
269a9ea25fSXin LI  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
279a9ea25fSXin LI  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
289a9ea25fSXin LI  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
299a9ea25fSXin LI  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
309a9ea25fSXin LI  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
319a9ea25fSXin LI  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
329a9ea25fSXin LI  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
339a9ea25fSXin LI  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
349a9ea25fSXin LI  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
359a9ea25fSXin LI  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
369a9ea25fSXin LI  * POSSIBILITY OF SUCH DAMAGE.
379a9ea25fSXin LI  *
389a9ea25fSXin LI  * $FreeBSD$
399a9ea25fSXin LI  */
409a9ea25fSXin LI 
419a9ea25fSXin LI /* This file is #included by gzip.c */
429a9ea25fSXin LI 
439a9ea25fSXin LI static off_t
449a9ea25fSXin LI unbzip2(int in, int out, char *pre, size_t prelen, off_t *bytes_in)
459a9ea25fSXin LI {
469a9ea25fSXin LI 	int		ret, end_of_file;
479a9ea25fSXin LI 	off_t		bytes_out = 0;
489a9ea25fSXin LI 	bz_stream	bzs;
499a9ea25fSXin LI 	static char	*inbuf, *outbuf;
509a9ea25fSXin LI 
519a9ea25fSXin LI 	if (inbuf == NULL)
529a9ea25fSXin LI 		inbuf = malloc(BUFLEN);
539a9ea25fSXin LI 	if (outbuf == NULL)
549a9ea25fSXin LI 		outbuf = malloc(BUFLEN);
559a9ea25fSXin LI 	if (inbuf == NULL || outbuf == NULL)
569a9ea25fSXin LI 	        maybe_err("malloc");
579a9ea25fSXin LI 
589a9ea25fSXin LI 	bzs.bzalloc = NULL;
599a9ea25fSXin LI 	bzs.bzfree = NULL;
609a9ea25fSXin LI 	bzs.opaque = NULL;
619a9ea25fSXin LI 
629a9ea25fSXin LI 	end_of_file = 0;
639a9ea25fSXin LI 	ret = BZ2_bzDecompressInit(&bzs, 0, 0);
649a9ea25fSXin LI 	if (ret != BZ_OK)
659a9ea25fSXin LI 	        maybe_errx("bzip2 init");
669a9ea25fSXin LI 
679a9ea25fSXin LI 	/* Prepend. */
689a9ea25fSXin LI 	bzs.avail_in = prelen;
699a9ea25fSXin LI 	bzs.next_in = pre;
709a9ea25fSXin LI 
719a9ea25fSXin LI 	if (bytes_in)
729a9ea25fSXin LI 		*bytes_in = prelen;
739a9ea25fSXin LI 
749a9ea25fSXin LI 	while (ret >= BZ_OK && ret != BZ_STREAM_END) {
759a9ea25fSXin LI 	        if (bzs.avail_in == 0 && !end_of_file) {
769a9ea25fSXin LI 			ssize_t	n;
779a9ea25fSXin LI 
789a9ea25fSXin LI 	                n = read(in, inbuf, BUFLEN);
799a9ea25fSXin LI 	                if (n < 0)
809a9ea25fSXin LI 	                        maybe_err("read");
819a9ea25fSXin LI 	                if (n == 0)
829a9ea25fSXin LI 	                        end_of_file = 1;
839a9ea25fSXin LI 	                bzs.next_in = inbuf;
849a9ea25fSXin LI 	                bzs.avail_in = n;
859a9ea25fSXin LI 			if (bytes_in)
869a9ea25fSXin LI 				*bytes_in += n;
879a9ea25fSXin LI 	        }
889a9ea25fSXin LI 
899a9ea25fSXin LI 	        bzs.next_out = outbuf;
909a9ea25fSXin LI 	        bzs.avail_out = BUFLEN;
919a9ea25fSXin LI 	        ret = BZ2_bzDecompress(&bzs);
929a9ea25fSXin LI 
939a9ea25fSXin LI 	        switch (ret) {
949a9ea25fSXin LI 	        case BZ_STREAM_END:
959a9ea25fSXin LI 	        case BZ_OK:
969a9ea25fSXin LI 	                if (ret == BZ_OK && end_of_file)
979a9ea25fSXin LI 	                        maybe_err("read");
989a9ea25fSXin LI 	                if (!tflag) {
999a9ea25fSXin LI 				ssize_t	n;
1009a9ea25fSXin LI 
1019a9ea25fSXin LI 	                        n = write(out, outbuf, BUFLEN - bzs.avail_out);
1029a9ea25fSXin LI 	                        if (n < 0)
1039a9ea25fSXin LI 	                                maybe_err("write");
1049a9ea25fSXin LI 	                	bytes_out += n;
1059a9ea25fSXin LI 	                }
1069a9ea25fSXin LI 	                break;
1079a9ea25fSXin LI 
1089a9ea25fSXin LI 	        case BZ_DATA_ERROR:
1099a9ea25fSXin LI 	                maybe_warnx("bzip2 data integrity error");
1109a9ea25fSXin LI 			break;
1119a9ea25fSXin LI 
1129a9ea25fSXin LI 	        case BZ_DATA_ERROR_MAGIC:
1139a9ea25fSXin LI 	                maybe_warnx("bzip2 magic number error");
1149a9ea25fSXin LI 			break;
1159a9ea25fSXin LI 
1169a9ea25fSXin LI 	        case BZ_MEM_ERROR:
1179a9ea25fSXin LI 	                maybe_warnx("bzip2 out of memory");
1189a9ea25fSXin LI 			break;
1199a9ea25fSXin LI 
1209a9ea25fSXin LI 	        }
1219a9ea25fSXin LI 	}
1229a9ea25fSXin LI 
1239a9ea25fSXin LI 	if (ret != BZ_STREAM_END || BZ2_bzDecompressEnd(&bzs) != BZ_OK)
1249a9ea25fSXin LI 	        return (-1);
1259a9ea25fSXin LI 
1269a9ea25fSXin LI 	return (bytes_out);
1279a9ea25fSXin LI }
1289a9ea25fSXin LI 
129