1 /* $NetBSD: unbzip2.c,v 1.14 2017/08/04 07:27:08 mrg Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2006 The NetBSD Foundation, Inc. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by Simon Burge. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* This file is #included by gzip.c */ 35 36 static off_t 37 unbzip2(int in, int out, char *pre, size_t prelen, off_t *bytes_in) 38 { 39 int ret, end_of_file, cold = 0; 40 off_t bytes_out = 0; 41 bz_stream bzs; 42 static char *inbuf, *outbuf; 43 44 if (inbuf == NULL) 45 inbuf = malloc(BUFLEN); 46 if (outbuf == NULL) 47 outbuf = malloc(BUFLEN); 48 if (inbuf == NULL || outbuf == NULL) 49 maybe_err("malloc"); 50 51 bzs.bzalloc = NULL; 52 bzs.bzfree = NULL; 53 bzs.opaque = NULL; 54 55 end_of_file = 0; 56 ret = BZ2_bzDecompressInit(&bzs, 0, 0); 57 if (ret != BZ_OK) 58 maybe_errx("bzip2 init"); 59 60 /* Prepend. */ 61 bzs.avail_in = prelen; 62 bzs.next_in = pre; 63 64 if (bytes_in) 65 *bytes_in = prelen; 66 67 while (ret == BZ_OK) { 68 check_siginfo(); 69 if (bzs.avail_in == 0 && !end_of_file) { 70 ssize_t n; 71 72 n = read(in, inbuf, BUFLEN); 73 if (n < 0) 74 maybe_err("read"); 75 if (n == 0) 76 end_of_file = 1; 77 infile_newdata(n); 78 bzs.next_in = inbuf; 79 bzs.avail_in = n; 80 if (bytes_in) 81 *bytes_in += n; 82 } 83 84 bzs.next_out = outbuf; 85 bzs.avail_out = BUFLEN; 86 ret = BZ2_bzDecompress(&bzs); 87 88 switch (ret) { 89 case BZ_STREAM_END: 90 case BZ_OK: 91 if (ret == BZ_OK && end_of_file) { 92 /* 93 * If we hit this after a stream end, consider 94 * it as the end of the whole file and don't 95 * bail out. 96 */ 97 if (cold == 1) 98 ret = BZ_STREAM_END; 99 else 100 maybe_errx("truncated file"); 101 } 102 cold = 0; 103 if (!tflag && bzs.avail_out != BUFLEN) { 104 ssize_t n; 105 106 n = write(out, outbuf, BUFLEN - bzs.avail_out); 107 if (n < 0) 108 maybe_err("write"); 109 bytes_out += n; 110 } 111 if (ret == BZ_STREAM_END && !end_of_file) { 112 if (BZ2_bzDecompressEnd(&bzs) != BZ_OK || 113 BZ2_bzDecompressInit(&bzs, 0, 0) != BZ_OK) 114 maybe_errx("bzip2 re-init"); 115 cold = 1; 116 ret = BZ_OK; 117 } 118 break; 119 120 case BZ_DATA_ERROR: 121 maybe_warnx("bzip2 data integrity error"); 122 break; 123 124 case BZ_DATA_ERROR_MAGIC: 125 maybe_warnx("bzip2 magic number error"); 126 break; 127 128 case BZ_MEM_ERROR: 129 maybe_warnx("bzip2 out of memory"); 130 break; 131 132 default: 133 maybe_warnx("unknown bzip2 error: %d", ret); 134 break; 135 } 136 } 137 138 if (ret != BZ_STREAM_END || BZ2_bzDecompressEnd(&bzs) != BZ_OK) 139 return (-1); 140 141 return (bytes_out); 142 } 143 144