gzwrite.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. /* gzwrite.c -- zlib functions for writing gzip files
  2. * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
  3. * For conditions of distribution and use, see copyright notice in zlib.h
  4. */
  5. #include "gzguts.h"
  6. /* Local functions */
  7. local int gz_init OF((gz_statep));
  8. local int gz_comp OF((gz_statep, int));
  9. local int gz_zero OF((gz_statep, z_off64_t));
  10. /* Initialize state for writing a gzip file. Mark initialization by setting
  11. state->size to non-zero. Return -1 on failure or 0 on success. */
  12. local int gz_init(state)
  13. gz_statep state;
  14. {
  15. int ret;
  16. z_streamp strm = &(state->strm);
  17. /* allocate input buffer */
  18. state->in = (unsigned char *)malloc(state->want);
  19. if (state->in == NULL)
  20. {
  21. gz_error(state, Z_MEM_ERROR, "out of memory");
  22. return -1;
  23. }
  24. /* only need output buffer and deflate state if compressing */
  25. if (!state->direct)
  26. {
  27. /* allocate output buffer */
  28. state->out = (unsigned char *)malloc(state->want);
  29. if (state->out == NULL)
  30. {
  31. free(state->in);
  32. gz_error(state, Z_MEM_ERROR, "out of memory");
  33. return -1;
  34. }
  35. /* allocate deflate memory, set up for gzip compression */
  36. strm->zalloc = Z_NULL;
  37. strm->zfree = Z_NULL;
  38. strm->opaque = Z_NULL;
  39. ret = deflateInit2(strm, state->level, Z_DEFLATED,
  40. MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
  41. if (ret != Z_OK)
  42. {
  43. free(state->out);
  44. free(state->in);
  45. gz_error(state, Z_MEM_ERROR, "out of memory");
  46. return -1;
  47. }
  48. }
  49. /* mark state as initialized */
  50. state->size = state->want;
  51. /* initialize write buffer if compressing */
  52. if (!state->direct)
  53. {
  54. strm->avail_out = state->size;
  55. strm->next_out = state->out;
  56. state->x.next = strm->next_out;
  57. }
  58. return 0;
  59. }
  60. /* Compress whatever is at avail_in and next_in and write to the output file.
  61. Return -1 if there is an error writing to the output file, otherwise 0.
  62. flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
  63. then the deflate() state is reset to start a new gzip stream. If gz->direct
  64. is true, then simply write to the output file without compressing, and
  65. ignore flush. */
  66. local int gz_comp(state, flush)
  67. gz_statep state;
  68. int flush;
  69. {
  70. int ret, got;
  71. unsigned have;
  72. z_streamp strm = &(state->strm);
  73. /* allocate memory if this is the first time through */
  74. if (state->size == 0 && gz_init(state) == -1)
  75. return -1;
  76. /* write directly if requested */
  77. if (state->direct)
  78. {
  79. got = write(state->fd, strm->next_in, strm->avail_in);
  80. if (got < 0 || (unsigned)got != strm->avail_in)
  81. {
  82. gz_error(state, Z_ERRNO, zstrerror());
  83. return -1;
  84. }
  85. strm->avail_in = 0;
  86. return 0;
  87. }
  88. /* run deflate() on provided input until it produces no more output */
  89. ret = Z_OK;
  90. do
  91. {
  92. /* write out current buffer contents if full, or if flushing, but if
  93. doing Z_FINISH then don't write until we get to Z_STREAM_END */
  94. if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
  95. (flush != Z_FINISH || ret == Z_STREAM_END)))
  96. {
  97. have = (unsigned)(strm->next_out - state->x.next);
  98. if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
  99. (unsigned)got != have))
  100. {
  101. gz_error(state, Z_ERRNO, zstrerror());
  102. return -1;
  103. }
  104. if (strm->avail_out == 0)
  105. {
  106. strm->avail_out = state->size;
  107. strm->next_out = state->out;
  108. }
  109. state->x.next = strm->next_out;
  110. }
  111. /* compress */
  112. have = strm->avail_out;
  113. ret = deflate(strm, flush);
  114. if (ret == Z_STREAM_ERROR)
  115. {
  116. gz_error(state, Z_STREAM_ERROR,
  117. "internal error: deflate stream corrupt");
  118. return -1;
  119. }
  120. have -= strm->avail_out;
  121. } while (have);
  122. /* if that completed a deflate stream, allow another to start */
  123. if (flush == Z_FINISH)
  124. deflateReset(strm);
  125. /* all done, no errors */
  126. return 0;
  127. }
  128. /* Compress len zeros to output. Return -1 on error, 0 on success. */
  129. local int gz_zero(state, len)
  130. gz_statep state;
  131. z_off64_t len;
  132. {
  133. int first;
  134. unsigned n;
  135. z_streamp strm = &(state->strm);
  136. /* consume whatever's left in the input buffer */
  137. if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
  138. return -1;
  139. /* compress len zeros (len guaranteed > 0) */
  140. first = 1;
  141. while (len)
  142. {
  143. n = GT_OFF(state->size) || (z_off64_t)state->size > len ? (unsigned)len : state->size;
  144. if (first)
  145. {
  146. memset(state->in, 0, n);
  147. first = 0;
  148. }
  149. strm->avail_in = n;
  150. strm->next_in = state->in;
  151. state->x.pos += n;
  152. if (gz_comp(state, Z_NO_FLUSH) == -1)
  153. return -1;
  154. len -= n;
  155. }
  156. return 0;
  157. }
  158. /* -- see zlib.h -- */
  159. int ZEXPORT gzwrite(file, buf, len)
  160. gzFile file;
  161. voidpc buf;
  162. unsigned len;
  163. {
  164. unsigned put = len;
  165. gz_statep state;
  166. z_streamp strm;
  167. /* get internal structure */
  168. if (file == NULL)
  169. return 0;
  170. state = (gz_statep)file;
  171. strm = &(state->strm);
  172. /* check that we're writing and that there's no error */
  173. if (state->mode != GZ_WRITE || state->err != Z_OK)
  174. return 0;
  175. /* since an int is returned, make sure len fits in one, otherwise return
  176. with an error (this avoids the flaw in the interface) */
  177. if ((int)len < 0)
  178. {
  179. gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
  180. return 0;
  181. }
  182. /* if len is zero, avoid unnecessary operations */
  183. if (len == 0)
  184. return 0;
  185. /* allocate memory if this is the first time through */
  186. if (state->size == 0 && gz_init(state) == -1)
  187. return 0;
  188. /* check for seek request */
  189. if (state->seek)
  190. {
  191. state->seek = 0;
  192. if (gz_zero(state, state->skip) == -1)
  193. return 0;
  194. }
  195. /* for small len, copy to input buffer, otherwise compress directly */
  196. if (len < state->size)
  197. {
  198. /* copy to input buffer, compress when full */
  199. do
  200. {
  201. unsigned have, copy;
  202. if (strm->avail_in == 0)
  203. strm->next_in = state->in;
  204. have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
  205. copy = state->size - have;
  206. if (copy > len)
  207. copy = len;
  208. memcpy(state->in + have, buf, copy);
  209. strm->avail_in += copy;
  210. state->x.pos += copy;
  211. buf = (const char *)buf + copy;
  212. len -= copy;
  213. if (len && gz_comp(state, Z_NO_FLUSH) == -1)
  214. return 0;
  215. } while (len);
  216. }
  217. else
  218. {
  219. /* consume whatever's left in the input buffer */
  220. if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
  221. return 0;
  222. /* directly compress user buffer to file */
  223. strm->avail_in = len;
  224. strm->next_in = (z_const Bytef *)buf;
  225. state->x.pos += len;
  226. if (gz_comp(state, Z_NO_FLUSH) == -1)
  227. return 0;
  228. }
  229. /* input was all buffered or compressed (put will fit in int) */
  230. return (int)put;
  231. }
  232. /* -- see zlib.h -- */
  233. int ZEXPORT gzputc(file, c)
  234. gzFile file;
  235. int c;
  236. {
  237. unsigned have;
  238. unsigned char buf[1];
  239. gz_statep state;
  240. z_streamp strm;
  241. /* get internal structure */
  242. if (file == NULL)
  243. return -1;
  244. state = (gz_statep)file;
  245. strm = &(state->strm);
  246. /* check that we're writing and that there's no error */
  247. if (state->mode != GZ_WRITE || state->err != Z_OK)
  248. return -1;
  249. /* check for seek request */
  250. if (state->seek)
  251. {
  252. state->seek = 0;
  253. if (gz_zero(state, state->skip) == -1)
  254. return -1;
  255. }
  256. /* try writing to input buffer for speed (state->size == 0 if buffer not
  257. initialized) */
  258. if (state->size)
  259. {
  260. if (strm->avail_in == 0)
  261. strm->next_in = state->in;
  262. have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
  263. if (have < state->size)
  264. {
  265. state->in[have] = c;
  266. strm->avail_in++;
  267. state->x.pos++;
  268. return c & 0xff;
  269. }
  270. }
  271. /* no room in buffer or not initialized, use gz_write() */
  272. buf[0] = c;
  273. if (gzwrite(file, buf, 1) != 1)
  274. return -1;
  275. return c & 0xff;
  276. }
  277. /* -- see zlib.h -- */
  278. int ZEXPORT gzputs(file, str)
  279. gzFile file;
  280. const char *str;
  281. {
  282. int ret;
  283. unsigned len;
  284. /* write string */
  285. len = (unsigned)strlen(str);
  286. ret = gzwrite(file, str, len);
  287. return ret == 0 && len != 0 ? -1 : ret;
  288. }
  289. #if defined(STDC) || defined(Z_HAVE_STDARG_H)
  290. #include <stdarg.h>
  291. /* -- see zlib.h -- */
  292. int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
  293. {
  294. int size, len;
  295. gz_statep state;
  296. z_streamp strm;
  297. /* get internal structure */
  298. if (file == NULL)
  299. return -1;
  300. state = (gz_statep)file;
  301. strm = &(state->strm);
  302. /* check that we're writing and that there's no error */
  303. if (state->mode != GZ_WRITE || state->err != Z_OK)
  304. return 0;
  305. /* make sure we have some buffer space */
  306. if (state->size == 0 && gz_init(state) == -1)
  307. return 0;
  308. /* check for seek request */
  309. if (state->seek)
  310. {
  311. state->seek = 0;
  312. if (gz_zero(state, state->skip) == -1)
  313. return 0;
  314. }
  315. /* consume whatever's left in the input buffer */
  316. if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
  317. return 0;
  318. /* do the printf() into the input buffer, put length in len */
  319. size = (int)(state->size);
  320. state->in[size - 1] = 0;
  321. #ifdef NO_vsnprintf
  322. #ifdef HAS_vsprintf_void
  323. (void)vsprintf((char *)(state->in), format, va);
  324. for (len = 0; len < size; len++)
  325. if (state->in[len] == 0) break;
  326. #else
  327. len = vsprintf((char *)(state->in), format, va);
  328. #endif
  329. #else
  330. #ifdef HAS_vsnprintf_void
  331. (void)vsnprintf((char *)(state->in), size, format, va);
  332. len = strlen((char *)(state->in));
  333. #else
  334. len = vsnprintf((char *)(state->in), size, format, va);
  335. #endif
  336. #endif
  337. /* check that printf() results fit in buffer */
  338. if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
  339. return 0;
  340. /* update buffer and position, defer compression until needed */
  341. strm->avail_in = (unsigned)len;
  342. strm->next_in = state->in;
  343. state->x.pos += len;
  344. return len;
  345. }
  346. int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
  347. {
  348. va_list va;
  349. int ret;
  350. va_start(va, format);
  351. ret = gzvprintf(file, format, va);
  352. va_end(va);
  353. return ret;
  354. }
  355. #else /* !STDC && !Z_HAVE_STDARG_H */
  356. /* -- see zlib.h -- */
  357. int ZEXPORTVA gzprintf(file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
  358. a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
  359. gzFile file;
  360. const char *format;
  361. int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
  362. a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
  363. {
  364. int size, len;
  365. gz_statep state;
  366. z_streamp strm;
  367. /* get internal structure */
  368. if (file == NULL)
  369. return -1;
  370. state = (gz_statep)file;
  371. strm = &(state->strm);
  372. /* check that can really pass pointer in ints */
  373. if (sizeof(int) != sizeof(void *))
  374. return 0;
  375. /* check that we're writing and that there's no error */
  376. if (state->mode != GZ_WRITE || state->err != Z_OK)
  377. return 0;
  378. /* make sure we have some buffer space */
  379. if (state->size == 0 && gz_init(state) == -1)
  380. return 0;
  381. /* check for seek request */
  382. if (state->seek)
  383. {
  384. state->seek = 0;
  385. if (gz_zero(state, state->skip) == -1)
  386. return 0;
  387. }
  388. /* consume whatever's left in the input buffer */
  389. if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
  390. return 0;
  391. /* do the printf() into the input buffer, put length in len */
  392. size = (int)(state->size);
  393. state->in[size - 1] = 0;
  394. #ifdef NO_snprintf
  395. #ifdef HAS_sprintf_void
  396. sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
  397. a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
  398. for (len = 0; len < size; len++)
  399. if (state->in[len] == 0) break;
  400. #else
  401. len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
  402. a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
  403. #endif
  404. #else
  405. #ifdef HAS_snprintf_void
  406. snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
  407. a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
  408. len = strlen((char *)(state->in));
  409. #else
  410. len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6,
  411. a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
  412. a19, a20);
  413. #endif
  414. #endif
  415. /* check that printf() results fit in buffer */
  416. if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
  417. return 0;
  418. /* update buffer and position, defer compression until needed */
  419. strm->avail_in = (unsigned)len;
  420. strm->next_in = state->in;
  421. state->x.pos += len;
  422. return len;
  423. }
  424. #endif
  425. /* -- see zlib.h -- */
  426. int ZEXPORT gzflush(file, flush)
  427. gzFile file;
  428. int flush;
  429. {
  430. gz_statep state;
  431. /* get internal structure */
  432. if (file == NULL)
  433. return -1;
  434. state = (gz_statep)file;
  435. /* check that we're writing and that there's no error */
  436. if (state->mode != GZ_WRITE || state->err != Z_OK)
  437. return Z_STREAM_ERROR;
  438. /* check flush parameter */
  439. if (flush < 0 || flush > Z_FINISH)
  440. return Z_STREAM_ERROR;
  441. /* check for seek request */
  442. if (state->seek)
  443. {
  444. state->seek = 0;
  445. if (gz_zero(state, state->skip) == -1)
  446. return -1;
  447. }
  448. /* compress remaining data with requested flush */
  449. gz_comp(state, flush);
  450. return state->err;
  451. }
  452. /* -- see zlib.h -- */
  453. int ZEXPORT gzsetparams(file, level, strategy)
  454. gzFile file;
  455. int level;
  456. int strategy;
  457. {
  458. gz_statep state;
  459. z_streamp strm;
  460. /* get internal structure */
  461. if (file == NULL)
  462. return Z_STREAM_ERROR;
  463. state = (gz_statep)file;
  464. strm = &(state->strm);
  465. /* check that we're writing and that there's no error */
  466. if (state->mode != GZ_WRITE || state->err != Z_OK)
  467. return Z_STREAM_ERROR;
  468. /* if no change is requested, then do nothing */
  469. if (level == state->level && strategy == state->strategy)
  470. return Z_OK;
  471. /* check for seek request */
  472. if (state->seek)
  473. {
  474. state->seek = 0;
  475. if (gz_zero(state, state->skip) == -1)
  476. return -1;
  477. }
  478. /* change compression parameters for subsequent input */
  479. if (state->size)
  480. {
  481. /* flush previous input with previous parameters before changing */
  482. if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
  483. return state->err;
  484. deflateParams(strm, level, strategy);
  485. }
  486. state->level = level;
  487. state->strategy = strategy;
  488. return Z_OK;
  489. }
  490. /* -- see zlib.h -- */
  491. int ZEXPORT gzclose_w(file)
  492. gzFile file;
  493. {
  494. int ret = Z_OK;
  495. gz_statep state;
  496. /* get internal structure */
  497. if (file == NULL)
  498. return Z_STREAM_ERROR;
  499. state = (gz_statep)file;
  500. /* check that we're writing */
  501. if (state->mode != GZ_WRITE)
  502. return Z_STREAM_ERROR;
  503. /* check for seek request */
  504. if (state->seek)
  505. {
  506. state->seek = 0;
  507. if (gz_zero(state, state->skip) == -1)
  508. ret = state->err;
  509. }
  510. /* flush, free memory, and close file */
  511. if (gz_comp(state, Z_FINISH) == -1)
  512. ret = state->err;
  513. if (state->size)
  514. {
  515. if (!state->direct)
  516. {
  517. (void)deflateEnd(&(state->strm));
  518. free(state->out);
  519. }
  520. free(state->in);
  521. }
  522. gz_error(state, Z_OK, NULL);
  523. free(state->path);
  524. if (close(state->fd) == -1)
  525. ret = Z_ERRNO;
  526. free(state);
  527. return ret;
  528. }