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