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