Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- unlz4c - LZ4c decoder without lz4io
- */
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #ifdef STANDALONE
- #define unlz4c main
- unsigned int read32(const void *p){
- const unsigned char *x=(const unsigned char*)p;
- return x[0]|(x[1]<<8)|(x[2]<<16)|(x[3]<<24);
- }
- #else
- #include "../compat.h"
- #endif
- #include "../lib/lz4/lz4.h"
- #include "../lib/lz4/xxhash.h"
- #define lz4s_magic 0x184D2204
- #define lz4s_legacy_magic 0x184C2102
- #define lz4s_legacy_blocksize 8*1024*1024
- //bitfield is LSB, on gcc/clang.
- typedef struct{
- //byte 0
- unsigned int dictionary: 1;
- unsigned int reserved1: 1;
- unsigned int stream_checksum: 1;
- unsigned int stream_size: 1;
- unsigned int block_checksum: 1;
- unsigned int block_independence: 1;
- unsigned int version: 2;
- //byte 1
- unsigned int reserved3: 4;
- unsigned int blocksize_id: 3;
- unsigned int reserved2: 1;
- } lz4s_descriptor;
- #define lz4s_getblocksize_fromid(n) (1<<(8+(2*(n))))
- #define lz4s_skippable_block(n) (((n)&0xfffffff0)==0x184d2a50)
- static int decode_file(FILE *fin,FILE *fout){
- unsigned char buf[15],hash[4];
- unsigned int ihash;
- if(fread(buf,1,4,fin)<4)return 1;
- if(read32(buf)==lz4s_legacy_magic){
- unsigned char *pd=malloc(lz4s_legacy_blocksize);
- for(;fread(buf,1,4,fin)==4;){
- unsigned char *pc=malloc(read32(buf));
- if(fread(pc,1,read32(buf),fin)<read32(buf))return 1;
- int dlen=LZ4_decompress_safe(pc,pd,read32(buf),lz4s_legacy_blocksize);
- if(dlen<0)return 3;
- fwrite(pd,1,dlen,fout);
- free(pc);
- }
- free(pd);
- }else{
- do{
- if(lz4s_skippable_block(read32(buf))){
- if(fread(buf,1,4,fin)<4)return 1;
- int i=0;
- for(;i<read32(buf);i++)fgetc(fin);
- }else if(read32(buf)==lz4s_magic){
- if(fread(buf,1,2,fin)<2)return 1;
- int descriptor_size=2;
- if(
- ((lz4s_descriptor*)&buf)->version!=1 ||
- ((lz4s_descriptor*)&buf)->dictionary!=0 ||
- ((lz4s_descriptor*)&buf)->reserved1!=0 ||
- ((lz4s_descriptor*)&buf)->reserved2!=0 ||
- ((lz4s_descriptor*)&buf)->reserved3!=0
- )return 4;
- if(((lz4s_descriptor*)&buf)->stream_size){
- if(fread(buf+descriptor_size,1,8,fin)<8)return 1;
- descriptor_size+=8;
- }
- if(((lz4s_descriptor*)&buf)->dictionary){
- if(fread(buf+descriptor_size,1,4,fin)<4)return 1;
- descriptor_size+=4;
- }
- if(fread(buf+descriptor_size,1,1,fin)<1)return 1;
- void *ctx=XXH32_init(0);
- XXH32_update(ctx,buf,descriptor_size);
- if(((XXH32_digest(ctx)>>8)&0xff)!=buf[descriptor_size])return 2;
- unsigned int blocksize=lz4s_getblocksize_fromid(((lz4s_descriptor*)&buf)->blocksize_id);
- int block_checksum=((lz4s_descriptor*)&buf)->block_checksum;
- int block_independence=((lz4s_descriptor*)&buf)->block_independence;
- int stream_checksum=((lz4s_descriptor*)&buf)->stream_checksum;
- typedef int (*T_decompressor)(const char*,char*,int,int);
- T_decompressor decompreesor=block_independence?LZ4_decompress_safe:LZ4_decompress_safe_withPrefix64k;
- //parsed header. entering data block.
- void *ctx_stream=XXH32_init(0);
- unsigned int size_max=blocksize;
- unsigned char *pc=malloc(size_max);
- unsigned char *pd=malloc(blocksize+65536);
- int bufsiz=0;
- for(;;){
- if(fread(buf,1,4,fin)<4)return 1;
- unsigned int size=read32(buf);
- int flag=size>>31;
- size&=0x7fffffff;
- if(size==0)break;
- //read data.
- void *ctx_block=XXH32_init(0);
- if(size>size_max){
- size_max=size;
- free(pc);
- pc=malloc(size_max);
- }
- if(fread(pc,1,size,fin)<size)return 1;
- XXH32_update(ctx_block,pc,size);
- ihash=XXH32_digest(ctx_block);
- if(block_checksum){
- if(fread(hash,1,4,fin)<4)return 1;
- if(read32(hash)!=ihash)return 2;
- }
- int dlen;
- if(flag==1){
- dlen=size;
- memcpy(pd+bufsiz,pc,size);
- }else{
- dlen=decompreesor(pc,pd+bufsiz,read32(buf),blocksize);
- if(dlen<0)return 3;
- }
- XXH32_update(ctx_stream,pd+bufsiz,dlen);
- bufsiz+=dlen;
- if(bufsiz>65536){
- fwrite(pd,1,bufsiz-65536,fout);
- memmove(pd,pd+bufsiz-65536,65536);
- bufsiz=65536;
- }
- }
- fwrite(pd,1,bufsiz,fout);
- free(pd);
- free(pc);
- //processed all data blocks.
- ihash=XXH32_digest(ctx_stream);
- if(stream_checksum){
- if(fread(hash,1,4,fin)<4)return 1;
- if(read32(hash)!=ihash)return 2;
- }
- }else return 2;
- }while(fread(buf,1,4,fin)==4);
- }
- return 0;
- }
- int unlz4c(const int argc, const char **argv){
- int i;
- if(isatty(fileno(stdin))||isatty(fileno(stdout))){
- fprintf(stderr,"unlz4c 140423 - LZ4c decoder without lz4io\n");
- fprintf(stderr,"Both stdin and stdout have to be redirected\n");return -2;
- }
- i=decode_file(stdin,stdout);
- switch(i){
- case 0: fprintf(stderr,"Everything is Ok\n");break;
- case 1: fprintf(stderr,"Unexpected EOF\n");break;
- case 2: fprintf(stderr,"File Corrupted\n");break;
- case 3: fprintf(stderr,"Decode Error\n");break;
- case 4: fprintf(stderr,"Format Unsupported\n");break;
- default: fprintf(stderr,"Unknown Error\n");
- }
- return i;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement