unbzip2.c revision 206387
1206387Sdelphij/* $NetBSD: unbzip2.c,v 1.13 2009/12/05 03:23:37 mrg Exp $ */ 2166255Sdelphij 3166255Sdelphij/*- 4166255Sdelphij * Copyright (c) 2006 The NetBSD Foundation, Inc. 5166255Sdelphij * All rights reserved. 6166255Sdelphij * 7166255Sdelphij * This code is derived from software contributed to The NetBSD Foundation 8166255Sdelphij * by Simon Burge. 9166255Sdelphij * 10166255Sdelphij * Redistribution and use in source and binary forms, with or without 11166255Sdelphij * modification, are permitted provided that the following conditions 12166255Sdelphij * are met: 13166255Sdelphij * 1. Redistributions of source code must retain the above copyright 14166255Sdelphij * notice, this list of conditions and the following disclaimer. 15166255Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 16166255Sdelphij * notice, this list of conditions and the following disclaimer in the 17166255Sdelphij * documentation and/or other materials provided with the distribution. 18166255Sdelphij * 19166255Sdelphij * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20166255Sdelphij * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21166255Sdelphij * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22166255Sdelphij * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23166255Sdelphij * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24166255Sdelphij * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25166255Sdelphij * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26166255Sdelphij * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27166255Sdelphij * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28166255Sdelphij * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29166255Sdelphij * POSSIBILITY OF SUCH DAMAGE. 30166255Sdelphij * 31166255Sdelphij * $FreeBSD: head/usr.bin/gzip/unbzip2.c 206387 2010-04-07 22:54:53Z delphij $ 32166255Sdelphij */ 33166255Sdelphij 34166255Sdelphij/* This file is #included by gzip.c */ 35166255Sdelphij 36166255Sdelphijstatic off_t 37166255Sdelphijunbzip2(int in, int out, char *pre, size_t prelen, off_t *bytes_in) 38166255Sdelphij{ 39199339Sdelphij int ret, end_of_file, cold = 0; 40166255Sdelphij off_t bytes_out = 0; 41166255Sdelphij bz_stream bzs; 42166255Sdelphij static char *inbuf, *outbuf; 43166255Sdelphij 44166255Sdelphij if (inbuf == NULL) 45166255Sdelphij inbuf = malloc(BUFLEN); 46166255Sdelphij if (outbuf == NULL) 47166255Sdelphij outbuf = malloc(BUFLEN); 48166255Sdelphij if (inbuf == NULL || outbuf == NULL) 49166255Sdelphij maybe_err("malloc"); 50166255Sdelphij 51166255Sdelphij bzs.bzalloc = NULL; 52166255Sdelphij bzs.bzfree = NULL; 53166255Sdelphij bzs.opaque = NULL; 54166255Sdelphij 55166255Sdelphij end_of_file = 0; 56166255Sdelphij ret = BZ2_bzDecompressInit(&bzs, 0, 0); 57166255Sdelphij if (ret != BZ_OK) 58166255Sdelphij maybe_errx("bzip2 init"); 59166255Sdelphij 60166255Sdelphij /* Prepend. */ 61166255Sdelphij bzs.avail_in = prelen; 62166255Sdelphij bzs.next_in = pre; 63166255Sdelphij 64166255Sdelphij if (bytes_in) 65166255Sdelphij *bytes_in = prelen; 66166255Sdelphij 67199066Sdelphij while (ret == BZ_OK) { 68166255Sdelphij if (bzs.avail_in == 0 && !end_of_file) { 69166255Sdelphij ssize_t n; 70166255Sdelphij 71166255Sdelphij n = read(in, inbuf, BUFLEN); 72166255Sdelphij if (n < 0) 73166255Sdelphij maybe_err("read"); 74166255Sdelphij if (n == 0) 75166255Sdelphij end_of_file = 1; 76166255Sdelphij bzs.next_in = inbuf; 77166255Sdelphij bzs.avail_in = n; 78166255Sdelphij if (bytes_in) 79166255Sdelphij *bytes_in += n; 80166255Sdelphij } 81166255Sdelphij 82166255Sdelphij bzs.next_out = outbuf; 83166255Sdelphij bzs.avail_out = BUFLEN; 84166255Sdelphij ret = BZ2_bzDecompress(&bzs); 85166255Sdelphij 86166255Sdelphij switch (ret) { 87166255Sdelphij case BZ_STREAM_END: 88166255Sdelphij case BZ_OK: 89199339Sdelphij if (ret == BZ_OK && end_of_file) { 90199339Sdelphij /* 91199339Sdelphij * If we hit this after a stream end, consider 92199339Sdelphij * it as the end of the whole file and don't 93199339Sdelphij * bail out. 94199339Sdelphij */ 95199339Sdelphij if (cold == 1) 96199339Sdelphij ret = BZ_STREAM_END; 97199339Sdelphij else 98199339Sdelphij maybe_errx("truncated file"); 99199339Sdelphij } 100199339Sdelphij cold = 0; 101199066Sdelphij if (!tflag && bzs.avail_out != BUFLEN) { 102166255Sdelphij ssize_t n; 103166255Sdelphij 104166255Sdelphij n = write(out, outbuf, BUFLEN - bzs.avail_out); 105166255Sdelphij if (n < 0) 106166255Sdelphij maybe_err("write"); 107166255Sdelphij bytes_out += n; 108166255Sdelphij } 109199066Sdelphij if (ret == BZ_STREAM_END && !end_of_file) { 110199066Sdelphij if (BZ2_bzDecompressEnd(&bzs) != BZ_OK || 111199066Sdelphij BZ2_bzDecompressInit(&bzs, 0, 0) != BZ_OK) 112199066Sdelphij maybe_errx("bzip2 re-init"); 113199339Sdelphij cold = 1; 114199066Sdelphij ret = BZ_OK; 115199066Sdelphij } 116199066Sdelphij break; 117166255Sdelphij 118166255Sdelphij case BZ_DATA_ERROR: 119166255Sdelphij maybe_warnx("bzip2 data integrity error"); 120166255Sdelphij break; 121166255Sdelphij 122166255Sdelphij case BZ_DATA_ERROR_MAGIC: 123166255Sdelphij maybe_warnx("bzip2 magic number error"); 124166255Sdelphij break; 125166255Sdelphij 126166255Sdelphij case BZ_MEM_ERROR: 127166255Sdelphij maybe_warnx("bzip2 out of memory"); 128166255Sdelphij break; 129199066Sdelphij 130199066Sdelphij default: 131199066Sdelphij maybe_warnx("unknown bzip2 error: %d", ret); 132199066Sdelphij break; 133166255Sdelphij } 134166255Sdelphij } 135166255Sdelphij 136166255Sdelphij if (ret != BZ_STREAM_END || BZ2_bzDecompressEnd(&bzs) != BZ_OK) 137166255Sdelphij return (-1); 138166255Sdelphij 139166255Sdelphij return (bytes_out); 140166255Sdelphij} 141166255Sdelphij 142