cielavenir

zlz4c - permissive LZ4c handler

Jun 28th, 2014
350
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.51 KB | None | 0 0
  1. /*
  2. zlz4c - permissive LZ4c handler
  3. */
  4.  
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8.  
  9. #ifdef STANDALONE
  10. #define zlz4c main
  11. void write32(void *p, const unsigned int n){
  12. unsigned char *x=(unsigned char*)p;
  13. x[0]=n&0xff,x[1]=(n>>8)&0xff,x[2]=(n>>16)&0xff,x[3]=(n>>24)&0xff;
  14. }
  15. unsigned int read32(const void *p){
  16. const unsigned char *x=(const unsigned char*)p;
  17. return x[0]|(x[1]<<8)|(x[2]<<16)|(x[3]<<24);
  18. }
  19. #else
  20. #include "../compat.h"
  21. #endif
  22. #include "../lib/lz4/lz4.h"
  23. #include "../lib/lz4/xxhash.h"
  24.  
  25. #define lz4s_magic 0x184D2204
  26. #define lz4s_legacy_magic 0x184C2102
  27. #define lz4s_legacy_blocksize 8*1024*1024
  28.  
  29. //bitfield is LSB, on gcc/clang.
  30. typedef struct{
  31. //byte 0
  32. unsigned int dictionary: 1;
  33. unsigned int reserved1: 1;
  34. unsigned int stream_checksum: 1;
  35. unsigned int stream_size: 1;
  36. unsigned int block_checksum: 1;
  37. unsigned int block_independence: 1;
  38. unsigned int version: 2;
  39.  
  40. //byte 1
  41. unsigned int reserved3: 4;
  42. unsigned int blocksize_id: 3;
  43. unsigned int reserved2: 1;
  44. } lz4s_descriptor;
  45.  
  46. #define lz4s_getblocksize_fromid(n) (1<<(8+(2*(n))))
  47. #define lz4s_skippable_block(n) (((n)&0xfffffff0)==0x184d2a50)
  48.  
  49. static int encode_file(FILE *fin,FILE *fout){
  50. unsigned char buf[4];
  51. write32(buf,lz4s_magic);
  52. fwrite(buf,1,4,fout);
  53. lz4s_descriptor *desc=buf;
  54. desc->version=1;
  55. desc->dictionary=0;
  56. desc->reserved1=0;
  57. desc->reserved2=0;
  58. desc->reserved3=0;
  59. desc->stream_size=0;
  60. desc->block_checksum=1;
  61. desc->stream_checksum=1;
  62. desc->block_independence=1; //gee
  63. desc->blocksize_id=7; ///
  64. fwrite(buf,1,2,fout);
  65. void *ctx=XXH32_init(0);
  66. XXH32_update(ctx,buf,2);
  67. fputc((XXH32_digest(ctx)>>8)&0xff,fout);
  68.  
  69. //parsed header. entering data block.
  70. void *ctx_stream=XXH32_init(0);
  71. unsigned int blocksize=lz4s_getblocksize_fromid(desc->blocksize_id);
  72. unsigned int size_max=blocksize+(blocksize>>1);
  73. unsigned char *pc=malloc(size_max);
  74. unsigned char *pd=malloc(blocksize/*+65536*/);
  75.  
  76. int readlen;
  77. for(;readlen=fread(pd,1,blocksize,fin);){
  78. XXH32_update(ctx_stream,pd,readlen);
  79. int clen=LZ4_compress(pd,pc,readlen);
  80. void *ctx_block=XXH32_init(0);
  81. if(clen>=blocksize){
  82. unsigned int size=readlen;
  83. write32(buf,size|0x80000000);
  84. fwrite(buf,1,4,fout);
  85. fwrite(pd,1,readlen,fout);
  86. XXH32_update(ctx_block,pd,readlen);
  87. }else{
  88. write32(buf,clen);
  89. fwrite(buf,1,4,fout);
  90. fwrite(pc,1,clen,fout);
  91. XXH32_update(ctx_block,pc,clen);
  92. }
  93. write32(buf,XXH32_digest(ctx_block));
  94. fwrite(buf,1,4,fout);
  95. }
  96. write32(buf,0);
  97. fwrite(buf,1,4,fout);
  98. write32(buf,XXH32_digest(ctx_stream));
  99. fwrite(buf,1,4,fout);
  100. return 0;
  101. }
  102.  
  103. static int decode_file(FILE *fin,FILE *fout){
  104. unsigned char buf[15],hash[4];
  105. unsigned int ihash;
  106.  
  107. if(fread(buf,1,4,fin)<4)return 1;
  108. if(read32(buf)==lz4s_legacy_magic){
  109. unsigned char *pd=malloc(lz4s_legacy_blocksize);
  110. for(;fread(buf,1,4,fin)==4;){
  111. unsigned char *pc=malloc(read32(buf));
  112. if(fread(pc,1,read32(buf),fin)<read32(buf))return 1;
  113. int dlen=LZ4_decompress_safe(pc,pd,read32(buf),lz4s_legacy_blocksize);
  114. if(dlen<0)return 3;
  115. fwrite(pd,1,dlen,fout);
  116. free(pc);
  117. }
  118. free(pd);
  119. }else{
  120. do{
  121. if(lz4s_skippable_block(read32(buf))){
  122. if(fread(buf,1,4,fin)<4)return 1;
  123. int i=0;
  124. for(;i<read32(buf);i++)fgetc(fin);
  125. }else if(read32(buf)==lz4s_magic){
  126. if(fread(buf,1,2,fin)<2)return 1;
  127. int descriptor_size=2;
  128. lz4s_descriptor *desc=buf;
  129. if(
  130. desc->version!=1 ||
  131. desc->dictionary!=0 ||
  132. desc->reserved1!=0 ||
  133. desc->reserved2!=0 ||
  134. desc->reserved3!=0
  135. )return 4;
  136. if(desc->stream_size){
  137. if(fread(buf+descriptor_size,1,8,fin)<8)return 1;
  138. descriptor_size+=8;
  139. }
  140. if(desc->dictionary){
  141. if(fread(buf+descriptor_size,1,4,fin)<4)return 1;
  142. descriptor_size+=4;
  143. }
  144. if(fread(buf+descriptor_size,1,1,fin)<1)return 1;
  145. void *ctx=XXH32_init(0);
  146. XXH32_update(ctx,buf,descriptor_size);
  147. if(((XXH32_digest(ctx)>>8)&0xff)!=buf[descriptor_size])return 2;
  148. unsigned int blocksize=lz4s_getblocksize_fromid(desc->blocksize_id);
  149. int block_checksum=desc->block_checksum;
  150. int block_independence=desc->block_independence;
  151. int stream_checksum=desc->stream_checksum;
  152. typedef int (*T_decompressor)(const char*,char*,int,int);
  153. T_decompressor decompressor=block_independence?LZ4_decompress_safe:LZ4_decompress_safe_withPrefix64k;
  154.  
  155. //parsed header. entering data block.
  156. void *ctx_stream=XXH32_init(0);
  157. unsigned int size_max=blocksize;
  158. unsigned char *pc=malloc(size_max);
  159. unsigned char *pd=malloc(blocksize+65536);
  160. int bufsiz=0;
  161. for(;;){
  162. if(fread(buf,1,4,fin)<4)return 1;
  163. unsigned int size=read32(buf);
  164. int flag=size>>31;
  165. size&=0x7fffffff;
  166. if(size==0)break;
  167. //read data.
  168. void *ctx_block=XXH32_init(0);
  169. if(size>size_max){
  170. size_max=size;
  171. free(pc);
  172. pc=malloc(size_max);
  173. }
  174. if(fread(pc,1,size,fin)<size)return 1;
  175. XXH32_update(ctx_block,pc,size);
  176. ihash=XXH32_digest(ctx_block);
  177. if(block_checksum){
  178. if(fread(hash,1,4,fin)<4)return 1;
  179. if(read32(hash)!=ihash)return 2;
  180. }
  181.  
  182. int dlen;
  183. if(flag==1){
  184. dlen=size;
  185. memcpy(pd+bufsiz,pc,size);
  186. }else{
  187. dlen=decompressor(pc,pd+bufsiz,read32(buf),blocksize);
  188. if(dlen<0)return 3;
  189. }
  190. XXH32_update(ctx_stream,pd+bufsiz,dlen);
  191. bufsiz+=dlen;
  192. if(bufsiz>65536){
  193. fwrite(pd,1,bufsiz-65536,fout);
  194. memmove(pd,pd+bufsiz-65536,65536);
  195. bufsiz=65536;
  196. }
  197. }
  198. fwrite(pd,1,bufsiz,fout);
  199. free(pd);
  200. free(pc);
  201.  
  202. //processed all data blocks.
  203. ihash=XXH32_digest(ctx_stream);
  204. if(stream_checksum){
  205. if(fread(hash,1,4,fin)<4)return 1;
  206. if(read32(hash)!=ihash)return 2;
  207. }
  208. }else return 2;
  209. }while(fread(buf,1,4,fin)==4);
  210. }
  211. return 0;
  212. }
  213.  
  214. int zlz4c(const int argc, const char **argv){
  215. int i;
  216. if(isatty(fileno(stdin))&&isatty(fileno(stdout))){
  217. fprintf(stderr,"zlz4c 140629 - permissive LZ4c handler\n");
  218. fprintf(stderr,"zlz4c [d] < in > out\n");
  219. return -1;
  220. }
  221. if(argc>1){
  222. i=decode_file(stdin,stdout);
  223. switch(i){
  224. case 0: fprintf(stderr,"Everything is Ok\n");break;
  225. case 1: fprintf(stderr,"Unexpected EOF\n");break;
  226. case 2: fprintf(stderr,"File Corrupted\n");break;
  227. case 3: fprintf(stderr,"Decode Error\n");break;
  228. case 4: fprintf(stderr,"Format Unsupported\n");break;
  229. default: fprintf(stderr,"Unknown Error\n");
  230. }
  231. return i;
  232. }else{
  233. return encode_file(stdin,stdout);
  234. }
  235. }
Advertisement
Add Comment
Please, Sign In to add comment