ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gzwrite.c
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file gzwrite.c
1 /* gzwrite.c -- zlib functions for writing gzip files
2  * Copyright (C) 2004-2017 Mark Adler
3  * For conditions of distribution and use, see copyright notice in zlib.h
4  */
5 
6 #include "gzguts.h"
7 
8 /* Local functions */
10 local int gz_comp OF((gz_statep, int));
11 local int gz_zero OF((gz_statep, z_off64_t));
12 local z_size_t gz_write OF((gz_statep, voidpc, z_size_t));
13 
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 local int gz_init(state)
18  gz_statep state;
19 {
20  int ret;
21  z_streamp strm = &(state->strm);
22 
23  /* allocate input buffer (double size for gzprintf) */
24  state->in = (unsigned char *)malloc(state->want << 1);
25  if (state->in == NULL) {
26  gz_error(state, Z_MEM_ERROR, "out of memory");
27  return -1;
28  }
29 
30  /* only need output buffer and deflate state if compressing */
31  if (!state->direct) {
32  /* allocate output buffer */
33  state->out = (unsigned char *)malloc(state->want);
34  if (state->out == NULL) {
35  free(state->in);
36  gz_error(state, Z_MEM_ERROR, "out of memory");
37  return -1;
38  }
39 
40  /* allocate deflate memory, set up for gzip compression */
41  strm->zalloc = Z_NULL;
42  strm->zfree = Z_NULL;
43  strm->opaque = Z_NULL;
44  ret = deflateInit2(strm, state->level, Z_DEFLATED,
45  MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
46  if (ret != Z_OK) {
47  free(state->out);
48  free(state->in);
49  gz_error(state, Z_MEM_ERROR, "out of memory");
50  return -1;
51  }
52  strm->next_in = NULL;
53  }
54 
55  /* mark state as initialized */
56  state->size = state->want;
57 
58  /* initialize write buffer if compressing */
59  if (!state->direct) {
60  strm->avail_out = state->size;
61  strm->next_out = state->out;
62  state->x.next = strm->next_out;
63  }
64  return 0;
65 }
66 
67 /* Compress whatever is at avail_in and next_in and write to the output file.
68  Return -1 if there is an error writing to the output file or if gz_init()
69  fails to allocate memory, otherwise 0. flush is assumed to be a valid
70  deflate() flush value. If flush is Z_FINISH, then the deflate() state is
71  reset to start a new gzip stream. If gz->direct is true, then simply write
72  to the output file without compressing, and ignore flush. */
73 local int gz_comp(state, flush)
74  gz_statep state;
75  int flush;
76 {
77  int ret, writ;
78  unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
79  z_streamp strm = &(state->strm);
80 
81  /* allocate memory if this is the first time through */
82  if (state->size == 0 && gz_init(state) == -1)
83  return -1;
84 
85  /* write directly if requested */
86  if (state->direct) {
87  while (strm->avail_in) {
88  put = strm->avail_in > max ? max : strm->avail_in;
89  writ = write(state->fd, strm->next_in, put);
90  if (writ < 0) {
91  gz_error(state, Z_ERRNO, zstrerror());
92  return -1;
93  }
94  strm->avail_in -= (unsigned)writ;
95  strm->next_in += writ;
96  }
97  return 0;
98  }
99 
100  /* run deflate() on provided input until it produces no more output */
101  ret = Z_OK;
102  do {
103  /* write out current buffer contents if full, or if flushing, but if
104  doing Z_FINISH then don't write until we get to Z_STREAM_END */
105  if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
106  (flush != Z_FINISH || ret == Z_STREAM_END))) {
107  while (strm->next_out > state->x.next) {
108  put = strm->next_out - state->x.next > (int)max ? max :
109  (unsigned)(strm->next_out - state->x.next);
110  writ = write(state->fd, state->x.next, put);
111  if (writ < 0) {
112  gz_error(state, Z_ERRNO, zstrerror());
113  return -1;
114  }
115  state->x.next += writ;
116  }
117  if (strm->avail_out == 0) {
118  strm->avail_out = state->size;
119  strm->next_out = state->out;
120  state->x.next = state->out;
121  }
122  }
123 
124  /* compress */
125  have = strm->avail_out;
126  ret = deflate(strm, flush);
127  if (ret == Z_STREAM_ERROR) {
128  gz_error(state, Z_STREAM_ERROR,
129  "internal error: deflate stream corrupt");
130  return -1;
131  }
132  have -= strm->avail_out;
133  } while (have);
134 
135  /* if that completed a deflate stream, allow another to start */
136  if (flush == Z_FINISH)
137  deflateReset(strm);
138 
139  /* all done, no errors */
140  return 0;
141 }
142 
143 /* Compress len zeros to output. Return -1 on a write error or memory
144  allocation failure by gz_comp(), or 0 on success. */
145 local int gz_zero(state, len)
146  gz_statep state;
147  z_off64_t len;
148 {
149  int first;
150  unsigned n;
151  z_streamp strm = &(state->strm);
152 
153  /* consume whatever's left in the input buffer */
154  if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
155  return -1;
156 
157  /* compress len zeros (len guaranteed > 0) */
158  first = 1;
159  while (len) {
160  n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
161  (unsigned)len : state->size;
162  if (first) {
163  memset(state->in, 0, n);
164  first = 0;
165  }
166  strm->avail_in = n;
167  strm->next_in = state->in;
168  state->x.pos += n;
169  if (gz_comp(state, Z_NO_FLUSH) == -1)
170  return -1;
171  len -= n;
172  }
173  return 0;
174 }
175 
176 /* Write len bytes from buf to file. Return the number of bytes written. If
177  the returned value is less than len, then there was an error. */
178 local z_size_t gz_write(state, buf, len)
179  gz_statep state;
180  voidpc buf;
181  z_size_t len;
182 {
183  z_size_t put = len;
184 
185  /* if len is zero, avoid unnecessary operations */
186  if (len == 0)
187  return 0;
188 
189  /* allocate memory if this is the first time through */
190  if (state->size == 0 && gz_init(state) == -1)
191  return 0;
192 
193  /* check for seek request */
194  if (state->seek) {
195  state->seek = 0;
196  if (gz_zero(state, state->skip) == -1)
197  return 0;
198  }
199 
200  /* for small len, copy to input buffer, otherwise compress directly */
201  if (len < state->size) {
202  /* copy to input buffer, compress when full */
203  do {
204  unsigned have, copy;
205 
206  if (state->strm.avail_in == 0)
207  state->strm.next_in = state->in;
208  have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
209  state->in);
210  copy = state->size - have;
211  if (copy > len)
212  copy = (unsigned)len;
213  memcpy(state->in + have, buf, copy);
214  state->strm.avail_in += copy;
215  state->x.pos += copy;
216  buf = (const char *)buf + copy;
217  len -= copy;
218  if (len && gz_comp(state, Z_NO_FLUSH) == -1)
219  return 0;
220  } while (len);
221  }
222  else {
223  /* consume whatever's left in the input buffer */
224  if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
225  return 0;
226 
227  /* directly compress user buffer to file */
228  state->strm.next_in = (z_const Bytef *)buf;
229  do {
230  unsigned n = (unsigned)-1;
231  if (n > len)
232  n = (unsigned)len;
233  state->strm.avail_in = n;
234  state->x.pos += n;
235  if (gz_comp(state, Z_NO_FLUSH) == -1)
236  return 0;
237  len -= n;
238  } while (len);
239  }
240 
241  /* input was all buffered or compressed */
242  return put;
243 }
244 
245 /* -- see zlib.h -- */
246 int ZEXPORT gzwrite(file, buf, len)
247  gzFile file;
248  voidpc buf;
249  unsigned len;
250 {
251  gz_statep state;
252 
253  /* get internal structure */
254  if (file == NULL)
255  return 0;
256  state = (gz_statep)file;
257 
258  /* check that we're writing and that there's no error */
259  if (state->mode != GZ_WRITE || state->err != Z_OK)
260  return 0;
261 
262  /* since an int is returned, make sure len fits in one, otherwise return
263  with an error (this avoids a flaw in the interface) */
264  if ((int)len < 0) {
265  gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
266  return 0;
267  }
268 
269  /* write len bytes from buf (the return value will fit in an int) */
270  return (int)gz_write(state, buf, len);
271 }
272 
273 /* -- see zlib.h -- */
274 z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
275  voidpc buf;
276  z_size_t size;
277  z_size_t nitems;
278  gzFile file;
279 {
280  z_size_t len;
281  gz_statep state;
282 
283  /* get internal structure */
284  if (file == NULL)
285  return 0;
286  state = (gz_statep)file;
287 
288  /* check that we're writing and that there's no error */
289  if (state->mode != GZ_WRITE || state->err != Z_OK)
290  return 0;
291 
292  /* compute bytes to read -- error on overflow */
293  len = nitems * size;
294  if (size && len / size != nitems) {
295  gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
296  return 0;
297  }
298 
299  /* write len bytes to buf, return the number of full items written */
300  return len ? gz_write(state, buf, len) / size : 0;
301 }
302 
303 /* -- see zlib.h -- */
304 int ZEXPORT gzputc(file, c)
305  gzFile file;
306  int c;
307 {
308  unsigned have;
309  unsigned char buf[1];
310  gz_statep state;
311  z_streamp strm;
312 
313  /* get internal structure */
314  if (file == NULL)
315  return -1;
316  state = (gz_statep)file;
317  strm = &(state->strm);
318 
319  /* check that we're writing and that there's no error */
320  if (state->mode != GZ_WRITE || state->err != Z_OK)
321  return -1;
322 
323  /* check for seek request */
324  if (state->seek) {
325  state->seek = 0;
326  if (gz_zero(state, state->skip) == -1)
327  return -1;
328  }
329 
330  /* try writing to input buffer for speed (state->size == 0 if buffer not
331  initialized) */
332  if (state->size) {
333  if (strm->avail_in == 0)
334  strm->next_in = state->in;
335  have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
336  if (have < state->size) {
337  state->in[have] = (unsigned char)c;
338  strm->avail_in++;
339  state->x.pos++;
340  return c & 0xff;
341  }
342  }
343 
344  /* no room in buffer or not initialized, use gz_write() */
345  buf[0] = (unsigned char)c;
346  if (gz_write(state, buf, 1) != 1)
347  return -1;
348  return c & 0xff;
349 }
350 
351 /* -- see zlib.h -- */
352 int ZEXPORT gzputs(file, str)
353  gzFile file;
354  const char *str;
355 {
356  int ret;
357  z_size_t len;
358  gz_statep state;
359 
360  /* get internal structure */
361  if (file == NULL)
362  return -1;
363  state = (gz_statep)file;
364 
365  /* check that we're writing and that there's no error */
366  if (state->mode != GZ_WRITE || state->err != Z_OK)
367  return -1;
368 
369  /* write string */
370  len = strlen(str);
371  if (len > INT_MAX) {
372  gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
373  return -1;
374  }
375 
376  /* write len bytes from buf (the return value will fit in an int) */
377  ret = (int)gz_write(state, str, len);
378  return ret < (int)len ? -1 : ret;
379 }
380 
381 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
382 #include <stdarg.h>
383 
384 /* -- see zlib.h -- */
385 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
386 {
387  int len;
388  unsigned left;
389  char *next;
390  gz_statep state;
391  z_streamp strm;
392 
393  /* get internal structure */
394  if (file == NULL)
395  return Z_STREAM_ERROR;
396  state = (gz_statep)file;
397  strm = &(state->strm);
398 
399  /* check that we're writing and that there's no error */
400  if (state->mode != GZ_WRITE || state->err != Z_OK)
401  return Z_STREAM_ERROR;
402 
403  /* make sure we have some buffer space */
404  if (state->size == 0 && gz_init(state) == -1)
405  return state->err;
406 
407  /* check for seek request */
408  if (state->seek) {
409  state->seek = 0;
410  if (gz_zero(state, state->skip) == -1)
411  return state->err;
412  }
413 
414  /* do the printf() into the input buffer, put length in len -- the input
415  buffer is double-sized just for this function, so there is guaranteed to
416  be state->size bytes available after the current contents */
417  if (strm->avail_in == 0)
418  strm->next_in = state->in;
419  next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
420  next[state->size - 1] = 0;
421 #ifdef NO_vsnprintf
422 # ifdef HAS_vsprintf_void
423  (void)vsprintf(next, format, va);
424  for (len = 0; len < state->size; len++)
425  if (next[len] == 0) break;
426 # else
427  len = vsprintf(next, format, va);
428 # endif
429 #else
430 # ifdef HAS_vsnprintf_void
431  (void)vsnprintf(next, state->size, format, va);
432  len = strlen(next);
433 # else
434  len = vsnprintf(next, state->size, format, va);
435 # endif
436 #endif
437 
438  /* check that printf() results fit in buffer */
439  if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
440  return 0;
441 
442  /* update buffer and position, compress first half if past that */
443  strm->avail_in += (unsigned)len;
444  state->x.pos += len;
445  if (strm->avail_in >= state->size) {
446  left = strm->avail_in - state->size;
447  strm->avail_in = state->size;
448  if (gz_comp(state, Z_NO_FLUSH) == -1)
449  return state->err;
450  memcpy(state->in, state->in + state->size, left);
451  strm->next_in = state->in;
452  strm->avail_in = left;
453  }
454  return len;
455 }
456 
457 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
458 {
459  va_list va;
460  int ret;
461 
462  va_start(va, format);
463  ret = gzvprintf(file, format, va);
464  va_end(va);
465  return ret;
466 }
467 
468 #else /* !STDC && !Z_HAVE_STDARG_H */
469 
470 /* -- see zlib.h -- */
471 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
472  a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
473  gzFile file;
474  const char *format;
475  int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
476  a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
477 {
478  unsigned len, left;
479  char *next;
480  gz_statep state;
481  z_streamp strm;
482 
483  /* get internal structure */
484  if (file == NULL)
485  return Z_STREAM_ERROR;
486  state = (gz_statep)file;
487  strm = &(state->strm);
488 
489  /* check that can really pass pointer in ints */
490  if (sizeof(int) != sizeof(void *))
491  return Z_STREAM_ERROR;
492 
493  /* check that we're writing and that there's no error */
494  if (state->mode != GZ_WRITE || state->err != Z_OK)
495  return Z_STREAM_ERROR;
496 
497  /* make sure we have some buffer space */
498  if (state->size == 0 && gz_init(state) == -1)
499  return state->error;
500 
501  /* check for seek request */
502  if (state->seek) {
503  state->seek = 0;
504  if (gz_zero(state, state->skip) == -1)
505  return state->error;
506  }
507 
508  /* do the printf() into the input buffer, put length in len -- the input
509  buffer is double-sized just for this function, so there is guaranteed to
510  be state->size bytes available after the current contents */
511  if (strm->avail_in == 0)
512  strm->next_in = state->in;
513  next = (char *)(strm->next_in + strm->avail_in);
514  next[state->size - 1] = 0;
515 #ifdef NO_snprintf
516 # ifdef HAS_sprintf_void
517  sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
518  a13, a14, a15, a16, a17, a18, a19, a20);
519  for (len = 0; len < size; len++)
520  if (next[len] == 0)
521  break;
522 # else
523  len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
524  a12, a13, a14, a15, a16, a17, a18, a19, a20);
525 # endif
526 #else
527 # ifdef HAS_snprintf_void
528  snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
529  a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
530  len = strlen(next);
531 # else
532  len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
533  a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
534 # endif
535 #endif
536 
537  /* check that printf() results fit in buffer */
538  if (len == 0 || len >= state->size || next[state->size - 1] != 0)
539  return 0;
540 
541  /* update buffer and position, compress first half if past that */
542  strm->avail_in += len;
543  state->x.pos += len;
544  if (strm->avail_in >= state->size) {
545  left = strm->avail_in - state->size;
546  strm->avail_in = state->size;
547  if (gz_comp(state, Z_NO_FLUSH) == -1)
548  return state->err;
549  memcpy(state->in, state->in + state->size, left);
550  strm->next_in = state->in;
551  strm->avail_in = left;
552  }
553  return (int)len;
554 }
555 
556 #endif
557 
558 /* -- see zlib.h -- */
559 int ZEXPORT gzflush(file, flush)
560  gzFile file;
561  int flush;
562 {
563  gz_statep state;
564 
565  /* get internal structure */
566  if (file == NULL)
567  return Z_STREAM_ERROR;
568  state = (gz_statep)file;
569 
570  /* check that we're writing and that there's no error */
571  if (state->mode != GZ_WRITE || state->err != Z_OK)
572  return Z_STREAM_ERROR;
573 
574  /* check flush parameter */
575  if (flush < 0 || flush > Z_FINISH)
576  return Z_STREAM_ERROR;
577 
578  /* check for seek request */
579  if (state->seek) {
580  state->seek = 0;
581  if (gz_zero(state, state->skip) == -1)
582  return state->err;
583  }
584 
585  /* compress remaining data with requested flush */
586  (void)gz_comp(state, flush);
587  return state->err;
588 }
589 
590 /* -- see zlib.h -- */
591 int ZEXPORT gzsetparams(file, level, strategy)
592  gzFile file;
593  int level;
594  int strategy;
595 {
596  gz_statep state;
597  z_streamp strm;
598 
599  /* get internal structure */
600  if (file == NULL)
601  return Z_STREAM_ERROR;
602  state = (gz_statep)file;
603  strm = &(state->strm);
604 
605  /* check that we're writing and that there's no error */
606  if (state->mode != GZ_WRITE || state->err != Z_OK)
607  return Z_STREAM_ERROR;
608 
609  /* if no change is requested, then do nothing */
610  if (level == state->level && strategy == state->strategy)
611  return Z_OK;
612 
613  /* check for seek request */
614  if (state->seek) {
615  state->seek = 0;
616  if (gz_zero(state, state->skip) == -1)
617  return state->err;
618  }
619 
620  /* change compression parameters for subsequent input */
621  if (state->size) {
622  /* flush previous input with previous parameters before changing */
623  if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
624  return state->err;
625  deflateParams(strm, level, strategy);
626  }
627  state->level = level;
628  state->strategy = strategy;
629  return Z_OK;
630 }
631 
632 /* -- see zlib.h -- */
633 int ZEXPORT gzclose_w(file)
634  gzFile file;
635 {
636  int ret = Z_OK;
637  gz_statep state;
638 
639  /* get internal structure */
640  if (file == NULL)
641  return Z_STREAM_ERROR;
642  state = (gz_statep)file;
643 
644  /* check that we're writing */
645  if (state->mode != GZ_WRITE)
646  return Z_STREAM_ERROR;
647 
648  /* check for seek request */
649  if (state->seek) {
650  state->seek = 0;
651  if (gz_zero(state, state->skip) == -1)
652  ret = state->err;
653  }
654 
655  /* flush, free memory, and close file */
656  if (gz_comp(state, Z_FINISH) == -1)
657  ret = state->err;
658  if (state->size) {
659  if (!state->direct) {
660  (void)deflateEnd(&(state->strm));
661  free(state->out);
662  }
663  free(state->in);
664  }
665  gz_error(state, Z_OK, NULL);
666  free(state->path);
667  if (close(state->fd) == -1)
668  ret = Z_ERRNO;
669  free(state);
670  return ret;
671 }