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