summaryrefslogtreecommitdiff
path: root/3rd-party/zisofs_tools/uncompress.c
diff options
context:
space:
mode:
Diffstat (limited to '3rd-party/zisofs_tools/uncompress.c')
-rw-r--r--3rd-party/zisofs_tools/uncompress.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/3rd-party/zisofs_tools/uncompress.c b/3rd-party/zisofs_tools/uncompress.c
new file mode 100644
index 0000000..c9ba6e4
--- /dev/null
+++ b/3rd-party/zisofs_tools/uncompress.c
@@ -0,0 +1,147 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* $Id: uncompress.c,v 1.3 2006/07/04 04:57:42 hpa Exp $ */
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include "mkzftree.h" /* Must be included first! */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <zlib.h>
+
+#include "iso9660.h"
+
+int block_uncompress_file(FILE *input, FILE *output, off_t size)
+{
+ struct compressed_file_header hdr;
+ Bytef *inbuf, *outbuf;
+ int block_shift;
+ char *pointer_block, *pptr;
+ unsigned long nblocks;
+ unsigned long fullsize, block_size, block_size2;
+ size_t ptrblock_bytes;
+ unsigned long cstart, cend, csize;
+ uLong bytes;
+ int zerr;
+ int err = EX_SOFTWARE;
+
+ if ( (bytes = fread(&hdr, 1, sizeof hdr, input)) != sizeof hdr ) {
+ if ( bytes == (size_t)size ) {
+ /* Very short file; not compressed */
+ return ( fwrite(&hdr, 1, bytes, output) != bytes ) ? EX_CANTCREAT : 0;
+ } else {
+ return EX_IOERR; /* Read error */
+ }
+ }
+
+ if ( memcmp(&hdr.magic, zisofs_magic, sizeof zisofs_magic) ) {
+ inbuf = xmalloc(CBLOCK_SIZE);
+ /* Not compressed */
+ memcpy(inbuf, &hdr, sizeof hdr);
+ bytes = sizeof hdr;
+ do {
+ if ( fwrite(inbuf, 1, bytes, output) != bytes )
+ return EX_CANTCREAT;
+ } while ( (bytes = fread(inbuf, 1, CBLOCK_SIZE, input)) > 0 );
+ free(inbuf);
+ return ferror(input) ? EX_IOERR : 0;
+ }
+
+ /* Now we know the file must be compressed. Get the pointer table. */
+ if ( fseek(input, hdr.header_size << 2, SEEK_SET) == -1 )
+ return EX_IOERR;
+
+ fullsize = get_731(hdr.uncompressed_len);
+ block_shift = hdr.block_size;
+ block_size = 1UL << block_shift;
+ block_size2 = block_size << 1;
+ inbuf = xmalloc(block_size2);
+ outbuf = xmalloc(block_size);
+
+ nblocks = (fullsize + block_size - 1) >> block_shift;
+
+ ptrblock_bytes = (nblocks+1) * 4;
+ pointer_block = xmalloc(ptrblock_bytes);
+
+ if ( (bytes = fread(pointer_block, 1, ptrblock_bytes, input)) != ptrblock_bytes ) {
+ err = EX_IOERR;
+ goto free_ptr_bail;
+ }
+
+ pptr = pointer_block;
+ while ( fullsize ) {
+ cstart = get_731(pptr);
+ pptr += 4;
+ cend = get_731(pptr);
+
+ csize = cend-cstart;
+
+ if ( csize == 0 ) {
+ memset(outbuf, 0, block_size);
+ bytes = block_size;
+ } else {
+ if ( csize > block_size2 ) {
+ err = EX_DATAERR;
+ goto free_ptr_bail;
+ }
+
+ if ( fseek(input, cstart, SEEK_SET) == -1 ||
+ (bytes = fread(inbuf, 1, csize, input)) != csize ) {
+ err = EX_IOERR;
+ goto free_ptr_bail;
+ }
+
+ bytes = block_size; /* Max output buffer size */
+ if ( (zerr = uncompress(outbuf, &bytes, inbuf, csize)) != Z_OK ) {
+ err = (zerr = Z_MEM_ERROR) ? EX_OSERR : EX_DATAERR;
+ goto free_ptr_bail;
+ }
+ }
+
+ if ( ((fullsize > block_size) && (bytes != block_size))
+ || ((fullsize <= block_size) && (bytes < fullsize)) ) {
+ err = EX_DATAERR;
+ goto free_ptr_bail;
+ }
+
+ if ( bytes > fullsize )
+ bytes = fullsize;
+
+ if ( fwrite(outbuf, 1, bytes, output) != bytes ) {
+ err = EX_CANTCREAT;
+ goto free_ptr_bail;
+ }
+
+ fullsize -= bytes;
+ }
+
+ err = 0;
+
+ free_ptr_bail:
+ free(pointer_block);
+ free(inbuf);
+ free(outbuf);
+ return err;
+}
+
+