2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
13 /* $Id: uncompress.c,v 1.3 2006/07/04 04:57:42 hpa Exp $ */
14 /* ----------------------------------------------------------------------- *
16 * Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
21 * USA; either version 2 of the License, or (at your option) any later
22 * version; incorporated herein by reference.
24 * ----------------------------------------------------------------------- */
26 #include "mkzftree.h" /* Must be included first! */
34 int block_uncompress_file(FILE *input, FILE *output, off_t size)
36 struct compressed_file_header hdr;
37 Bytef *inbuf, *outbuf;
39 char *pointer_block, *pptr;
40 unsigned long nblocks;
41 unsigned long fullsize, block_size, block_size2;
42 size_t ptrblock_bytes;
43 unsigned long cstart, cend, csize;
46 int err = EX_SOFTWARE;
48 if ( (bytes = fread(&hdr, 1, sizeof hdr, input)) != sizeof hdr ) {
49 if ( bytes == (size_t)size ) {
50 /* Very short file; not compressed */
51 return ( fwrite(&hdr, 1, bytes, output) != bytes ) ? EX_CANTCREAT : 0;
53 return EX_IOERR; /* Read error */
57 if ( memcmp(&hdr.magic, zisofs_magic, sizeof zisofs_magic) ) {
58 inbuf = xmalloc(CBLOCK_SIZE);
60 memcpy(inbuf, &hdr, sizeof hdr);
63 if ( fwrite(inbuf, 1, bytes, output) != bytes )
65 } while ( (bytes = fread(inbuf, 1, CBLOCK_SIZE, input)) > 0 );
67 return ferror(input) ? EX_IOERR : 0;
70 /* Now we know the file must be compressed. Get the pointer table. */
71 if ( fseek(input, hdr.header_size << 2, SEEK_SET) == -1 )
74 fullsize = get_731(hdr.uncompressed_len);
75 block_shift = hdr.block_size;
76 block_size = 1UL << block_shift;
77 block_size2 = block_size << 1;
78 inbuf = xmalloc(block_size2);
79 outbuf = xmalloc(block_size);
81 nblocks = (fullsize + block_size - 1) >> block_shift;
83 ptrblock_bytes = (nblocks+1) * 4;
84 pointer_block = xmalloc(ptrblock_bytes);
86 if ( (bytes = fread(pointer_block, 1, ptrblock_bytes, input)) != ptrblock_bytes ) {
93 cstart = get_731(pptr);
100 memset(outbuf, 0, block_size);
103 if ( csize > block_size2 ) {
108 if ( fseek(input, cstart, SEEK_SET) == -1 ||
109 (bytes = fread(inbuf, 1, csize, input)) != csize ) {
114 bytes = block_size; /* Max output buffer size */
115 if ( (zerr = uncompress(outbuf, &bytes, inbuf, csize)) != Z_OK ) {
116 err = (zerr = Z_MEM_ERROR) ? EX_OSERR : EX_DATAERR;
121 if ( ((fullsize > block_size) && (bytes != block_size))
122 || ((fullsize <= block_size) && (bytes < fullsize)) ) {
127 if ( bytes > fullsize )
130 if ( fwrite(outbuf, 1, bytes, output) != bytes ) {