Advertisement
cielavenir

unlz4c

May 3rd, 2014
371
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.05 KB | None | 0 0
  1. /*
  2.   unlz4c - LZ4c decoder without lz4io
  3. */
  4.  
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8.  
  9. #ifdef STANDALONE
  10. #define unlz4c main
  11. unsigned int read32(const void *p){
  12.     const unsigned char *x=(const unsigned char*)p;
  13.     return x[0]|(x[1]<<8)|(x[2]<<16)|(x[3]<<24);
  14. }
  15. #else
  16. #include "../compat.h"
  17. #endif
  18. #include "../lib/lz4/lz4.h"
  19. #include "../lib/lz4/xxhash.h"
  20.  
  21. #define lz4s_magic 0x184D2204
  22. #define lz4s_legacy_magic 0x184C2102
  23. #define lz4s_legacy_blocksize 8*1024*1024
  24.  
  25. //bitfield is LSB, on gcc/clang.
  26. typedef struct{
  27.     //byte 0
  28.     unsigned int dictionary: 1;
  29.     unsigned int reserved1: 1;
  30.     unsigned int stream_checksum: 1;
  31.     unsigned int stream_size: 1;
  32.     unsigned int block_checksum: 1;
  33.     unsigned int block_independence: 1;
  34.     unsigned int version: 2;
  35.  
  36.     //byte 1
  37.     unsigned int reserved3: 4;
  38.     unsigned int blocksize_id: 3;
  39.     unsigned int reserved2: 1;
  40. } lz4s_descriptor;
  41.  
  42. #define lz4s_getblocksize_fromid(n) (1<<(8+(2*(n))))
  43. #define lz4s_skippable_block(n) (((n)&0xfffffff0)==0x184d2a50)
  44.  
  45. static int decode_file(FILE *fin,FILE *fout){
  46.     unsigned char buf[15],hash[4];
  47.     unsigned int ihash;
  48.  
  49.     if(fread(buf,1,4,fin)<4)return 1;
  50.     if(read32(buf)==lz4s_legacy_magic){
  51.         unsigned char *pd=malloc(lz4s_legacy_blocksize);
  52.         for(;fread(buf,1,4,fin)==4;){
  53.             unsigned char *pc=malloc(read32(buf));
  54.             if(fread(pc,1,read32(buf),fin)<read32(buf))return 1;
  55.             int dlen=LZ4_decompress_safe(pc,pd,read32(buf),lz4s_legacy_blocksize);
  56.             if(dlen<0)return 3;
  57.             fwrite(pd,1,dlen,fout);
  58.             free(pc);
  59.         }
  60.         free(pd);
  61.     }else{
  62.         do{
  63.             if(lz4s_skippable_block(read32(buf))){
  64.                 if(fread(buf,1,4,fin)<4)return 1;
  65.                 int i=0;
  66.                 for(;i<read32(buf);i++)fgetc(fin);
  67.             }else if(read32(buf)==lz4s_magic){
  68.                 if(fread(buf,1,2,fin)<2)return 1;
  69.                 int descriptor_size=2;
  70.                 if(
  71.                     ((lz4s_descriptor*)&buf)->version!=1 ||
  72.                     ((lz4s_descriptor*)&buf)->dictionary!=0 ||
  73.                     ((lz4s_descriptor*)&buf)->reserved1!=0 ||
  74.                     ((lz4s_descriptor*)&buf)->reserved2!=0 ||
  75.                     ((lz4s_descriptor*)&buf)->reserved3!=0
  76.                 )return 4;
  77.                 if(((lz4s_descriptor*)&buf)->stream_size){
  78.                     if(fread(buf+descriptor_size,1,8,fin)<8)return 1;
  79.                     descriptor_size+=8;
  80.                 }
  81.                 if(((lz4s_descriptor*)&buf)->dictionary){
  82.                     if(fread(buf+descriptor_size,1,4,fin)<4)return 1;
  83.                     descriptor_size+=4;
  84.                 }
  85.                 if(fread(buf+descriptor_size,1,1,fin)<1)return 1;
  86.                 void *ctx=XXH32_init(0);
  87.                 XXH32_update(ctx,buf,descriptor_size);
  88.                 if(((XXH32_digest(ctx)>>8)&0xff)!=buf[descriptor_size])return 2;
  89.                 unsigned int blocksize=lz4s_getblocksize_fromid(((lz4s_descriptor*)&buf)->blocksize_id);
  90.                 int block_checksum=((lz4s_descriptor*)&buf)->block_checksum;
  91.                 int block_independence=((lz4s_descriptor*)&buf)->block_independence;
  92.                 int stream_checksum=((lz4s_descriptor*)&buf)->stream_checksum;
  93.                 typedef int (*T_decompressor)(const char*,char*,int,int);
  94.                 T_decompressor decompreesor=block_independence?LZ4_decompress_safe:LZ4_decompress_safe_withPrefix64k;
  95.  
  96.                 //parsed header. entering data block.
  97.                 void *ctx_stream=XXH32_init(0);
  98.                 unsigned int size_max=blocksize;
  99.                 unsigned char *pc=malloc(size_max);
  100.                 unsigned char *pd=malloc(blocksize+65536);
  101.                 int bufsiz=0;
  102.                 for(;;){
  103.                     if(fread(buf,1,4,fin)<4)return 1;
  104.                     unsigned int size=read32(buf);
  105.                     int flag=size>>31;
  106.                     size&=0x7fffffff;
  107.                     if(size==0)break;
  108.                     //read data.
  109.                     void *ctx_block=XXH32_init(0);
  110.                     if(size>size_max){
  111.                         size_max=size;
  112.                         free(pc);
  113.                         pc=malloc(size_max);
  114.                     }
  115.                     if(fread(pc,1,size,fin)<size)return 1;
  116.                     XXH32_update(ctx_block,pc,size);
  117.                     ihash=XXH32_digest(ctx_block);
  118.                     if(block_checksum){
  119.                         if(fread(hash,1,4,fin)<4)return 1;
  120.                         if(read32(hash)!=ihash)return 2;
  121.                     }
  122.  
  123.                     int dlen;
  124.                     if(flag==1){
  125.                         dlen=size;
  126.                         memcpy(pd+bufsiz,pc,size);
  127.                     }else{
  128.                         dlen=decompreesor(pc,pd+bufsiz,read32(buf),blocksize);
  129.                         if(dlen<0)return 3;
  130.                     }
  131.                     XXH32_update(ctx_stream,pd+bufsiz,dlen);
  132.                     bufsiz+=dlen;
  133.                     if(bufsiz>65536){
  134.                         fwrite(pd,1,bufsiz-65536,fout);
  135.                         memmove(pd,pd+bufsiz-65536,65536);
  136.                         bufsiz=65536;
  137.                     }
  138.                 }
  139.                 fwrite(pd,1,bufsiz,fout);
  140.                 free(pd);
  141.                 free(pc);
  142.  
  143.                 //processed all data blocks.
  144.                 ihash=XXH32_digest(ctx_stream);
  145.                 if(stream_checksum){
  146.                     if(fread(hash,1,4,fin)<4)return 1;
  147.                     if(read32(hash)!=ihash)return 2;
  148.                 }
  149.             }else return 2;
  150.         }while(fread(buf,1,4,fin)==4);
  151.     }
  152.     return 0;
  153. }
  154.  
  155. int unlz4c(const int argc, const char **argv){
  156.     int i;
  157.     if(isatty(fileno(stdin))||isatty(fileno(stdout))){
  158.         fprintf(stderr,"unlz4c 140423 - LZ4c decoder without lz4io\n");
  159.         fprintf(stderr,"Both stdin and stdout have to be redirected\n");return -2;
  160.     }
  161.     i=decode_file(stdin,stdout);
  162.     switch(i){
  163.         case 0: fprintf(stderr,"Everything is Ok\n");break;
  164.         case 1: fprintf(stderr,"Unexpected EOF\n");break;
  165.         case 2: fprintf(stderr,"File Corrupted\n");break;
  166.         case 3: fprintf(stderr,"Decode Error\n");break;
  167.         case 4: fprintf(stderr,"Format Unsupported\n");break;
  168.         default: fprintf(stderr,"Unknown Error\n");
  169.     }
  170.     return i;
  171. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement