void XzCompress::Decode(void) { direct = 1; // set direction needed by parent [Get|Send]Chars() // get buffer char chunk[1024]; char *zbuf = (char *)calloc(1, 1024); char *chunkbuf = zbuf; int chunklen; unsigned long zlen = 0; while((chunklen = GetChars(chunk, 1023))) { memcpy(chunkbuf, chunk, chunklen); zlen += chunklen; if (chunklen < 1023) break; else zbuf = (char *)realloc(zbuf, zlen + 1024); chunkbuf = zbuf + zlen; } //printf("Decoding complength{%ld} uncomp{%ld}\n", zlen, blen); if (zlen) { unsigned long blen = zlen*20; // trust compression is less than 2000% char *buf = new char[blen]; //printf("Doing decompress {%s}\n", zbuf); slen = 0; size_t zpos = 0; size_t bpos = 0; switch (lzma_stream_buffer_decode(&memlimit, 0, NULL, (const uint8_t*)zbuf, &zpos, (size_t)zlen, (uint8_t*)buf, &bpos, (size_t)&blen)){ case LZMA_OK: SendChars(buf, bpos); slen = bpos; break; case LZMA_FORMAT_ERROR: fprintf(stderr, "ERROR: format error encountered during decompression.\n"); break; case LZMA_OPTIONS_ERROR: fprintf(stderr, "ERROR: options error encountered during decompression.\n"); break; case LZMA_DATA_ERROR: fprintf(stderr, "ERROR: corrupt data during decompression.\n"); break; case LZMA_NO_CHECK: fprintf(stderr, "ERROR: no_check error encountered during decompression.\n"); break; case LZMA_UNSUPPORTED_CHECK: fprintf(stderr, "ERROR: unsupported_check error encountered during decompression.\n"); break; case LZMA_MEMLIMIT_ERROR: fprintf(stderr, "ERROR: memlimit error encountered during decompression.\n"); break; case LZMA_MEM_ERROR: fprintf(stderr, "ERROR: not enough memory during decompression.\n"); break; case LZMA_BUF_ERROR: fprintf(stderr, "ERROR: not enough room in the out buffer during decompression.\n"); break; case LZMA_PROG_ERROR: fprintf(stderr, "ERROR: program error encountered during decompression.\n"); break; default: fprintf(stderr, "ERROR: an unknown error occured during decompression.\n"); break; } delete [] buf; } else { fprintf(stderr, "ERROR: no buffer to decompress!\n"); } //printf("Finished decoding\n"); free (zbuf); }
Array<uint8_t> decompress(RawArray<const uint8_t> compressed, const size_t uncompressed_size, event_t event) { GEODE_ASSERT(uncompressed_size<(uint64_t)1<<31); thread_time_t time(decompress_kind,event); size_t dest_size = uncompressed_size; Array<uint8_t> uncompressed = aligned_buffer<uint8_t>(CHECK_CAST_INT(dest_size)); if (!is_lzma(compressed)) { // zlib int z = uncompress((uint8_t*)uncompressed.data(),&dest_size,compressed.data(),compressed.size()); if (z!=Z_OK) THROW(IOError,"zlib failure in read_and_uncompress: %s",zlib_error(z)); } else { // lzma const uint32_t flags = LZMA_TELL_NO_CHECK | LZMA_TELL_UNSUPPORTED_CHECK; uint64_t memlimit = UINT64_MAX; size_t in_pos = 0, out_pos = 0; lzma_ret r = lzma_stream_buffer_decode(&memlimit,flags,0,compressed.data(),&in_pos,compressed.size(),uncompressed.data(),&out_pos,dest_size); if (r!=LZMA_OK) THROW(IOError,"lzma failure in read_and_uncompress: %s (%d)",lzma_error(r),r); } if (dest_size != uncompressed_size) THROW(IOError,"read_and_compress: expected uncompressed size %zu, got %zu",uncompressed_size,dest_size); return uncompressed; }
void* gar_map(char* filename, size_t* out_length) { uint8_t* in_data; size_t in_length; if (!(in_data = platform_map(filename, &in_length))) return NULL; switch (gar_identify(in_data)) { case gar_uncompressed: *out_length = in_length; return in_data; case gar_xz_compressed: { uint8_t* out_data; size_t in_pos = 0; size_t out_pos = 0; uint8_t* ptr; uint64_t memlimit = 134217728; lzma_stream_flags flags; lzma_index *index; if ((ptr = in_data + in_length - 12) < in_data) goto error; if (lzma_stream_footer_decode(&flags, ptr) != LZMA_OK) goto error; if ((ptr -= flags.backward_size) < in_data) goto error; if (lzma_index_buffer_decode(&index, &memlimit, NULL, ptr, &in_pos, in_length - (ptr - in_data)) != LZMA_OK) goto error; memlimit = 134217728; *out_length = lzma_index_uncompressed_size(index); if (!(out_data = platform_virtualalloc(*out_length, mem_read | mem_write))) { lzma_index_end(index, NULL); goto error; } in_pos = 0; if (lzma_stream_buffer_decode(&memlimit, 0, NULL, in_data, &in_pos, in_length, out_data, &out_pos, *out_length) == LZMA_OK) { lzma_index_end(index, NULL); platform_unmap(in_data, in_length); if (gar_identify(out_data) != gar_uncompressed) { platform_virtualfree(out_data, *out_length); return NULL; } out_data[0] = 'a'; out_data[1] = 'n'; out_data[2] = 'o'; out_data[3] = 'n'; platform_virtualprotect(out_data, *out_length, mem_read); return out_data; } platform_virtualfree(out_data, *out_length); error: platform_unmap(in_data, in_length); return NULL; } default: platform_unmap(in_data, in_length); return NULL; } }