gzwrite.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. /* gzwrite.c -- zlib functions for writing gzip files
  2. * Copyright (C) 2004-2019 Mark Adler
  3. * For conditions of distribution and use, see copyright notice in zlib.h
  4. */
  5. #include "zbuild.h"
  6. #include "zutil_p.h"
  7. #include <stdarg.h>
  8. #include "gzguts.h"
  9. /* Local functions */
  10. static int gz_init(gz_state *);
  11. static int gz_comp(gz_state *, int);
  12. static int gz_zero(gz_state *, z_off64_t);
  13. static size_t gz_write(gz_state *, void const *, size_t);
  14. /* Initialize state for writing a gzip file. Mark initialization by setting
  15. state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
  16. success. */
  17. static int gz_init(gz_state *state) {
  18. int ret;
  19. PREFIX3(stream) *strm = &(state->strm);
  20. /* allocate input buffer (double size for gzprintf) */
  21. state->in = (unsigned char *)zng_alloc(state->want << 1);
  22. if (state->in == NULL) {
  23. gz_error(state, Z_MEM_ERROR, "out of memory");
  24. return -1;
  25. }
  26. memset(state->in, 0, state->want << 1);
  27. /* only need output buffer and deflate state if compressing */
  28. if (!state->direct) {
  29. /* allocate output buffer */
  30. state->out = (unsigned char *)zng_alloc(state->want);
  31. if (state->out == NULL) {
  32. zng_free(state->in);
  33. gz_error(state, Z_MEM_ERROR, "out of memory");
  34. return -1;
  35. }
  36. /* allocate deflate memory, set up for gzip compression */
  37. strm->zalloc = NULL;
  38. strm->zfree = NULL;
  39. strm->opaque = NULL;
  40. ret = PREFIX(deflateInit2)(strm, state->level, Z_DEFLATED, MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
  41. if (ret != Z_OK) {
  42. zng_free(state->out);
  43. zng_free(state->in);
  44. gz_error(state, Z_MEM_ERROR, "out of memory");
  45. return -1;
  46. }
  47. strm->next_in = NULL;
  48. }
  49. /* mark state as initialized */
  50. state->size = state->want;
  51. /* initialize write buffer if compressing */
  52. if (!state->direct) {
  53. strm->avail_out = state->size;
  54. strm->next_out = state->out;
  55. state->x.next = strm->next_out;
  56. }
  57. return 0;
  58. }
  59. /* Compress whatever is at avail_in and next_in and write to the output file.
  60. Return -1 if there is an error writing to the output file or if gz_init()
  61. fails to allocate memory, otherwise 0. flush is assumed to be a valid
  62. deflate() flush value. If flush is Z_FINISH, then the deflate() state is
  63. reset to start a new gzip stream. If gz->direct is true, then simply write
  64. to the output file without compressing, and ignore flush. */
  65. static int gz_comp(gz_state *state, int flush) {
  66. int ret;
  67. ssize_t got;
  68. unsigned have;
  69. PREFIX3(stream) *strm = &(state->strm);
  70. /* allocate memory if this is the first time through */
  71. if (state->size == 0 && gz_init(state) == -1)
  72. return -1;
  73. /* write directly if requested */
  74. if (state->direct) {
  75. got = write(state->fd, strm->next_in, strm->avail_in);
  76. if (got < 0 || (unsigned)got != strm->avail_in) {
  77. gz_error(state, Z_ERRNO, zstrerror());
  78. return -1;
  79. }
  80. strm->avail_in = 0;
  81. return 0;
  82. }
  83. /* check for a pending reset */
  84. if (state->reset) {
  85. /* don't start a new gzip member unless there is data to write */
  86. if (strm->avail_in == 0)
  87. return 0;
  88. PREFIX(deflateReset)(strm);
  89. state->reset = 0;
  90. }
  91. /* run deflate() on provided input until it produces no more output */
  92. ret = Z_OK;
  93. do {
  94. /* write out current buffer contents if full, or if flushing, but if
  95. doing Z_FINISH then don't write until we get to Z_STREAM_END */
  96. if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) {
  97. have = (unsigned)(strm->next_out - state->x.next);
  98. if (have && ((got = write(state->fd, state->x.next, (unsigned long)have)) < 0 || (unsigned)got != have)) {
  99. gz_error(state, Z_ERRNO, zstrerror());
  100. return -1;
  101. }
  102. if (strm->avail_out == 0) {
  103. strm->avail_out = state->size;
  104. strm->next_out = state->out;
  105. state->x.next = state->out;
  106. }
  107. state->x.next = strm->next_out;
  108. }
  109. /* compress */
  110. have = strm->avail_out;
  111. ret = PREFIX(deflate)(strm, flush);
  112. if (ret == Z_STREAM_ERROR) {
  113. gz_error(state, Z_STREAM_ERROR, "internal error: deflate stream corrupt");
  114. return -1;
  115. }
  116. have -= strm->avail_out;
  117. } while (have);
  118. /* if that completed a deflate stream, allow another to start */
  119. if (flush == Z_FINISH)
  120. state->reset = 1;
  121. /* all done, no errors */
  122. return 0;
  123. }
  124. /* Compress len zeros to output. Return -1 on a write error or memory
  125. allocation failure by gz_comp(), or 0 on success. */
  126. static int gz_zero(gz_state *state, z_off64_t len) {
  127. int first;
  128. unsigned n;
  129. PREFIX3(stream) *strm = &(state->strm);
  130. /* consume whatever's left in the input buffer */
  131. if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
  132. return -1;
  133. /* compress len zeros (len guaranteed > 0) */
  134. first = 1;
  135. while (len) {
  136. n = GT_OFF(state->size) || (z_off64_t)state->size > len ? (unsigned)len : state->size;
  137. if (first) {
  138. memset(state->in, 0, n);
  139. first = 0;
  140. }
  141. strm->avail_in = n;
  142. strm->next_in = state->in;
  143. state->x.pos += n;
  144. if (gz_comp(state, Z_NO_FLUSH) == -1)
  145. return -1;
  146. len -= n;
  147. }
  148. return 0;
  149. }
  150. /* Write len bytes from buf to file. Return the number of bytes written. If
  151. the returned value is less than len, then there was an error. */
  152. static size_t gz_write(gz_state *state, void const *buf, size_t len) {
  153. size_t put = len;
  154. /* if len is zero, avoid unnecessary operations */
  155. if (len == 0)
  156. return 0;
  157. /* allocate memory if this is the first time through */
  158. if (state->size == 0 && gz_init(state) == -1)
  159. return 0;
  160. /* check for seek request */
  161. if (state->seek) {
  162. state->seek = 0;
  163. if (gz_zero(state, state->skip) == -1)
  164. return 0;
  165. }
  166. /* for small len, copy to input buffer, otherwise compress directly */
  167. if (len < state->size) {
  168. /* copy to input buffer, compress when full */
  169. do {
  170. unsigned have, copy;
  171. if (state->strm.avail_in == 0)
  172. state->strm.next_in = state->in;
  173. have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
  174. state->in);
  175. copy = state->size - have;
  176. if (copy > len)
  177. copy = (unsigned)len;
  178. memcpy(state->in + have, buf, copy);
  179. state->strm.avail_in += copy;
  180. state->x.pos += copy;
  181. buf = (const char *)buf + copy;
  182. len -= copy;
  183. if (len && gz_comp(state, Z_NO_FLUSH) == -1)
  184. return 0;
  185. } while (len);
  186. } else {
  187. /* consume whatever's left in the input buffer */
  188. if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
  189. return 0;
  190. /* directly compress user buffer to file */
  191. state->strm.next_in = (z_const unsigned char *) buf;
  192. do {
  193. unsigned n = (unsigned)-1;
  194. if (n > len)
  195. n = (unsigned)len;
  196. state->strm.avail_in = n;
  197. state->x.pos += n;
  198. if (gz_comp(state, Z_NO_FLUSH) == -1)
  199. return 0;
  200. len -= n;
  201. } while (len);
  202. }
  203. /* input was all buffered or compressed */
  204. return put;
  205. }
  206. /* -- see zlib.h -- */
  207. int Z_EXPORT PREFIX(gzwrite)(gzFile file, void const *buf, unsigned len) {
  208. gz_state *state;
  209. /* get internal structure */
  210. if (file == NULL)
  211. return 0;
  212. state = (gz_state *)file;
  213. /* check that we're writing and that there's no error */
  214. if (state->mode != GZ_WRITE || state->err != Z_OK)
  215. return 0;
  216. /* since an int is returned, make sure len fits in one, otherwise return
  217. with an error (this avoids a flaw in the interface) */
  218. if ((int)len < 0) {
  219. gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
  220. return 0;
  221. }
  222. /* write len bytes from buf (the return value will fit in an int) */
  223. return (int)gz_write(state, buf, len);
  224. }
  225. /* -- see zlib.h -- */
  226. size_t Z_EXPORT PREFIX(gzfwrite)(void const *buf, size_t size, size_t nitems, gzFile file) {
  227. size_t len;
  228. gz_state *state;
  229. /* Exit early if size is zero, also prevents potential division by zero */
  230. if (size == 0)
  231. return 0;
  232. /* get internal structure */
  233. if (file == NULL)
  234. return 0;
  235. state = (gz_state *)file;
  236. /* check that we're writing and that there's no error */
  237. if (state->mode != GZ_WRITE || state->err != Z_OK)
  238. return 0;
  239. /* compute bytes to read -- error on overflow */
  240. len = nitems * size;
  241. if (len / size != nitems) {
  242. gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
  243. return 0;
  244. }
  245. /* write len bytes to buf, return the number of full items written */
  246. return len ? gz_write(state, buf, len) / size : 0;
  247. }
  248. /* -- see zlib.h -- */
  249. int Z_EXPORT PREFIX(gzputc)(gzFile file, int c) {
  250. unsigned have;
  251. unsigned char buf[1];
  252. gz_state *state;
  253. PREFIX3(stream) *strm;
  254. /* get internal structure */
  255. if (file == NULL)
  256. return -1;
  257. state = (gz_state *)file;
  258. strm = &(state->strm);
  259. /* check that we're writing and that there's no error */
  260. if (state->mode != GZ_WRITE || state->err != Z_OK)
  261. return -1;
  262. /* check for seek request */
  263. if (state->seek) {
  264. state->seek = 0;
  265. if (gz_zero(state, state->skip) == -1)
  266. return -1;
  267. }
  268. /* try writing to input buffer for speed (state->size == 0 if buffer not
  269. initialized) */
  270. if (state->size) {
  271. if (strm->avail_in == 0)
  272. strm->next_in = state->in;
  273. have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
  274. if (have < state->size) {
  275. state->in[have] = (unsigned char)c;
  276. strm->avail_in++;
  277. state->x.pos++;
  278. return c & 0xff;
  279. }
  280. }
  281. /* no room in buffer or not initialized, use gz_write() */
  282. buf[0] = (unsigned char)c;
  283. if (gz_write(state, buf, 1) != 1)
  284. return -1;
  285. return c & 0xff;
  286. }
  287. /* -- see zlib.h -- */
  288. int Z_EXPORT PREFIX(gzputs)(gzFile file, const char *s) {
  289. size_t len, put;
  290. gz_state *state;
  291. /* get internal structure */
  292. if (file == NULL)
  293. return -1;
  294. state = (gz_state *)file;
  295. /* check that we're writing and that there's no error */
  296. if (state->mode != GZ_WRITE || state->err != Z_OK)
  297. return -1;
  298. /* write string */
  299. len = strlen(s);
  300. if ((int)len < 0 || (unsigned)len != len) {
  301. gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
  302. return -1;
  303. }
  304. put = gz_write(state, s, len);
  305. return put < len ? -1 : (int)len;
  306. }
  307. /* -- see zlib.h -- */
  308. int Z_EXPORTVA PREFIX(gzvprintf)(gzFile file, const char *format, va_list va) {
  309. int len;
  310. unsigned left;
  311. char *next;
  312. gz_state *state;
  313. PREFIX3(stream) *strm;
  314. /* get internal structure */
  315. if (file == NULL)
  316. return Z_STREAM_ERROR;
  317. state = (gz_state *)file;
  318. strm = &(state->strm);
  319. /* check that we're writing and that there's no error */
  320. if (state->mode != GZ_WRITE || state->err != Z_OK)
  321. return Z_STREAM_ERROR;
  322. /* make sure we have some buffer space */
  323. if (state->size == 0 && gz_init(state) == -1)
  324. return state->err;
  325. /* check for seek request */
  326. if (state->seek) {
  327. state->seek = 0;
  328. if (gz_zero(state, state->skip) == -1)
  329. return state->err;
  330. }
  331. /* do the printf() into the input buffer, put length in len -- the input
  332. buffer is double-sized just for this function, so there is guaranteed to
  333. be state->size bytes available after the current contents */
  334. if (strm->avail_in == 0)
  335. strm->next_in = state->in;
  336. next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
  337. next[state->size - 1] = 0;
  338. len = vsnprintf(next, state->size, format, va);
  339. /* check that printf() results fit in buffer */
  340. if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
  341. return 0;
  342. /* update buffer and position, compress first half if past that */
  343. strm->avail_in += (unsigned)len;
  344. state->x.pos += len;
  345. if (strm->avail_in >= state->size) {
  346. left = strm->avail_in - state->size;
  347. strm->avail_in = state->size;
  348. if (gz_comp(state, Z_NO_FLUSH) == -1)
  349. return state->err;
  350. memmove(state->in, state->in + state->size, left);
  351. strm->next_in = state->in;
  352. strm->avail_in = left;
  353. }
  354. return len;
  355. }
  356. int Z_EXPORTVA PREFIX(gzprintf)(gzFile file, const char *format, ...) {
  357. va_list va;
  358. int ret;
  359. va_start(va, format);
  360. ret = PREFIX(gzvprintf)(file, format, va);
  361. va_end(va);
  362. return ret;
  363. }
  364. /* -- see zlib.h -- */
  365. int Z_EXPORT PREFIX(gzflush)(gzFile file, int flush) {
  366. gz_state *state;
  367. /* get internal structure */
  368. if (file == NULL)
  369. return Z_STREAM_ERROR;
  370. state = (gz_state *)file;
  371. /* check that we're writing and that there's no error */
  372. if (state->mode != GZ_WRITE || state->err != Z_OK)
  373. return Z_STREAM_ERROR;
  374. /* check flush parameter */
  375. if (flush < 0 || flush > Z_FINISH)
  376. return Z_STREAM_ERROR;
  377. /* check for seek request */
  378. if (state->seek) {
  379. state->seek = 0;
  380. if (gz_zero(state, state->skip) == -1)
  381. return state->err;
  382. }
  383. /* compress remaining data with requested flush */
  384. (void)gz_comp(state, flush);
  385. return state->err;
  386. }
  387. /* -- see zlib.h -- */
  388. int Z_EXPORT PREFIX(gzsetparams)(gzFile file, int level, int strategy) {
  389. gz_state *state;
  390. PREFIX3(stream) *strm;
  391. /* get internal structure */
  392. if (file == NULL)
  393. return Z_STREAM_ERROR;
  394. state = (gz_state *)file;
  395. strm = &(state->strm);
  396. /* check that we're writing and that there's no error */
  397. if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
  398. return Z_STREAM_ERROR;
  399. /* if no change is requested, then do nothing */
  400. if (level == state->level && strategy == state->strategy)
  401. return Z_OK;
  402. /* check for seek request */
  403. if (state->seek) {
  404. state->seek = 0;
  405. if (gz_zero(state, state->skip) == -1)
  406. return state->err;
  407. }
  408. /* change compression parameters for subsequent input */
  409. if (state->size) {
  410. /* flush previous input with previous parameters before changing */
  411. if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
  412. return state->err;
  413. PREFIX(deflateParams)(strm, level, strategy);
  414. }
  415. state->level = level;
  416. state->strategy = strategy;
  417. return Z_OK;
  418. }
  419. /* -- see zlib.h -- */
  420. int Z_EXPORT PREFIX(gzclose_w)(gzFile file) {
  421. int ret = Z_OK;
  422. gz_state *state;
  423. /* get internal structure */
  424. if (file == NULL)
  425. return Z_STREAM_ERROR;
  426. state = (gz_state *)file;
  427. /* check that we're writing */
  428. if (state->mode != GZ_WRITE)
  429. return Z_STREAM_ERROR;
  430. /* check for seek request */
  431. if (state->seek) {
  432. state->seek = 0;
  433. if (gz_zero(state, state->skip) == -1)
  434. ret = state->err;
  435. }
  436. /* flush, free memory, and close file */
  437. if (gz_comp(state, Z_FINISH) == -1)
  438. ret = state->err;
  439. if (state->size) {
  440. if (!state->direct) {
  441. (void)PREFIX(deflateEnd)(&(state->strm));
  442. zng_free(state->out);
  443. }
  444. zng_free(state->in);
  445. }
  446. gz_error(state, Z_OK, NULL);
  447. free(state->path);
  448. if (close(state->fd) == -1)
  449. ret = Z_ERRNO;
  450. zng_free(state);
  451. return ret;
  452. }