STATIC inline int INIT unlzo(u8 *input, int in_len, int (*fill) (void *, unsigned int), int (*flush) (void *, unsigned int), u8 *output, int *posp, void (*error) (char *x)) { u8 r = 0; int skip = 0; u32 src_len, dst_len; size_t tmp; u8 *in_buf, *in_buf_save, *out_buf; int ret = -1; if (output) { out_buf = output; } else if (!flush) { error("NULL output pointer and no flush function provided"); goto exit; } else { out_buf = malloc(LZO_BLOCK_SIZE); if (!out_buf) { error("Could not allocate output buffer"); goto exit; } } if (input && fill) { error("Both input pointer and fill function provided, don't know what to do"); goto exit_1; } else if (input) { in_buf = input; } else if (!fill) { error("NULL input pointer and missing fill function"); goto exit_1; } else { in_buf = malloc(lzo1x_worst_compress(LZO_BLOCK_SIZE)); if (!in_buf) { error("Could not allocate input buffer"); goto exit_1; } } in_buf_save = in_buf; if (posp) *posp = 0; if (fill) { /* * Start from in_buf + HEADER_SIZE_MAX to make it possible * to use memcpy() to copy the unused data to the beginning * of the buffer. This way memmove() isn't needed which * is missing from pre-boot environments of most archs. */ in_buf += HEADER_SIZE_MAX; in_len = fill(in_buf, HEADER_SIZE_MAX); } if (!parse_header(in_buf, &skip, in_len)) { error("invalid header"); goto exit_2; } in_buf += skip; in_len -= skip; if (fill) { /* Move the unused data to the beginning of the buffer. */ memcpy(in_buf_save, in_buf, in_len); in_buf = in_buf_save; } if (posp) *posp = skip; for (;;) { /* read uncompressed block size */ if (fill && in_len < 4) { skip = fill(in_buf + in_len, 4 - in_len); if (skip > 0) in_len += skip; } if (in_len < 4) { error("file corrupted"); goto exit_2; } dst_len = get_unaligned_be32(in_buf); in_buf += 4; in_len -= 4; /* exit if last block */ if (dst_len == 0) { if (posp) *posp += 4; break; } if (dst_len > LZO_BLOCK_SIZE) { error("dest len longer than block size"); goto exit_2; } /* read compressed block size, and skip block checksum info */ if (fill && in_len < 8) { skip = fill(in_buf + in_len, 8 - in_len); if (skip > 0) in_len += skip; } if (in_len < 8) { error("file corrupted"); goto exit_2; } src_len = get_unaligned_be32(in_buf); in_buf += 8; in_len -= 8; if (src_len <= 0 || src_len > dst_len) { error("file corrupted"); goto exit_2; } /* decompress */ if (fill && in_len < src_len) { skip = fill(in_buf + in_len, src_len - in_len); if (skip > 0) in_len += skip; } if (in_len < src_len) { error("file corrupted"); goto exit_2; } tmp = dst_len; /* When the input data is not compressed at all, * lzo1x_decompress_safe will fail, so call memcpy() * instead */ if (unlikely(dst_len == src_len)) memcpy(out_buf, in_buf, src_len); else { r = lzo1x_decompress_safe((u8 *) in_buf, src_len, out_buf, &tmp); if (r != LZO_E_OK || dst_len != tmp) { error("Compressed data violation"); goto exit_2; } } if (flush && flush(out_buf, dst_len) != dst_len) goto exit_2; if (output) out_buf += dst_len; if (posp) *posp += src_len + 12; in_buf += src_len; in_len -= src_len; if (fill) { /* * If there happens to still be unused data left in * in_buf, move it to the beginning of the buffer. * Use a loop to avoid memmove() dependency. */ if (in_len > 0) for (skip = 0; skip < in_len; ++skip) in_buf_save[skip] = in_buf[skip]; in_buf = in_buf_save; } } ret = 0; exit_2: if (!input) free(in_buf_save); exit_1: if (!output) free(out_buf); exit: return ret; }
static int zram_read(struct zram *zram, struct bio *bio) { int i; u32 index; struct bio_vec *bvec; if (unlikely(!zram->init_done)) { set_bit(BIO_UPTODATE, &bio->bi_flags); bio_endio(bio, 0); return 0; } zram_inc_stat(zram, ZRAM_STAT_NUM_READS); index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; bio_for_each_segment(bvec, bio, i) { int ret; size_t zlen; u32 zoffset; struct page *bio_page, *zpage; unsigned char *bio_mem, *zmem; bio_page = bvec->bv_page; if (zram_is_zero_page(zram, index)) { handle_zero_page(bio_page); continue; } zram_find_obj(zram, index, &zpage, &zoffset); /* Requested page is not present in compressed area */ if (unlikely(!zpage)) { pr_debug("Read before write on swap device: " "sector=%lu, size=%u", (ulong)(bio->bi_sector), bio->bi_size); /* Do nothing */ continue; } /* Page is stored uncompressed since it's incompressible */ if (unlikely(!zoffset)) { handle_uncompressed_page(zram, bio_page, index); continue; } bio_mem = kmap_atomic(bio_page, KM_USER0); zlen = PAGE_SIZE; zmem = kmap_atomic(zpage, KM_USER1) + zoffset; ret = lzo1x_decompress_safe(zmem, xv_get_object_size(zmem), bio_mem, &zlen); kunmap_atomic(bio_mem, KM_USER0); kunmap_atomic(zmem, KM_USER1); /* This should NEVER happen - return bio error if it does! */ if (unlikely(ret != LZO_E_OK)) { pr_err("Decompression failed! err=%d, page=%u\n", ret, index); goto out; } flush_dcache_page(bio_page); index++; }
size_t lzo_deflate (unsigned flags, size_t cd_nelmts, const unsigned cd_values[], size_t nbytes, size_t *buf_size, void **buf) { size_t ret_value = 0; #ifdef HAVE_LZO_LIB void *outbuf = NULL, *wrkmem = NULL; int status; size_t nalloc = *buf_size; lzo_uint out_len = (lzo_uint) nalloc; /* max_len_buffer will keep the likely output buffer size after processing the first chunk */ static unsigned int max_len_buffer = 0; int complevel = 1; int object_version = 10; /* Default version 1.0 */ int object_type = Table; /* Default object type */ #ifdef CHECKSUM lzo_uint32 checksum; #endif /* Check arguments */ /* For Table versions < 20, there were no parameters */ if (cd_nelmts==1 ) { complevel = cd_values[0]; /* This do nothing right now */ } else if (cd_nelmts==2 ) { complevel = cd_values[0]; /* This do nothing right now */ object_version = cd_values[1]; /* The table VERSION attribute */ } else if (cd_nelmts==3 ) { complevel = cd_values[0]; /* This do nothing right now */ object_version = cd_values[1]; /* The table VERSION attribute */ object_type = cd_values[2]; /* A tag for identifying the object (see tables.h) */ } #ifdef DEBUG printf("Object type: %d. ", object_type); printf("object_version:%d\n", object_version); #endif if (flags & H5Z_FLAG_REVERSE) { /* Input */ /* printf("Decompressing chunk with LZO\n"); */ #ifdef CHECKSUM if ((object_type == Table && object_version >= 20) || object_type != Table) { nbytes -= 4; /* Point to uncompressed buffer length */ memcpy(&nalloc, ((unsigned char *)(*buf)+nbytes), 4); out_len = nalloc; nbytes -= 4; /* Point to the checksum */ #ifdef DEBUG printf("Compressed bytes: %d. Uncompressed bytes: %d\n", nbytes, nalloc); #endif } #endif /* Only allocate the bytes for the outbuf */ if (max_len_buffer == 0) { if (NULL==(outbuf = (void *)malloc(nalloc))) fprintf(stderr, "Memory allocation failed for lzo uncompression.\n"); } else { if (NULL==(outbuf = (void *)malloc(max_len_buffer))) fprintf(stderr, "Memory allocation failed for lzo uncompression.\n"); out_len = max_len_buffer; nalloc = max_len_buffer; } while(1) { #ifdef DEBUG printf("nbytes -->%d\n", nbytes); printf("nalloc -->%d\n", nalloc); printf("max_len_buffer -->%d\n", max_len_buffer); #endif /* DEBUG */ /* The assembler version is a 10% slower than the C version with gcc 3.2.2 and gcc 3.3.3 */ /* status = lzo1x_decompress_asm_safe(*buf, (lzo_uint)nbytes, outbuf, */ /* &out_len, NULL); */ /* The safe and unsafe versions have the same speed more or less */ status = lzo1x_decompress_safe(*buf, (lzo_uint)nbytes, outbuf, &out_len, NULL); if (status == LZO_E_OK) { #ifdef DEBUG printf("decompressed %lu bytes back into %lu bytes\n", (long) nbytes, (long) out_len); #endif max_len_buffer = out_len; break; /* done */ } else if (status == LZO_E_OUTPUT_OVERRUN) { nalloc *= 2; out_len = (lzo_uint) nalloc; if (NULL==(outbuf = realloc(outbuf, nalloc))) { fprintf(stderr, "Memory allocation failed for lzo uncompression\n"); } } else { /* this should NEVER happen */ fprintf(stderr, "internal error - decompression failed: %d\n", status); ret_value = 0; /* fail */ goto done; } } #ifdef CHECKSUM if ((object_type == Table && object_version >= 20) || object_type != Table) { #ifdef DEBUG printf("Checksum uncompressing..."); #endif /* Compute the checksum */ checksum=lzo_adler32(lzo_adler32(0,NULL,0), outbuf, out_len); /* Compare */ if (memcmp(&checksum, (unsigned char*)(*buf)+nbytes, 4)) { ret_value = 0; /*fail*/ fprintf(stderr,"Checksum failed!.\n"); goto done; } } #endif /* CHECKSUM */ free(*buf); *buf = outbuf; outbuf = NULL; *buf_size = nalloc; ret_value = out_len; } else { /* * Output; compress but fail if the result would be larger than the * input. The library doesn't provide in-place compression, so we * must allocate a separate buffer for the result. */ lzo_byte *z_src = (lzo_byte*)(*buf); lzo_byte *z_dst; /*destination buffer */ lzo_uint z_src_nbytes = (lzo_uint)(nbytes); /* The next was the original computation for worst-case expansion */ /* I don't know why the difference with LZO1*. Perhaps some wrong docs in LZO package? */ /* lzo_uint z_dst_nbytes = (lzo_uint)(nbytes + (nbytes / 64) + 16 + 3); */ /* The next is for LZO1* algorithms */ /* lzo_uint z_dst_nbytes = (lzo_uint)(nbytes + (nbytes / 16) + 64 + 3); */ /* The next is for LZO2* algorithms. This will be the default */ lzo_uint z_dst_nbytes = (lzo_uint)(nbytes + (nbytes / 8) + 128 + 3); #ifdef CHECKSUM if ((object_type == Table && object_version >= 20) || object_type != Table) { z_dst_nbytes += 4+4; /* Checksum + buffer size */ } #endif if (NULL==(z_dst=outbuf=(void *)malloc(z_dst_nbytes))) { fprintf(stderr, "Unable to allocate lzo destination buffer.\n"); ret_value = 0; /* fail */ goto done; } /* Compress this buffer */ wrkmem = malloc(LZO1X_1_MEM_COMPRESS); if (wrkmem == NULL) { fprintf(stderr, "Memory allocation failed for lzo compression\n"); ret_value = 0; goto done; } status = lzo1x_1_compress (z_src, z_src_nbytes, z_dst, &z_dst_nbytes, wrkmem); free(wrkmem); wrkmem = NULL; #ifdef CHECKSUM if ((object_type == Table && object_version >= 20) || object_type != Table) { #ifdef DEBUG printf("Checksum compressing ..."); printf("src_nbytes: %d, dst_nbytes: %d\n", z_src_nbytes, z_dst_nbytes); #endif /* Append checksum of *uncompressed* data at the end */ checksum = lzo_adler32(lzo_adler32(0,NULL,0), *buf, nbytes); memcpy((unsigned char*)(z_dst)+z_dst_nbytes, &checksum, 4); memcpy((unsigned char*)(z_dst)+z_dst_nbytes+4, &nbytes, 4); z_dst_nbytes += (lzo_uint)4+4; nbytes += 4+4; } #endif if (z_dst_nbytes >= nbytes) { #ifdef DEBUG printf("The compressed buffer takes more space than uncompressed!.\n"); #endif ret_value = 0; /* fail */ goto done; } else if (LZO_E_OK != status) { fprintf(stderr,"lzo library error in compression\n"); ret_value = 0; /* fail */ goto done; } else { free(*buf); *buf = outbuf; outbuf = NULL; *buf_size = z_dst_nbytes; ret_value = z_dst_nbytes; } } done: if(outbuf) free(outbuf); #endif /* HAVE_LZO_LIB */ return ret_value; }
static int xc_try_lzo1x_decode( struct xc_dom_image *dom, void **blob, size_t *size) { int ret; const unsigned char *cur = dom->kernel_blob; unsigned char *out_buf = NULL; size_t left = dom->kernel_size; const char *msg; unsigned version; static const unsigned char magic[] = { 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a }; ret = lzo_init(); if ( ret != LZO_E_OK ) { DOMPRINTF("LZO1x: Failed to init library (%d)\n", ret); return -1; } if ( left < 16 || memcmp(cur, magic, 9) ) { DOMPRINTF("LZO1x: Unrecognized magic\n"); return -1; } /* get version (2bytes), skip library version (2), * 'need to be extracted' version (2) and method (1) */ version = lzo_read_16(cur + 9); cur += 16; left -= 16; if ( version >= 0x0940 ) { /* skip level */ ++cur; if ( left ) --left; } if ( left >= 4 && (lzo_read_32(cur) & LZOP_HEADER_HAS_FILTER) ) ret = 8; /* flags + filter info */ else ret = 4; /* flags */ /* skip mode and mtime_low */ ret += 8; if ( version >= 0x0940 ) ret += 4; /* skip mtime_high */ /* don't care about the file name, and skip checksum */ if ( left > ret ) ret += 1 + cur[ret] + 4; if ( left < ret ) { DOMPRINTF("LZO1x: Incomplete header\n"); return -1; } cur += ret; left -= ret; for ( *size = 0; ; ) { lzo_uint src_len, dst_len, out_len; unsigned char *tmp_buf; msg = "Short input"; if ( left < 4 ) break; dst_len = lzo_read_32(cur); if ( !dst_len ) return 0; if ( dst_len > LZOP_MAX_BLOCK_SIZE ) { msg = "Block size too large"; break; } if ( left < 12 ) break; src_len = lzo_read_32(cur + 4); cur += 12; /* also skip block checksum info */ left -= 12; msg = "Bad source length"; if ( src_len <= 0 || src_len > dst_len || src_len > left ) break; msg = "Failed to (re)alloc memory"; tmp_buf = realloc(out_buf, *size + dst_len); if ( tmp_buf == NULL ) break; out_buf = tmp_buf; out_len = dst_len; ret = lzo1x_decompress_safe(cur, src_len, out_buf + *size, &out_len, NULL); switch ( ret ) { case LZO_E_OK: msg = "Input underrun"; if ( out_len != dst_len ) break; *blob = out_buf; *size += out_len; cur += src_len; left -= src_len; continue; case LZO_E_INPUT_NOT_CONSUMED: msg = "Unconsumed input"; break; case LZO_E_OUTPUT_OVERRUN: msg = "Output overrun"; break; case LZO_E_INPUT_OVERRUN: msg = "Input overrun"; break; case LZO_E_LOOKBEHIND_OVERRUN: msg = "Look-behind overrun"; break; case LZO_E_EOF_NOT_FOUND: msg = "No EOF marker"; break; case LZO_E_ERROR: msg = "General error"; break; default: msg = "Internal program error (bug)"; break; } break; } free(out_buf); DOMPRINTF("LZO1x decompression error: %s\n", msg); return -1; }
static int decompress_lzo(struct btrfs_root *root, unsigned char *inbuf, char *outbuf, u64 compress_len, u64 *decompress_len) { size_t new_len; size_t in_len; size_t out_len = 0; size_t tot_len; size_t tot_in; int ret; ret = lzo_init(); if (ret != LZO_E_OK) { error("lzo init returned %d", ret); return -1; } tot_len = read_compress_length(inbuf); inbuf += LZO_LEN; tot_in = LZO_LEN; while (tot_in < tot_len) { size_t mod_page; size_t rem_page; in_len = read_compress_length(inbuf); if ((tot_in + LZO_LEN + in_len) > tot_len) { error("bad compress length %lu", (unsigned long)in_len); return -1; } inbuf += LZO_LEN; tot_in += LZO_LEN; new_len = lzo1x_worst_compress(root->sectorsize); ret = lzo1x_decompress_safe((const unsigned char *)inbuf, in_len, (unsigned char *)outbuf, (void *)&new_len, NULL); if (ret != LZO_E_OK) { error("lzo decompress failed: %d", ret); return -1; } out_len += new_len; outbuf += new_len; inbuf += in_len; tot_in += in_len; /* * If the 4 byte header does not fit to the rest of the page we * have to move to the next one, unless we read some garbage */ mod_page = tot_in % root->sectorsize; rem_page = root->sectorsize - mod_page; if (rem_page < LZO_LEN) { inbuf += rem_page; tot_in += rem_page; } } *decompress_len = out_len; return 0; }
int __lzo_cdecl_main main(int argc, char *argv[]) { int r; int lazy; const int max_try_lazy = 5; const lzo_uint big = 65536L; /* can result in very slow compression */ const lzo_uint32_t flags = 0x1; lzo_bytep in; lzo_uint in_len; lzo_bytep out; lzo_uint out_bufsize; lzo_uint out_len = 0; lzo_voidp wrkmem; lzo_uint wrkmem_size; lzo_uint best_len; int best_compress = -1; int best_lazy = -1; lzo_uint orig_len; lzo_uint32_t uncompressed_checksum; lzo_uint32_t compressed_checksum; FILE *fp; const char *in_name = NULL; const char *out_name = NULL; long l; lzo_wildargv(&argc, &argv); printf("\nLZO real-time data compression library (v%s, %s).\n", lzo_version_string(), lzo_version_date()); printf("Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer\nAll Rights Reserved.\n\n"); progname = argv[0]; if (argc < 2 || argc > 3) { printf("usage: %s file [output-file]\n", progname); exit(1); } in_name = argv[1]; if (argc > 2) out_name = argv[2]; /* * Step 1: initialize the LZO library */ if (lzo_init() != LZO_E_OK) { printf("internal error - lzo_init() failed !!!\n"); printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable '-DLZO_DEBUG' for diagnostics)\n"); exit(1); } /* * Step 2: allocate the work-memory */ wrkmem_size = 1; #ifdef USE_LZO1X wrkmem_size = (LZO1X_999_MEM_COMPRESS > wrkmem_size) ? LZO1X_999_MEM_COMPRESS : wrkmem_size; #endif #ifdef USE_LZO1Y wrkmem_size = (LZO1Y_999_MEM_COMPRESS > wrkmem_size) ? LZO1Y_999_MEM_COMPRESS : wrkmem_size; #endif wrkmem = (lzo_voidp) xmalloc(wrkmem_size); if (wrkmem == NULL) { printf("%s: out of memory\n", progname); exit(1); } /* * Step 3: open the input file */ fp = fopen(in_name,"rb"); if (fp == NULL) { printf("%s: cannot open file %s\n", progname, in_name); exit(1); } fseek(fp, 0, SEEK_END); l = ftell(fp); fseek(fp, 0, SEEK_SET); if (l <= 0) { printf("%s: %s: empty file\n", progname, in_name); fclose(fp); fp = NULL; exit(1); } in_len = (lzo_uint) l; out_bufsize = in_len + in_len / 16 + 64 + 3; best_len = in_len; /* * Step 4: allocate compression buffers and read the file */ in = (lzo_bytep) xmalloc(in_len); out = (lzo_bytep) xmalloc(out_bufsize); if (in == NULL || out == NULL) { printf("%s: out of memory\n", progname); exit(1); } in_len = (lzo_uint) lzo_fread(fp, in, in_len); printf("%s: loaded file %s: %ld bytes\n", progname, in_name, (long) in_len); fclose(fp); fp = NULL; /* * Step 5: compute a checksum of the uncompressed data */ uncompressed_checksum = lzo_adler32(0,NULL,0); uncompressed_checksum = lzo_adler32(uncompressed_checksum,in,in_len); /* * Step 6a: compress from 'in' to 'out' with LZO1X-999 */ #ifdef USE_LZO1X for (lazy = 0; lazy <= max_try_lazy; lazy++) { out_len = out_bufsize; r = lzo1x_999_compress_internal(in,in_len,out,&out_len,wrkmem, NULL, 0, 0, lazy, big, big, big, big, flags); if (r != LZO_E_OK) { /* this should NEVER happen */ printf("internal error - compression failed: %d\n", r); exit(1); } printf("LZO1X-999: lazy =%2d: %8lu -> %8lu\n", lazy, (unsigned long) in_len, (unsigned long) out_len); if (out_len < best_len) { best_len = out_len; best_lazy = lazy; best_compress = 1; /* LZO1X-999 */ } } #endif /* USE_LZO1X */ /* * Step 6b: compress from 'in' to 'out' with LZO1Y-999 */ #ifdef USE_LZO1Y for (lazy = 0; lazy <= max_try_lazy; lazy++) { out_len = out_bufsize; r = lzo1y_999_compress_internal(in,in_len,out,&out_len,wrkmem, NULL, 0, 0, lazy, big, big, big, big, flags); if (r != LZO_E_OK) { /* this should NEVER happen */ printf("internal error - compression failed: %d\n", r); exit(1); } printf("LZO1Y-999: lazy =%2d: %8lu -> %8lu\n", lazy, (unsigned long) in_len, (unsigned long) out_len); if (out_len < best_len) { best_len = out_len; best_lazy = lazy; best_compress = 2; /* LZO1Y-999 */ } } #endif /* USE_LZO1Y */ /* * Step 7: check if compressible */ if (best_len >= in_len) { printf("This file contains incompressible data.\n"); return 0; } /* * Step 8: compress data again using the best compressor found */ out_len = out_bufsize; if (best_compress == 1) r = lzo1x_999_compress_internal(in,in_len,out,&out_len,wrkmem, NULL, 0, 0, best_lazy, big, big, big, big, flags); else if (best_compress == 2) r = lzo1y_999_compress_internal(in,in_len,out,&out_len,wrkmem, NULL, 0, 0, best_lazy, big, big, big, big, flags); else r = -100; assert(r == LZO_E_OK); assert(out_len == best_len); /* * Step 9: optimize compressed data (compressed data is in 'out' buffer) */ #if 1 /* Optimization does not require any data in the buffer that will * hold the uncompressed data. To prove this, we clear the buffer. */ lzo_memset(in,0,in_len); #endif orig_len = in_len; r = -100; #ifdef USE_LZO1X if (best_compress == 1) r = lzo1x_optimize(out,out_len,in,&orig_len,NULL); #endif #ifdef USE_LZO1Y if (best_compress == 2) r = lzo1y_optimize(out,out_len,in,&orig_len,NULL); #endif if (r != LZO_E_OK || orig_len != in_len) { /* this should NEVER happen */ printf("internal error - optimization failed: %d\n", r); exit(1); } /* * Step 10: compute a checksum of the compressed data */ compressed_checksum = lzo_adler32(0,NULL,0); compressed_checksum = lzo_adler32(compressed_checksum,out,out_len); /* * Step 11: write compressed data to a file */ printf("%s: %s: %ld -> %ld, checksum 0x%08lx 0x%08lx\n", progname, in_name, (long) in_len, (long) out_len, (long) uncompressed_checksum, (long) compressed_checksum); if (out_name && out_name[0]) { printf("%s: writing to file %s\n", progname, out_name); fp = fopen(out_name,"wb"); if (fp == NULL) { printf("%s: cannot open output file %s\n", progname, out_name); exit(1); } if (lzo_fwrite(fp, out, out_len) != out_len || fclose(fp) != 0) { printf("%s: write error !!\n", progname); exit(1); } } /* * Step 12: verify decompression */ #ifdef PARANOID lzo_memset(in,0,in_len); /* paranoia - clear output buffer */ orig_len = in_len; r = -100; #ifdef USE_LZO1X if (best_compress == 1) r = lzo1x_decompress_safe(out,out_len,in,&orig_len,NULL); #endif #ifdef USE_LZO1Y if (best_compress == 2) r = lzo1y_decompress_safe(out,out_len,in,&orig_len,NULL); #endif if (r != LZO_E_OK || orig_len != in_len) { /* this should NEVER happen */ printf("internal error - decompression failed: %d\n", r); exit(1); } if (uncompressed_checksum != lzo_adler32(lzo_adler32(0,NULL,0),in,in_len)) { /* this should NEVER happen */ printf("internal error - decompression data error\n"); exit(1); } /* Now you could also verify decompression under similar conditions as in * your application, e.g. overlapping assembler decompression etc. */ #endif lzo_free(in); lzo_free(out); lzo_free(wrkmem); return 0; }
lzo_bool lzo_decompress(file_t *fip, file_t *fop, const header_t *h, lzo_bool skip) { int r; lzo_uint32 src_len, dst_len; lzo_uint32 c_adler32 = ADLER32_INIT_VALUE, d_adler32 = ADLER32_INIT_VALUE; lzo_uint32 c_crc32 = CRC32_INIT_VALUE, d_crc32 = CRC32_INIT_VALUE; lzo_bool ok = 1; lzo_bool use_seek; mblock_t * const block = &blocks[1]; lzo_bytep b1; lzo_bytep const b2 = block->mb_mem; use_seek = skip || opt_cmd == CMD_LIST || opt_cmd == CMD_LS || opt_cmd == CMD_INFO; for (;;) { lzo_bytep dst; /* read uncompressed block size */ read32(fip,&dst_len); /* exit if last block */ if (dst_len == 0) break; /* error if split file */ if (dst_len == 0xffffffffUL) { /* should not happen - not yet implemented */ error(fip,"this file is a split " PACKAGE " file"); ok = 0; break; } if (dst_len > MAX_BLOCK_SIZE) { error(fip, PACKAGE " file corrupted"); ok = 0; break; } /* read compressed block size */ read32(fip,&src_len); if (src_len <= 0 || src_len > dst_len) { error(fip, PACKAGE " file corrupted"); ok = 0; break; } if (dst_len > BLOCK_SIZE) { fatal(fip,"block size too small -- recompile " PACKAGE); ok = 0; break; } if (dst_len > block_size) { /* should not happen - not yet implemented */ fatal(fip,"block size too small -- use option `--blocksize'"); ok = 0; break; } assert(block->mb_size >= src_len); /* read checksum of uncompressed block */ if (h->flags & F_ADLER32_D) read32(fip,&d_adler32); if (h->flags & F_CRC32_D) read32(fip,&d_crc32); /* read checksum of compressed block */ if (h->flags & F_ADLER32_C) { if (src_len < dst_len) read32(fip,&c_adler32); else { assert(h->flags & F_ADLER32_D); c_adler32 = d_adler32; } } if (h->flags & F_CRC32_C) { if (src_len < dst_len) read32(fip,&c_crc32); else { assert(h->flags & F_CRC32_D); c_crc32 = d_crc32; } } /* read the block */ b1 = block->mb_mem + block->mb_size - src_len; if (use_seek && fip->fd != STDIN_FILENO) { if (lseek(fip->fd, src_len, SEEK_CUR) == -1) read_error(fip); } else { if (read_buf(fip, b1, src_len) != (lzo_int) src_len) read_error(fip); } fip->bytes_processed += src_len; if (use_seek) { fop->bytes_processed += dst_len; continue; } assert(block->mb_size >= MAX_COMPRESSED_SIZE(dst_len)); /* verify checksum of compressed block */ if (opt_checksum && (h->flags & F_ADLER32_C)) { lzo_uint32 c; c = lzo_adler32(ADLER32_INIT_VALUE,b1,src_len); if (c != c_adler32) { error(fip,"Checksum error (" PACKAGE " file corrupted)"); ok = 0; break; } } if (opt_checksum && (h->flags & F_CRC32_C)) { lzo_uint32 c; c = lzo_crc32(CRC32_INIT_VALUE,b1,src_len); if (c != c_crc32) { error(fip,"Checksum error (" PACKAGE " file corrupted)"); ok = 0; break; } } if (src_len < dst_len) { lzo_uint d = dst_len; /* decompress */ if (opt_decompress_safe) r = lzo1x_decompress_safe(b1,src_len,b2,&d,NULL); else r = lzo1x_decompress(b1,src_len,b2,&d,NULL); if (r != LZO_E_OK || dst_len != d) { error(fip,"Compressed data violation"); #if 0 fprintf(stderr,"%d %ld %ld\n", r, (long)dst_len, (long)d); #endif ok = 0; break; } dst = b2; } else { assert(dst_len == src_len); dst = b1; } x_filter(dst,dst_len,h); /* verify checksum of uncompressed block */ if (opt_checksum && (h->flags & F_ADLER32_D)) { lzo_uint32 c; c = lzo_adler32(ADLER32_INIT_VALUE,dst,dst_len); if (c != d_adler32) { error(fip,"Checksum error"); ok = 0; break; } } if (opt_checksum && (h->flags & F_CRC32_D)) { lzo_uint32 c; c = lzo_crc32(CRC32_INIT_VALUE,dst,dst_len); if (c != d_crc32) { error(fip,"Checksum error"); ok = 0; break; } } /* write uncompressed block data */ write_buf(fop,dst,dst_len); fop->bytes_processed += dst_len; } return ok; }
STATIC inline int INIT unlzo(u8 *input, int in_len, int (*fill) (void *, unsigned int), int (*flush) (void *, unsigned int), u8 *output, int *posp, void (*error_fn) (char *x)) { u8 skip = 0, r = 0; u32 src_len, dst_len; size_t tmp; u8 *in_buf, *in_buf_save, *out_buf; int obytes_processed = 0; set_error_fn(error_fn); if (output) out_buf = output; else if (!flush) { error("NULL output pointer and no flush function provided"); goto exit; } else { out_buf = malloc(LZO_BLOCK_SIZE); if (!out_buf) { error("Could not allocate output buffer"); goto exit; } } if (input && fill) { error("Both input pointer and fill function provided, don't know what to do"); goto exit_1; } else if (input) in_buf = input; else if (!fill || !posp) { error("NULL input pointer and missing position pointer or fill function"); goto exit_1; } else { in_buf = malloc(lzo1x_worst_compress(LZO_BLOCK_SIZE)); if (!in_buf) { error("Could not allocate input buffer"); goto exit_1; } } in_buf_save = in_buf; if (posp) *posp = 0; if (fill) fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE)); if (!parse_header(input, &skip)) { error("invalid header"); goto exit_2; } in_buf += skip; if (posp) *posp = skip; for (;;) { /* read uncompressed block size */ dst_len = get_unaligned_be32(in_buf); in_buf += 4; /* exit if last block */ if (dst_len == 0) { if (posp) *posp += 4; break; } if (dst_len > LZO_BLOCK_SIZE) { error("dest len longer than block size"); goto exit_2; } /* read compressed block size, and skip block checksum info */ src_len = get_unaligned_be32(in_buf); in_buf += 8; if (src_len <= 0 || src_len > dst_len) { error("file corrupted"); goto exit_2; } /* decompress */ tmp = dst_len; r = lzo1x_decompress_safe((u8 *) in_buf, src_len, out_buf, &tmp); if (r != LZO_E_OK || dst_len != tmp) { error("Compressed data violation"); goto exit_2; } obytes_processed += dst_len; if (flush) flush(out_buf, dst_len); if (output) out_buf += dst_len; if (posp) *posp += src_len + 12; if (fill) { in_buf = in_buf_save; fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE)); } else in_buf += src_len; } exit_2: if (!input) free(in_buf); exit_1: if (!output) free(out_buf); exit: return obytes_processed; }
static ssize_t lzop_filter_read(struct archive_read_filter *self, const void **p) { struct read_lzop *state = (struct read_lzop *)self->data; const void *b; lzo_uint out_size; uint32_t cksum; int ret, r; if (state->unconsumed_bytes) { __archive_read_filter_consume(self->upstream, state->unconsumed_bytes); state->unconsumed_bytes = 0; } if (state->eof) return (0); for (;;) { if (!state->in_stream) { ret = consume_header(self); if (ret < ARCHIVE_OK) return (ret); if (ret == ARCHIVE_EOF) { state->eof = 1; return (0); } } ret = consume_block_info(self); if (ret < ARCHIVE_OK) return (ret); if (ret == ARCHIVE_EOF) state->in_stream = 0; else break; } if (state->out_block == NULL || state->out_block_size < state->uncompressed_size) { void *new_block; new_block = realloc(state->out_block, state->uncompressed_size); if (new_block == NULL) { archive_set_error(&self->archive->archive, ENOMEM, "Can't allocate data for lzop decompression"); return (ARCHIVE_FATAL); } state->out_block = new_block; state->out_block_size = state->uncompressed_size; } b = __archive_read_filter_ahead(self->upstream, state->compressed_size, NULL); if (b == NULL) { archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); return (ARCHIVE_FATAL); } if (state->flags & CRC32_COMPRESSED) cksum = crc32(crc32(0, NULL, 0), b, state->compressed_size); else if (state->flags & ADLER32_COMPRESSED) cksum = adler32(adler32(0, NULL, 0), b, state->compressed_size); else cksum = state->compressed_cksum; if (cksum != state->compressed_cksum) { archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "Corrupted data"); return (ARCHIVE_FATAL); } /* * If the both uncompressed size and compressed size are the same, * we do not decompress this block. */ if (state->uncompressed_size == state->compressed_size) { *p = b; state->total_out += state->compressed_size; state->unconsumed_bytes = state->compressed_size; return ((ssize_t)state->uncompressed_size); } /* * Drive lzo uncompresison. */ out_size = (lzo_uint)state->uncompressed_size; r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size, state->out_block, &out_size, NULL); switch (r) { case LZO_E_OK: if (out_size == state->uncompressed_size) break; archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "Corrupted data"); return (ARCHIVE_FATAL); case LZO_E_OUT_OF_MEMORY: archive_set_error(&self->archive->archive, ENOMEM, "lzop decompression failed: out of memory"); return (ARCHIVE_FATAL); default: archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "lzop decompression failed: %d", r); return (ARCHIVE_FATAL); } if (state->flags & CRC32_UNCOMPRESSED) cksum = crc32(crc32(0, NULL, 0), state->out_block, state->uncompressed_size); else if (state->flags & ADLER32_UNCOMPRESSED) cksum = adler32(adler32(0, NULL, 0), state->out_block, state->uncompressed_size); else cksum = state->uncompressed_cksum; if (cksum != state->uncompressed_cksum) { archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "Corrupted data"); return (ARCHIVE_FATAL); } __archive_read_filter_consume(self->upstream, state->compressed_size); *p = state->out_block; state->total_out += out_size; return ((ssize_t)out_size); }
static bool decompress_with_lzo(JCR *jcr, const char *last_fname, char **data, uint32_t *length, bool sparse, bool want_data_stream) { char ec1[50]; /* Buffer printing huge values */ lzo_uint compress_len; const unsigned char *cbuf; unsigned char *wbuf; int status, real_compress_len; if (sparse && want_data_stream) { compress_len = jcr->compress.inflate_buffer_size - OFFSET_FADDR_SIZE; cbuf = (const unsigned char *)*data + OFFSET_FADDR_SIZE + sizeof(comp_stream_header); wbuf = (unsigned char *)jcr->compress.inflate_buffer + OFFSET_FADDR_SIZE; } else { compress_len = jcr->compress.inflate_buffer_size; cbuf = (const unsigned char *)*data + sizeof(comp_stream_header); wbuf = (unsigned char *)jcr->compress.inflate_buffer; } real_compress_len = *length - sizeof(comp_stream_header); Dmsg2(400, "Comp_len=%d msglen=%d\n", compress_len, *length); while ((status = lzo1x_decompress_safe(cbuf, real_compress_len, wbuf, &compress_len, NULL)) == LZO_E_OUTPUT_OVERRUN) { /* * The buffer size is too small, try with a bigger one */ jcr->compress.inflate_buffer_size = jcr->compress.inflate_buffer_size + (jcr->compress.inflate_buffer_size >> 1); jcr->compress.inflate_buffer = check_pool_memory_size(jcr->compress.inflate_buffer, jcr->compress.inflate_buffer_size); if (sparse && want_data_stream) { compress_len = jcr->compress.inflate_buffer_size - OFFSET_FADDR_SIZE; wbuf = (unsigned char *)jcr->compress.inflate_buffer + OFFSET_FADDR_SIZE; } else { compress_len = jcr->compress.inflate_buffer_size; wbuf = (unsigned char *)jcr->compress.inflate_buffer; } Dmsg2(400, "Comp_len=%d msglen=%d\n", compress_len, *length); } if (status != LZO_E_OK) { Qmsg(jcr, M_ERROR, 0, _("LZO uncompression error on file %s. ERR=%d\n"), last_fname, status); return false; } /* * We return a decompressed data stream with the fileoffset encoded when this was a sparse stream. */ if (sparse && want_data_stream) { memcpy(jcr->compress.inflate_buffer, *data, OFFSET_FADDR_SIZE); } *data = jcr->compress.inflate_buffer; *length = compress_len; Dmsg2(400, "Write uncompressed %d bytes, total before write=%s\n", compress_len, edit_uint64(jcr->JobBytes, ec1)); return true; }
static int _fill_decompressed_buffer(struct compressed_chunk_s * chunk, gsize to_skip) { DEBUG("_fill_decompressed_buffer: START\n"); gsize nb_read; gsize in_len; gulong out_len; gsize total_skipped = 0; int r; if(chunk->buf) g_free(chunk->buf); chunk->buf = NULL; chunk->buf_len = 0; chunk->buf_offset = 0; chunk->data_len = 0; while(1) { /* read uncompressed size */ nb_read = 0; nb_read = fread(&out_len, sizeof(out_len), 1, chunk->fd); if (nb_read != 1) { DEBUG("Failed to read compressed chunk size"); return -1; } /* exit if last block (EOF marker) */ if(out_len == 0) { return 0; } /* read compressed size */ in_len = 0; nb_read = 0; nb_read = fread(&in_len, sizeof(in_len), 1, chunk->fd); if (nb_read != 1) { return -1; } /* check if we are in good block */ if(to_skip < total_skipped + out_len) { /* data in this block */ chunk->data_len = out_len; chunk->buf_offset = to_skip - total_skipped; break; } else { /* don't need to uncompress this block, go to the next */ total_skipped += out_len; if(fseek(chunk->fd, in_len, SEEK_CUR)) { /* fseek issue */ return -1; } } } /* Consider the "to_skip" bytes already read */ chunk->read += to_skip; DEBUG("_fill_decompressed_buffer: current block compressed size (read from file): %"G_GSIZE_FORMAT, in_len); DEBUG("_fill_decompressed_buffer: block_size = %u", (uint)chunk->block_size); /* sanity check of the size values */ if (in_len > chunk->block_size || chunk->data_len > chunk->block_size || in_len == 0 || in_len > chunk->data_len){ DEBUG("_fill_decompressed_buffer: block size error - data corrupted"); r = -1; goto err; } DEBUG("_fill_decompressed_buffer: ok, data not corrupted, it's time to work"); /* Manage the case of uncompressed data */ if (in_len == chunk->data_len) { chunk->buf_len = chunk->data_len; chunk->buf = g_malloc0(chunk->buf_len); nb_read = 0; nb_read = fread(chunk->buf, chunk->buf_len, 1, chunk->fd); if (nb_read != 1) { DEBUG("Failed to read uncompressed block"); r = -1; goto err; } } else { /* in_len < chunk->data_len */ lzo_bytep in; lzo_uint new_len; chunk->buf_len = chunk->data_len; chunk->buf = g_malloc0(chunk->buf_len); DEBUG("_fill_uncompressed_buffer: before lzo1x_decompress_safe" " (input=%u max_out=%u expected=%u)\n", (uint)in_len, (uint)chunk->buf_len, (uint)chunk->data_len); in = g_malloc0(in_len); nb_read = 0; nb_read = fread(in, in_len, 1, chunk->fd); if (nb_read != 1) { g_free(in); DEBUG("Failed to read compressed block"); r = -1; goto err; } /* decompress - use safe decompressor as data might be corrupted * during a file transfer */ new_len = chunk->buf_len; r = lzo1x_decompress_safe(in, in_len, chunk->buf, &new_len, NULL); g_free(in); if (r != LZO_E_OK || new_len != chunk->data_len) { DEBUG("_fill_uncompressed_buffer: compressed data violation" " (input=%u max_out=%u expected=%u got=%u)\n", (uint)in_len, (uint)chunk->buf_len, (uint)chunk->data_len, (uint)new_len); r = -1; goto err; } DEBUG("_fill_uncompressed_buffer: afetr lzo1x_decompress_safe" " (input=%u max_out=%u expected=%u got=%u)\n", (uint)in_len, (uint)chunk->buf_len, (uint)chunk->data_len, (uint)new_len); } /* update checksum */ if (chunk->flags & LZO_FLAG_CHECKSUM) { DEBUG("data used for checksum : %u\n", (uint)chunk->data_len); lzo_uint32 checksum32 = 0; checksum32 = chunk->checksum; checksum32 = lzo_adler32(checksum32, chunk->buf, chunk->data_len); chunk->checksum = checksum32; DEBUG("_fill_decompressed_buffer: checksum updated\n"); } r = 1; err: return r; }
static int zram_read(struct zram *zram, struct bio *bio) { int i; u32 index; struct bio_vec *bvec; if (unlikely(!zram->init_done)) { set_bit(BIO_UPTODATE, &bio->bi_flags); bio_endio(bio, 0); return 0; } zram_stat64_inc(zram, &zram->stats.num_reads); index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; bio_for_each_segment(bvec, bio, i) { int ret; size_t clen; struct page *page; struct zobj_header *zheader; unsigned char *user_mem, *cmem; page = bvec->bv_page; if (zram_test_flag(zram, index, ZRAM_ZERO)) { handle_zero_page(page); index++; continue; } /* Requested page is not present in compressed area */ if (unlikely(!zram->table[index].page)) { pr_debug("Read before write: sector=%lu, size=%u", (ulong)(bio->bi_sector), bio->bi_size); /* Do nothing */ index++; continue; } /* Page is stored uncompressed since it's incompressible */ if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) { handle_uncompressed_page(zram, page, index); index++; continue; } user_mem = kmap_atomic(page, KM_USER0); clen = PAGE_SIZE; cmem = kmap_atomic(zram->table[index].page, KM_USER1) + zram->table[index].offset; ret = lzo1x_decompress_safe( cmem + sizeof(*zheader), xv_get_object_size(cmem) - sizeof(*zheader), user_mem, &clen); kunmap_atomic(user_mem, KM_USER0); kunmap_atomic(cmem, KM_USER1); /* Should NEVER happen. Return bio error if it does. */ if (unlikely(ret != LZO_E_OK)) { pr_err("Decompression failed! err=%d, page=%u\n", ret, index); zram_stat64_inc(zram, &zram->stats.failed_reads); goto out; } flush_dcache_page(page); index++; }
bool xboxIMGCompression::Decompress( CFile *input, CFile *output ) { // Make sure we have LZO. this->InitializeLZO(); if ( !this->isUsingLZO ) { // We cannot continue if LZO has failed to initialize. return false; } bool decompressionSuccess = false; // Determine what kind of compression we have and decompress. fsUInt_t magic = 0; bool couldReadMagic = input->ReadUInt( magic ); if ( couldReadMagic ) { // Also read the compression header. compressionHeader header; bool couldReadHeader = input->ReadStruct( header ); if ( couldReadHeader ) { // lzo1x(-999) if ( magic == 0x67A3A1CE ) { // Prepare a memory block that will be used as compression buffer. void *compressedFileData = malloc( header.blockSize ); // Copy the work buffer over fast. // This leaves the decompress buffer in our class in an invalid state. simpleWorkBuffer localDecompressBuffer = this->decompressBuffer; bool hasDecompressBufferChanged = false; // Make sure we have got any decompression buffer before we start. bool hasAllocatedMinimum = localDecompressBuffer.MinimumSize( minimumDecompressBufferSize ); if ( hasAllocatedMinimum ) { hasDecompressBufferChanged = true; } if ( compressedFileData && localDecompressBuffer.IsReady() ) { size_t segmentRemaining = header.blockSize; bool lzoSuccess = true; checksumCallback_t _checksumCallback = NULL; if ( _performLZOChecksumVerify ) { _checksumCallback = this->_checksumCallback; } // Verify the checksum. lzo_uint32_t checksum = 0; if ( _checksumCallback != NULL ) { checksum = _checksumCallback( 0, NULL, 0 ); } // Read all blocks. while ( true ) { // Check whether we reached the end. if ( segmentRemaining == 0 ) { // We can safely exit the loop here. break; } // Read the block header. perBlockHeader blockHeader; bool couldReadBlock = input->ReadStruct( blockHeader ); if ( !couldReadBlock ) { lzoSuccess = false; break; } // Verify that this block is valid. if ( blockHeader.compressedSize > header.blockSize ) { lzoSuccess = false; break; } // Check some non-trivial stuff. if ( blockHeader.unk != 4 || blockHeader.compressedSize != blockHeader.uncompressedSize ) { lzoSuccess = false; break; } // Read the compressed block. size_t dataReadCount = input->Read( compressedFileData, 1, blockHeader.compressedSize ); if ( dataReadCount != blockHeader.compressedSize ) { lzoSuccess = false; break; } repeatDecompress: // Decompress our block. void *decompressBuffer = localDecompressBuffer.GetPointer(); lzo_uint realDecompressedSize = localDecompressBuffer.GetSize(); int lzoerr = lzo1x_decompress_safe( (const unsigned char*)compressedFileData, blockHeader.compressedSize, (unsigned char*)decompressBuffer, &realDecompressedSize, NULL ); // Handle valid errors. if ( lzoerr == LZO_E_OUTPUT_OVERRUN ) { // Increase buffer size. localDecompressBuffer.Grow( realDecompressedSize ); // Remember that we updated the decompression buffer. hasDecompressBufferChanged = true; // Try again. goto repeatDecompress; } if ( lzoerr != LZO_E_OK ) { lzoSuccess = false; break; } // Write the decompressed stuff into the file. output->Write( decompressBuffer, 1, realDecompressedSize ); if ( _checksumCallback != NULL ) { // Update checksum. checksum = _checksumCallback( checksum, decompressBuffer, realDecompressedSize ); } // Decrease the remaining bytes. size_t processedSize = ( blockHeader.compressedSize + sizeof( blockHeader ) ); if ( segmentRemaining < processedSize ) { lzoSuccess = false; break; } segmentRemaining -= processedSize; } if ( lzoSuccess ) { // Verify the checksum. bool isDataValid = true; if ( isDataValid && ( _checksumCallback != NULL ) ) { bool isChecksumValid = ( checksum == header.checksum ); if ( !isChecksumValid ) { isDataValid = false; } } if ( isDataValid ) { // If we succeeded, we have got decompressed data in the output stream. decompressionSuccess = true; } } } // Clean up. if ( compressedFileData ) { free( compressedFileData ); } // Update the decompress buffer. if ( hasDecompressBufferChanged ) { // Validate the decompress buffer in our class again. this->decompressBuffer = localDecompressBuffer; } // Release our buffer so we do not free it. localDecompressBuffer.Release(); } } } return decompressionSuccess; }
int appDecompress(byte *CompressedBuffer, int CompressedSize, byte *UncompressedBuffer, int UncompressedSize, int Flags) { guard(appDecompress); #if BLADENSOUL if (GForceGame == GAME_BladeNSoul && Flags == COMPRESS_LZO_ENC_BNS) // note: GForceGame is required (to not pass 'Game' here) { if (CompressedSize >= 32) { static const char *key = "qiffjdlerdoqymvketdcl0er2subioxq"; for (int i = 0; i < CompressedSize; i++) CompressedBuffer[i] ^= key[i % 32]; } // overide compression Flags = COMPRESS_LZO; } #endif // BLADENSOUL #if SMITE if (GForceGame == GAME_Smite && Flags == COMPRESS_LZO_ENC_SMITE) { for (int i = 0; i < CompressedSize; i++) CompressedBuffer[i] ^= 0x2A; // overide compression Flags = COMPRESS_LZO; } #endif // SMITE #if TAO_YUAN if (GForceGame == GAME_TaoYuan) // note: GForceGame is required (to not pass 'Game' here); { static const byte key[] = { 137, 35, 95, 142, 69, 136, 243, 119, 25, 35, 111, 94, 101, 136, 243, 204, 243, 67, 95, 158, 69, 106, 107, 187, 237, 35, 103, 142, 72, 142, 243 }; for (int i = 0; i < CompressedSize; i++) CompressedBuffer[i] ^= key[i % 31]; // note: "N % 31" is not the same as "N & 0x1F" } #endif // TAO_YUAN #if ALICE // this code exists in Alice: Madness Returns only if (GForceGame == GAME_Alice && CompressedSize == UncompressedSize) { // CompressedSize == UncompressedSize -> no compression memcpy(UncompressedBuffer, CompressedBuffer, UncompressedSize); return UncompressedSize; } #endif // ALICE if (Flags == COMPRESS_FIND && CompressedSize >= 2) { byte b1 = CompressedBuffer[0]; byte b2 = CompressedBuffer[1]; // detect compression // zlib: // http://tools.ietf.org/html/rfc1950 // http://stackoverflow.com/questions/9050260/what-does-a-zlib-header-look-like if ( b1 == 0x78 && // b1=CMF: 7=32k buffer (CINFO), 8=deflate (CM) (b2 == 0x9C || b2 == 0xDA) ) // b2=FLG { Flags = COMPRESS_ZLIB; } else Flags = COMPRESS_LZO; } if (Flags == COMPRESS_LZO) { int r; r = lzo_init(); if (r != LZO_E_OK) appError("lzo_init() returned %d", r); lzo_uint newLen = UncompressedSize; r = lzo1x_decompress_safe(CompressedBuffer, CompressedSize, UncompressedBuffer, &newLen, NULL); if (r != LZO_E_OK) appError("lzo_decompress(%d,%d) returned %d", CompressedSize, UncompressedSize, r); if (newLen != UncompressedSize) appError("len mismatch: %d != %d", newLen, UncompressedSize); return newLen; } if (Flags == COMPRESS_ZLIB) { #if 0 appError("appDecompress: Zlib compression is not supported"); #else unsigned long newLen = UncompressedSize; int r = uncompress(UncompressedBuffer, &newLen, CompressedBuffer, CompressedSize); if (r != Z_OK) appError("zlib uncompress(%d,%d) returned %d", CompressedSize, UncompressedSize, r); // if (newLen != UncompressedSize) appError("len mismatch: %d != %d", newLen, UncompressedSize); -- needed by Bioshock return newLen; #endif } if (Flags == COMPRESS_LZX) { #if SUPPORT_XBOX360 # if !USE_XDK appDecompressLZX(CompressedBuffer, CompressedSize, UncompressedBuffer, UncompressedSize); return UncompressedSize; # else void *context; int r; r = XMemCreateDecompressionContext(0, NULL, 0, &context); if (r < 0) appError("XMemCreateDecompressionContext failed"); unsigned int newLen = UncompressedSize; r = XMemDecompress(context, UncompressedBuffer, &newLen, CompressedBuffer, CompressedSize); if (r < 0) appError("XMemDecompress failed"); if (newLen != UncompressedSize) appError("len mismatch: %d != %d", newLen, UncompressedSize); XMemDestroyDecompressionContext(context); return newLen; # endif // USE_XDK #else // SUPPORT_XBOX360 appError("appDecompress: LZX compression is not supported"); #endif // SUPPORT_XBOX360 } appError("appDecompress: unknown compression flags: %d", Flags); return 0; unguardf("CompSize=%d UncompSize=%d Flags=0x%X", CompressedSize, UncompressedSize, Flags); }
void compressor::lzo_read_and_uncompress_to_buffer() { #if LIBLZO2_AVAILABLE lzo_block_header lzo_bh; lzo_uint compr_size; int status; #if LZO1X_MEM_DECOMPRESS > 0 char wrkmem[LZO1X_MEM_DECOMPRESS]; #else char *wrkmem = NULL; #endif if(compressed == NULL) throw SRC_BUG; lzo_bh.set_from(*compressed); if(lzo_bh.type != BLOCK_HEADER_LZO && lzo_bh.type != BLOCK_HEADER_EOF) throw Erange("compressor::lzo_read_and_uncompress_to_buffer", gettext("data corruption detected: Incoherence in LZO compressed data")); if(lzo_bh.type == BLOCK_HEADER_EOF) { if(lzo_bh.size != 0) throw Erange("compressor::lzo_read_and_uncompress_to_buffer", gettext("compressed data corruption detected")); lzo_read_size = 0; lzo_read_start = 0; } else { lzo_uint read; if(lzo_bh.size > LZO_COMPRESSED_BUFFER_SIZE) #if !defined(SSIZE_MAX) || SSIZE_MAX > BUFFER_SIZE throw Erange("compressor::lzo_read_and_uncompress_to_buffer", gettext("data corruption detected: Too large block of compressed data")); #else throw Erange("compressor::lzo_read_and_uncompress_to_buffer", gettext("Too large block of compressed data: Either due to data corruption or current system limitation where SSIZE_MAX value implied smaller buffers than required")); #endif compr_size = 0; lzo_bh.size.unstack(compr_size); if(lzo_bh.size != 0) throw SRC_BUG; read = compressed->read(lzo_compressed, compr_size); if(read != compr_size) Erange("compressor::lzo_read_and_uncompress_to_buffer", gettext("compressed data corruption detected")); read = LZO_CLEAR_BUFFER_SIZE; status = lzo1x_decompress_safe((lzo_bytep)lzo_compressed, compr_size, (lzo_bytep)lzo_read_buffer, &read, wrkmem); lzo_read_size = read; lzo_read_start = 0; switch(status) { case LZO_E_OK: break; // all is fine case LZO_E_INPUT_NOT_CONSUMED: throw SRC_BUG; default: lzo_read_size = 0; throw Erange("compressor::lzo_read_and_uncompress_to_buffer", gettext("compressed data corruption detected")); } } #else throw Efeature(gettext("lzo compression")); #endif }
static int eeprom_config_read_compressed_data(struct msm_eeprom_ctrl_t *e_ctrl, struct msm_eeprom_cfg_data *cdata) { int rc = 0; #if 0 // just once to power up when load lib bool down; #endif uint8_t *buf_comp = NULL; uint8_t *buf_decomp = NULL; uint32_t decomp_size; pr_err("%s: address (0x%x) comp_size (%d) after decomp (%d)", __func__, cdata->cfg.read_data.addr, cdata->cfg.read_data.comp_size, cdata->cfg.read_data.num_bytes); buf_comp = kmalloc(cdata->cfg.read_data.comp_size, GFP_KERNEL); buf_decomp = kmalloc(cdata->cfg.read_data.num_bytes, GFP_KERNEL); if (!buf_decomp || !buf_comp) { pr_err("%s: kmalloc fail", __func__); rc = -ENOMEM; goto FREE; } #if 0 // just once to power up when load lib rc = msm_eeprom_power_up(e_ctrl, &down); if (rc < 0) { pr_err("%s: failed to power on eeprom\n", __func__); goto FREE; } #endif rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_read_seq( &(e_ctrl->i2c_client), cdata->cfg.read_data.addr, buf_comp, cdata->cfg.read_data.comp_size); if (rc < 0) { pr_err("%s: failed to read data, rc %d\n", __func__, rc); goto POWER_DOWN; } pr_err("%s: crc = 0x%08X\n", __func__, *(uint32_t*)&buf_comp[cdata->cfg.read_data.comp_size-4]); // compressed data(buf_comp) contains uncompressed crc32 value. rc = msm_eeprom_verify_sum(buf_comp, cdata->cfg.read_data.comp_size-4, *(uint32_t*)&buf_comp[cdata->cfg.read_data.comp_size-4]); if (rc < 0) { pr_err("%s: crc check error, rc %d\n", __func__, rc); goto POWER_DOWN; } decomp_size = cdata->cfg.read_data.num_bytes; rc = lzo1x_decompress_safe(buf_comp, cdata->cfg.read_data.comp_size-4, buf_decomp, &decomp_size); if (rc != LZO_E_OK) { pr_err("%s: decompression failed %d", __func__, rc); goto POWER_DOWN; } rc = copy_to_user(cdata->cfg.read_data.dbuffer, buf_decomp, decomp_size); if (rc < 0) { pr_err("%s: failed to copy to user\n", __func__); goto POWER_DOWN; } pr_info("%s: done", __func__); POWER_DOWN: #if 0 // just once to power up when load lib msm_eeprom_power_down(e_ctrl, down); #endif FREE: if (buf_comp) kfree(buf_comp); if (buf_decomp) kfree(buf_decomp); return rc; }
STATIC inline int INIT unlzo(u8 *input, int in_len, int (*fill) (void *, unsigned int), int (*flush) (void *, unsigned int), u8 *output, int *posp, void (*error) (char *x)) { u8 r = 0; int skip = 0; u32 src_len, dst_len; size_t tmp; u8 *in_buf, *in_buf_save, *out_buf; int ret = -1; if (output) { out_buf = output; } else if (!flush) { error("NULL output pointer and no flush function provided"); goto exit; } else { out_buf = malloc(LZO_BLOCK_SIZE); if (!out_buf) { error("Could not allocate output buffer"); goto exit; } } if (input && fill) { error("Both input pointer and fill function provided, don't know what to do"); goto exit_1; } else if (input) { in_buf = input; } else if (!fill) { error("NULL input pointer and missing fill function"); goto exit_1; } else { in_buf = malloc(lzo1x_worst_compress(LZO_BLOCK_SIZE)); if (!in_buf) { error("Could not allocate input buffer"); goto exit_1; } } in_buf_save = in_buf; if (posp) *posp = 0; if (fill) { /* */ in_buf += HEADER_SIZE_MAX; in_len = fill(in_buf, HEADER_SIZE_MAX); } if (!parse_header(in_buf, &skip, in_len)) { error("invalid header"); goto exit_2; } in_buf += skip; in_len -= skip; if (fill) { /* */ memcpy(in_buf_save, in_buf, in_len); in_buf = in_buf_save; } if (posp) *posp = skip; for (;;) { /* */ if (fill && in_len < 4) { skip = fill(in_buf + in_len, 4 - in_len); if (skip > 0) in_len += skip; } if (in_len < 4) { error("file corrupted"); goto exit_2; } dst_len = get_unaligned_be32(in_buf); in_buf += 4; in_len -= 4; /* */ if (dst_len == 0) { if (posp) *posp += 4; break; } if (dst_len > LZO_BLOCK_SIZE) { error("dest len longer than block size"); goto exit_2; } /* */ if (fill && in_len < 8) { skip = fill(in_buf + in_len, 8 - in_len); if (skip > 0) in_len += skip; } if (in_len < 8) { error("file corrupted"); goto exit_2; } src_len = get_unaligned_be32(in_buf); in_buf += 8; in_len -= 8; if (src_len <= 0 || src_len > dst_len) { error("file corrupted"); goto exit_2; } /* */ if (fill && in_len < src_len) { skip = fill(in_buf + in_len, src_len - in_len); if (skip > 0) in_len += skip; } if (in_len < src_len) { error("file corrupted"); goto exit_2; } tmp = dst_len; /* */ if (unlikely(dst_len == src_len)) memcpy(out_buf, in_buf, src_len); else { r = lzo1x_decompress_safe((u8 *) in_buf, src_len, out_buf, &tmp); if (r != LZO_E_OK || dst_len != tmp) { error("Compressed data violation"); goto exit_2; } } if (flush && flush(out_buf, dst_len) != dst_len) goto exit_2; if (output) out_buf += dst_len; if (posp) *posp += src_len + 12; in_buf += src_len; in_len -= src_len; if (fill) { /* */ if (in_len > 0) for (skip = 0; skip < in_len; ++skip) in_buf_save[skip] = in_buf[skip]; in_buf = in_buf_save; } } ret = 0; exit_2: if (!input) free(in_buf_save); exit_1: if (!output) free(out_buf); exit: return ret; }
BOOL GetFileUBISOFT_BF(const char * PackName, const char * FileName, const char * PathName, long StartOffset, long FileSize, long UnpSize, struct RIP_SERVICE_FUNC* func, struct RIP_FLAGS *flags){ unsigned char * bufIn; unsigned char * bufOut; char * dstpath; unsigned long rd, FrameUnp, FramePack, FOffset; unsigned int iFrameUnp; BOOL CanUnpacking; FOffset = StartOffset; CanUnpacking = TRUE; if (UnpSize == 0) { dstpath = my_strdup(PathName, strlen(FileName)+2); strcat(dstpath, "\\"); strcat(dstpath, FileName); while (FOffset-StartOffset < FileSize){ rd = func->ReadFromFile(PackName, FOffset, &FrameUnp, sizeof FrameUnp); if (rd < sizeof FrameUnp) {my_free(dstpath); return FALSE;} FOffset += rd; rd = func->ReadFromFile(PackName, FOffset, &FramePack, sizeof FramePack); if (rd < sizeof FramePack) {my_free(dstpath); return FALSE;} FOffset += rd; if ((FramePack == 0)||(FrameUnp == 0)) {my_free(dstpath); return TRUE;} if (FramePack != FrameUnp){ bufIn = (unsigned char *)my_malloc(FramePack); if (!bufIn) {my_free(dstpath); return FALSE;} bufOut = (unsigned char *)my_malloc(FrameUnp); if (!bufOut) {my_free(bufIn);my_free(dstpath); return FALSE;} rd = func->ReadFromFile(PackName, FOffset, bufIn, FramePack); if (rd < FramePack) { my_free(dstpath); my_free(bufIn); my_free(bufOut); return FALSE; } FOffset += rd; iFrameUnp = FrameUnp; int r = lzo1x_decompress_safe(bufIn, FramePack, bufOut, &iFrameUnp, NULL); if(r == LZO_E_OK || r == LZO_E_INPUT_NOT_CONSUMED && iFrameUnp){ } else { my_free(dstpath); my_free(bufIn); my_free(bufOut); return FALSE; } my_free(bufIn); if (func->AppendToFile(dstpath, bufOut, iFrameUnp) != iFrameUnp){ my_free(dstpath); my_free(bufOut); return FALSE; } my_free(bufOut); } else { bufIn = (unsigned char *)my_malloc(FramePack); if (!bufIn) {my_free(dstpath); return FALSE;} rd = func->ReadFromFile(PackName, FOffset, bufIn, FramePack); if (rd < FramePack) { my_free(dstpath); my_free(bufIn); return FALSE; } FOffset += rd; if (func->AppendToFile(dstpath, bufIn, FramePack) != FramePack){ my_free(dstpath); my_free(bufIn); return FALSE; } } } my_free(dstpath); return TRUE; } return FALSE; }