190f528e8SXin LI /* $NetBSD: unbzip2.c,v 1.14 2017/08/04 07:27:08 mrg Exp $ */
29a9ea25fSXin LI
39a9ea25fSXin LI /*-
4*b61a5730SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
51de7b4b8SPedro F. Giffuni *
69a9ea25fSXin LI * Copyright (c) 2006 The NetBSD Foundation, Inc.
79a9ea25fSXin LI * All rights reserved.
89a9ea25fSXin LI *
99a9ea25fSXin LI * This code is derived from software contributed to The NetBSD Foundation
109a9ea25fSXin LI * by Simon Burge.
119a9ea25fSXin LI *
129a9ea25fSXin LI * Redistribution and use in source and binary forms, with or without
139a9ea25fSXin LI * modification, are permitted provided that the following conditions
149a9ea25fSXin LI * are met:
159a9ea25fSXin LI * 1. Redistributions of source code must retain the above copyright
169a9ea25fSXin LI * notice, this list of conditions and the following disclaimer.
179a9ea25fSXin LI * 2. Redistributions in binary form must reproduce the above copyright
189a9ea25fSXin LI * notice, this list of conditions and the following disclaimer in the
199a9ea25fSXin LI * documentation and/or other materials provided with the distribution.
209a9ea25fSXin LI *
219a9ea25fSXin LI * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
229a9ea25fSXin LI * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
239a9ea25fSXin LI * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
249a9ea25fSXin LI * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
259a9ea25fSXin LI * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
269a9ea25fSXin LI * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
279a9ea25fSXin LI * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
289a9ea25fSXin LI * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
299a9ea25fSXin LI * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
309a9ea25fSXin LI * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
319a9ea25fSXin LI * POSSIBILITY OF SUCH DAMAGE.
329a9ea25fSXin LI */
339a9ea25fSXin LI
349a9ea25fSXin LI /* This file is #included by gzip.c */
359a9ea25fSXin LI
369a9ea25fSXin LI static off_t
unbzip2(int in,int out,char * pre,size_t prelen,off_t * bytes_in)379a9ea25fSXin LI unbzip2(int in, int out, char *pre, size_t prelen, off_t *bytes_in)
389a9ea25fSXin LI {
39a0b4046bSXin LI int ret, end_of_file, cold = 0;
409a9ea25fSXin LI off_t bytes_out = 0;
419a9ea25fSXin LI bz_stream bzs;
429a9ea25fSXin LI static char *inbuf, *outbuf;
439a9ea25fSXin LI
449a9ea25fSXin LI if (inbuf == NULL)
459a9ea25fSXin LI inbuf = malloc(BUFLEN);
469a9ea25fSXin LI if (outbuf == NULL)
479a9ea25fSXin LI outbuf = malloc(BUFLEN);
489a9ea25fSXin LI if (inbuf == NULL || outbuf == NULL)
499a9ea25fSXin LI maybe_err("malloc");
509a9ea25fSXin LI
519a9ea25fSXin LI bzs.bzalloc = NULL;
529a9ea25fSXin LI bzs.bzfree = NULL;
539a9ea25fSXin LI bzs.opaque = NULL;
549a9ea25fSXin LI
559a9ea25fSXin LI end_of_file = 0;
569a9ea25fSXin LI ret = BZ2_bzDecompressInit(&bzs, 0, 0);
579a9ea25fSXin LI if (ret != BZ_OK)
589a9ea25fSXin LI maybe_errx("bzip2 init");
599a9ea25fSXin LI
609a9ea25fSXin LI /* Prepend. */
619a9ea25fSXin LI bzs.avail_in = prelen;
629a9ea25fSXin LI bzs.next_in = pre;
639a9ea25fSXin LI
649a9ea25fSXin LI if (bytes_in)
659a9ea25fSXin LI *bytes_in = prelen;
669a9ea25fSXin LI
670c10c611SXin LI while (ret == BZ_OK) {
6890f528e8SXin LI check_siginfo();
699a9ea25fSXin LI if (bzs.avail_in == 0 && !end_of_file) {
709a9ea25fSXin LI ssize_t n;
719a9ea25fSXin LI
729a9ea25fSXin LI n = read(in, inbuf, BUFLEN);
739a9ea25fSXin LI if (n < 0)
749a9ea25fSXin LI maybe_err("read");
759a9ea25fSXin LI if (n == 0)
769a9ea25fSXin LI end_of_file = 1;
7790f528e8SXin LI infile_newdata(n);
789a9ea25fSXin LI bzs.next_in = inbuf;
799a9ea25fSXin LI bzs.avail_in = n;
809a9ea25fSXin LI if (bytes_in)
819a9ea25fSXin LI *bytes_in += n;
829a9ea25fSXin LI }
839a9ea25fSXin LI
849a9ea25fSXin LI bzs.next_out = outbuf;
859a9ea25fSXin LI bzs.avail_out = BUFLEN;
869a9ea25fSXin LI ret = BZ2_bzDecompress(&bzs);
879a9ea25fSXin LI
889a9ea25fSXin LI switch (ret) {
899a9ea25fSXin LI case BZ_STREAM_END:
909a9ea25fSXin LI case BZ_OK:
91a0b4046bSXin LI if (ret == BZ_OK && end_of_file) {
92a0b4046bSXin LI /*
93a0b4046bSXin LI * If we hit this after a stream end, consider
94a0b4046bSXin LI * it as the end of the whole file and don't
95a0b4046bSXin LI * bail out.
96a0b4046bSXin LI */
97a0b4046bSXin LI if (cold == 1)
98a0b4046bSXin LI ret = BZ_STREAM_END;
99a0b4046bSXin LI else
100a0b4046bSXin LI maybe_errx("truncated file");
101a0b4046bSXin LI }
102a0b4046bSXin LI cold = 0;
1030c10c611SXin LI if (!tflag && bzs.avail_out != BUFLEN) {
1049a9ea25fSXin LI ssize_t n;
1059a9ea25fSXin LI
1069a9ea25fSXin LI n = write(out, outbuf, BUFLEN - bzs.avail_out);
1079a9ea25fSXin LI if (n < 0)
1089a9ea25fSXin LI maybe_err("write");
1099a9ea25fSXin LI bytes_out += n;
1109a9ea25fSXin LI }
1110c10c611SXin LI if (ret == BZ_STREAM_END && !end_of_file) {
1120c10c611SXin LI if (BZ2_bzDecompressEnd(&bzs) != BZ_OK ||
1130c10c611SXin LI BZ2_bzDecompressInit(&bzs, 0, 0) != BZ_OK)
1140c10c611SXin LI maybe_errx("bzip2 re-init");
115a0b4046bSXin LI cold = 1;
1160c10c611SXin LI ret = BZ_OK;
1170c10c611SXin LI }
1189a9ea25fSXin LI break;
1199a9ea25fSXin LI
1209a9ea25fSXin LI case BZ_DATA_ERROR:
1219a9ea25fSXin LI maybe_warnx("bzip2 data integrity error");
1229a9ea25fSXin LI break;
1239a9ea25fSXin LI
1249a9ea25fSXin LI case BZ_DATA_ERROR_MAGIC:
1259a9ea25fSXin LI maybe_warnx("bzip2 magic number error");
1269a9ea25fSXin LI break;
1279a9ea25fSXin LI
1289a9ea25fSXin LI case BZ_MEM_ERROR:
1299a9ea25fSXin LI maybe_warnx("bzip2 out of memory");
1309a9ea25fSXin LI break;
1319a9ea25fSXin LI
1320c10c611SXin LI default:
1330c10c611SXin LI maybe_warnx("unknown bzip2 error: %d", ret);
1340c10c611SXin LI break;
1359a9ea25fSXin LI }
1369a9ea25fSXin LI }
1379a9ea25fSXin LI
1389a9ea25fSXin LI if (ret != BZ_STREAM_END || BZ2_bzDecompressEnd(&bzs) != BZ_OK)
1399a9ea25fSXin LI return (-1);
1409a9ea25fSXin LI
1419a9ea25fSXin LI return (bytes_out);
1429a9ea25fSXin LI }
1439a9ea25fSXin LI
144