zpipe.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. /* zpipe.c: example of proper use of zlib's inflate() and deflate()
  2. Not copyrighted -- provided to the public domain
  3. Version 1.4 11 December 2005 Mark Adler */
  4. /* Version history:
  5. 1.0 30 Oct 2004 First version
  6. 1.1 8 Nov 2004 Add void casting for unused return values
  7. Use switch statement for inflate() return values
  8. 1.2 9 Nov 2004 Add assertions to document zlib guarantees
  9. 1.3 6 Apr 2005 Remove incorrect assertion in inf()
  10. 1.4 11 Dec 2005 Add hack to avoid MSDOS end-of-line conversions
  11. Avoid some compiler warnings for input and output buffers
  12. */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <assert.h>
  17. #include "zlib.h"
  18. #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
  19. # include <fcntl.h>
  20. # include <io.h>
  21. # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
  22. #else
  23. # define SET_BINARY_MODE(file)
  24. #endif
  25. #define CHUNK 16384
  26. /* Compress from file source to file dest until EOF on source.
  27. def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
  28. allocated for processing, Z_STREAM_ERROR if an invalid compression
  29. level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
  30. version of the library linked do not match, or Z_ERRNO if there is
  31. an error reading or writing the files. */
  32. int def(FILE *source, FILE *dest, int level)
  33. {
  34. int ret, flush;
  35. unsigned have;
  36. z_stream strm;
  37. unsigned char in[CHUNK];
  38. unsigned char out[CHUNK];
  39. /* allocate deflate state */
  40. strm.zalloc = Z_NULL;
  41. strm.zfree = Z_NULL;
  42. strm.opaque = Z_NULL;
  43. ret = deflateInit(&strm, level);
  44. if (ret != Z_OK)
  45. return ret;
  46. /* compress until end of file */
  47. do
  48. {
  49. strm.avail_in = fread(in, 1, CHUNK, source);
  50. if (ferror(source))
  51. {
  52. (void)deflateEnd(&strm);
  53. return Z_ERRNO;
  54. }
  55. flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
  56. strm.next_in = in;
  57. /* run deflate() on input until output buffer not full, finish
  58. compression if all of source has been read in */
  59. do
  60. {
  61. strm.avail_out = CHUNK;
  62. strm.next_out = out;
  63. ret = deflate(&strm, flush); /* no bad return value */
  64. assert(ret != Z_STREAM_ERROR); /* state not clobbered */
  65. have = CHUNK - strm.avail_out;
  66. if (fwrite(out, 1, have, dest) != have || ferror(dest))
  67. {
  68. (void)inflateEnd(&strm);
  69. return Z_ERRNO;
  70. }
  71. } while (strm.avail_out == 0);
  72. assert(strm.avail_in == 0); /* all input will be used */
  73. /* done when last data in file processed */
  74. } while (flush != Z_FINISH);
  75. assert(ret == Z_STREAM_END); /* stream will be complete */
  76. /* clean up and return */
  77. (void)deflateEnd(&strm);
  78. return Z_OK;
  79. }
  80. /* Decompress from file source to file dest until stream ends or EOF.
  81. inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
  82. allocated for processing, Z_DATA_ERROR if the deflate data is
  83. invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
  84. the version of the library linked do not match, or Z_ERRNO if there
  85. is an error reading or writing the files. */
  86. int inf(FILE *source, FILE *dest)
  87. {
  88. int ret;
  89. unsigned int have;
  90. z_stream strm;
  91. unsigned char in[CHUNK];
  92. unsigned char out[CHUNK];
  93. /* allocate inflate state */
  94. strm.zalloc = Z_NULL;
  95. strm.zfree = Z_NULL;
  96. strm.opaque = Z_NULL;
  97. strm.avail_in = 0;
  98. strm.next_in = Z_NULL;
  99. ret = inflateInit(&strm);
  100. if (ret != Z_OK)
  101. return ret;
  102. /* decompress until deflate stream ends or end of file */
  103. do
  104. {
  105. strm.avail_in = fread(in, 1, CHUNK, source);
  106. if (ferror(source)) {
  107. (void)inflateEnd(&strm);
  108. return Z_ERRNO;
  109. }
  110. if (strm.avail_in == 0)
  111. break;
  112. strm.next_in = in;
  113. /* run inflate() on input until output buffer not full */
  114. do
  115. {
  116. strm.avail_out = CHUNK;
  117. strm.next_out = out;
  118. ret = inflate(&strm, Z_NO_FLUSH);
  119. assert(ret != Z_STREAM_ERROR); /* state not clobbered */
  120. switch (ret)
  121. {
  122. case Z_NEED_DICT:
  123. ret = Z_DATA_ERROR; /* and fall through */
  124. case Z_DATA_ERROR:
  125. case Z_MEM_ERROR:
  126. (void)inflateEnd(&strm);
  127. return ret;
  128. }
  129. have = CHUNK - strm.avail_out;
  130. if (fwrite(out, 1, have, dest) != have || ferror(dest))
  131. {
  132. (void)inflateEnd(&strm);
  133. return Z_ERRNO;
  134. }
  135. } while (strm.avail_out == 0);
  136. /* done when inflate() says it's done */
  137. } while (ret != Z_STREAM_END);
  138. /* clean up and return */
  139. (void)inflateEnd(&strm);
  140. return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
  141. }
  142. /* report a zlib or i/o error */
  143. void zerr(int ret)
  144. {
  145. fputs("zpipe: ", stderr);
  146. switch (ret)
  147. {
  148. case Z_ERRNO:
  149. if (ferror(stdin))
  150. fputs("error reading stdin\n", stderr);
  151. if (ferror(stdout))
  152. fputs("error writing stdout\n", stderr);
  153. break;
  154. case Z_STREAM_ERROR:
  155. fputs("invalid compression level\n", stderr);
  156. break;
  157. case Z_DATA_ERROR:
  158. fputs("invalid or incomplete deflate data\n", stderr);
  159. break;
  160. case Z_MEM_ERROR:
  161. fputs("out of memory\n", stderr);
  162. break;
  163. case Z_VERSION_ERROR:
  164. fputs("zlib version mismatch!\n", stderr);
  165. }
  166. }
  167. /* compress or decompress from stdin to stdout */
  168. int process(int argc, char **argv)
  169. {
  170. int ret;
  171. /* avoid end-of-line conversions */
  172. SET_BINARY_MODE(stdin);
  173. SET_BINARY_MODE(stdout);
  174. /* do compression if no arguments */
  175. if (argc == 1)
  176. {
  177. ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
  178. if (ret != Z_OK)
  179. zerr(ret);
  180. return ret;
  181. }
  182. /* do decompression if -d specified */
  183. else if (argc == 2 && strcmp(argv[1], "-d") == 0)
  184. {
  185. ret = inf(stdin, stdout);
  186. if (ret != Z_OK)
  187. zerr(ret);
  188. return ret;
  189. }
  190. /* otherwise, report usage */
  191. else
  192. {
  193. fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr);
  194. return 1;
  195. }
  196. }
  197. int main(int argc, char **argv)
  198. {
  199. int ret = 0;
  200. int i;
  201. FILE *input, *output;
  202. if (argc < 4 || (strcmp(argv[1], "-l") && strcmp(argv[1], "-d")))
  203. {
  204. printf("[Usage] compress -l n output input1 [input2]\n");
  205. printf("Example: compress -l 9 logo.raw battery.raw\n");
  206. return -1;
  207. }
  208. // compress
  209. if(!strcmp(argv[1], "-l"))
  210. {
  211. char *ptemp;
  212. unsigned int *pinfo;
  213. int level = -1;
  214. int filenum = argc - 2;
  215. level = atoi(argv[2]);
  216. input = fopen(argv[4], "rb");
  217. output = fopen(argv[3], "wb");
  218. ptemp = (char*)malloc(1024*1024);
  219. pinfo = (unsigned int*)malloc(filenum*sizeof(int));
  220. if(input < 0 || output < 0 || ptemp == NULL || pinfo == NULL)
  221. {
  222. fprintf(stderr, "open file and allocate temp buffer fail\n");
  223. fprintf(stderr, "input = %d, output = %d, ptemp = 0x%08x, pinfo = 0x%08x\n", input, output, ptemp, pinfo);
  224. ret = -1;
  225. goto done;
  226. }
  227. // structre of pinfo:
  228. // pinfo[0] ==> size of pinfo
  229. // pinfo[1] ==> offset of zip chunk[1]
  230. // pinfo[2] ==> offset of zip chunk[2]
  231. // ...
  232. // pinfo[n] ==> offset of zip chunk[n]
  233. // "offset" is the distance from the begining of the file, not the zip chunk
  234. memset((void*)pinfo, 0, sizeof(int)*filenum);
  235. // write information header to output first
  236. if(sizeof(int)*filenum != fwrite(pinfo, 1, filenum*sizeof(int), output))
  237. {
  238. ret = -2;
  239. goto done;
  240. }
  241. pinfo[pinfo[0]+2]=ftell(output);
  242. if (Z_OK != def(input, output, level))
  243. {
  244. ret = -2;
  245. goto done;
  246. }
  247. pinfo[0] = pinfo[0]+1;
  248. for (i = 5; i < argc; i++)
  249. {
  250. fclose(input);
  251. input = fopen(argv[i], "rb");
  252. pinfo[pinfo[0]+2]=ftell(output);
  253. if (Z_OK != def(input, output, level))
  254. {
  255. fprintf(stderr, "compress error\n");
  256. ret = -2;
  257. goto done;
  258. }
  259. pinfo[0] = pinfo[0]+1;
  260. }
  261. done:
  262. fseek(output, 0L, SEEK_END);
  263. pinfo[1] = ftell(output);
  264. fseek(output, 0L, SEEK_SET);
  265. fwrite(pinfo, 1, filenum*sizeof(int), output);
  266. fclose(input);
  267. fclose(output);
  268. free(ptemp);
  269. free(pinfo);
  270. return ret;
  271. }
  272. // decompress
  273. else
  274. {
  275. unsigned int temp;
  276. unsigned int *pinfo;
  277. char outputfilename[256];
  278. input = fopen(argv[3], "rb");
  279. if(input < 0)
  280. {
  281. printf("open file fail\n");
  282. printf("input = %d\n", input);
  283. ret = -1;
  284. goto done2;
  285. }
  286. fread(&temp, 1, sizeof(int), input);
  287. printf("temp=%d\n", temp);
  288. pinfo = malloc(temp*sizeof(int));
  289. if(pinfo == NULL)
  290. {
  291. printf("allocate pinfo failed\n");
  292. ret = -1;
  293. goto done2;
  294. }
  295. fread(pinfo, 1, temp*sizeof(int), input);
  296. for(i=0;i<temp;i++)
  297. printf("pinfo[%d]=%d\n", i, pinfo[i]);
  298. for(i = 0;i < temp;i++)
  299. {
  300. sprintf(outputfilename, "%d_%s", i, argv[2]);
  301. output = fopen(outputfilename, "wb");
  302. if(output < 0)
  303. {
  304. printf("create output file %s fail\n", outputfilename);
  305. goto done2;
  306. }
  307. fseek(input, pinfo[i], SEEK_SET);
  308. if(Z_OK != inf(input, output))
  309. {
  310. printf("decompress error\n");
  311. ret = -2;
  312. goto done2;
  313. }
  314. fclose(output);
  315. output = 0;
  316. }
  317. done2:
  318. fclose(input);
  319. if(output) fclose(output);
  320. return ret;
  321. }
  322. }