static void appDecompressLZX(byte *CompressedBuffer, int CompressedSize, byte *UncompressedBuffer, int UncompressedSize) { guard(appDecompressLZX); // setup streams mspack_file src, dst; src.buf = CompressedBuffer; src.bufSize = CompressedSize; src.pos = 0; src.rest = 0; dst.buf = UncompressedBuffer; dst.bufSize = UncompressedSize; dst.pos = 0; // prepare decompressor lzxd_stream *lzxd = lzxd_init(&lzxSys, &src, &dst, 17, 0, 256*1024, UncompressedSize); assert(lzxd); // decompress int r = lzxd_decompress(lzxd, UncompressedSize); if (r != MSPACK_ERR_OK) appError("lzxd_decompress(%d,%d) returned %d", CompressedSize, UncompressedSize, r); // free resources lzxd_free(lzxd); unguard; }
static int oabd_decompress(struct msoab_decompressor *_self, const char *input, const char *output) { struct msoab_decompressor_p *self = (struct msoab_decompressor_p *) _self; struct mspack_system *sys; struct mspack_file *infh = NULL; struct mspack_file *outfh = NULL; unsigned char *buf = NULL; unsigned char hdrbuf[oabhead_SIZEOF]; unsigned int block_max, target_size; struct lzxd_stream *lzx = NULL; struct mspack_system oabd_sys; struct oabd_file in_ofh, out_ofh; unsigned int window_bits; int ret = MSPACK_ERR_OK; if (!self) return MSPACK_ERR_ARGS; sys = self->system; infh = sys->open(sys, input, MSPACK_SYS_OPEN_READ); if (!infh) { ret = MSPACK_ERR_OPEN; goto out; } if (sys->read(infh, hdrbuf, oabhead_SIZEOF) != oabhead_SIZEOF) { ret = MSPACK_ERR_READ; goto out; } if (EndGetI32(&hdrbuf[oabhead_VersionHi]) != 3 || EndGetI32(&hdrbuf[oabhead_VersionLo]) != 1) { ret = MSPACK_ERR_SIGNATURE; goto out; } block_max = EndGetI32(&hdrbuf[oabhead_BlockMax]); target_size = EndGetI32(&hdrbuf[oabhead_TargetSize]); /* We use it for reading block headers too */ if (block_max < oabblk_SIZEOF) block_max = oabblk_SIZEOF; outfh = sys->open(sys, output, MSPACK_SYS_OPEN_WRITE); if (!outfh) { ret = MSPACK_ERR_OPEN; goto out; } buf = sys->alloc(sys, block_max); if (!buf) { ret = MSPACK_ERR_NOMEMORY; goto out; } oabd_sys = *sys; oabd_sys.read = oabd_sys_read; oabd_sys.write = oabd_sys_write; in_ofh.orig_sys = sys; in_ofh.orig_file = infh; out_ofh.orig_sys = sys; out_ofh.orig_file = outfh; while (target_size) { unsigned int blk_csize, blk_dsize, blk_crc, blk_flags; if (sys->read(infh, buf, oabblk_SIZEOF) != oabblk_SIZEOF) { ret = MSPACK_ERR_READ; goto out; } blk_flags = EndGetI32(&buf[oabblk_Flags]); blk_csize = EndGetI32(&buf[oabblk_CompSize]); blk_dsize = EndGetI32(&buf[oabblk_UncompSize]); blk_crc = EndGetI32(&buf[oabblk_CRC]); if (blk_dsize > block_max || blk_dsize > target_size || blk_flags > 1) { ret = MSPACK_ERR_DATAFORMAT; goto out; } if (!blk_flags) { /* Uncompressed block */ if (blk_dsize != blk_csize) { ret = MSPACK_ERR_DATAFORMAT; goto out; } if (sys->read(infh, buf, blk_dsize) != (int)blk_dsize) { ret = MSPACK_ERR_READ; goto out; } if (sys->write(outfh, buf, blk_dsize) != (int)blk_dsize) { ret = MSPACK_ERR_WRITE; goto out; } } else { /* LZX compressed block */ window_bits = 17; while (window_bits < 25 && (1U << window_bits) < blk_dsize) window_bits++; in_ofh.available = blk_csize; out_ofh.crc = 0xffffffff; lzx = lzxd_init(&oabd_sys, (void *)&in_ofh, (void *)&out_ofh, window_bits, 0, 4096, blk_dsize, 1); if (!lzx) { ret = MSPACK_ERR_NOMEMORY; goto out; } ret = lzxd_decompress(lzx, blk_dsize); if (ret != MSPACK_ERR_OK) goto out; lzxd_free(lzx); lzx = NULL; /* Consume any trailing padding bytes before the next block */ while (in_ofh.available) { int count = block_max; if ((size_t)count > in_ofh.available) count = in_ofh.available; count = sys->read(infh, buf, count); if (count < 0) { ret = MSPACK_ERR_READ; goto out; } in_ofh.available -= count; } if (out_ofh.crc != blk_crc) { ret = MSPACK_ERR_CHECKSUM; goto out; } } target_size -= blk_dsize; } out: if (lzx) lzxd_free(lzx); if (buf) sys->free(buf); if (outfh) sys->close(outfh); if (infh) sys->close(infh); return ret; }