6 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 /* file_access interface based heavily on zlib gzread.c and gzlib.c from zlib
24 * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
27 * This software is provided 'as-is', without any express or implied
28 * warranty. In no event will the authors be held liable for any damages
29 * arising from the use of this software.
31 * Permission is granted to anyone to use this software for any purpose,
32 * including commercial applications, and to alter it and redistribute it
33 * freely, subject to the following restrictions:
35 * 1. The origin of this software must not be misrepresented; you must not
36 * claim that you wrote the original software. If you use this software
37 * in a product, an acknowledgment in the product documentation would be
38 * appreciated but is not required.
39 * 2. Altered source versions must be plainly marked as such, and must not be
40 * misrepresented as being the original software.
41 * 3. This notice may not be removed or altered from any source distribution.
50 #endif /* HAVE_UNISTD_H */
56 #endif /* HAVE_FCNTL_H */
59 #include "file_wrappers.h"
60 #include <wsutil/file_util.h>
63 * See RFC 1952 for a description of the gzip file format.
65 * Some other compressed file formats we might want to support:
67 * XZ format: http://tukaani.org/xz/
69 * Bzip2 format: http://bzip.org/
72 /* #define GZBUFSIZE 8192 */
73 #define GZBUFSIZE 4096
76 int fd; /* file descriptor */
77 gint64 raw_pos; /* current position in file (just to not call lseek()) */
78 gint64 pos; /* current position in uncompressed data */
79 unsigned size; /* buffer size */
80 unsigned char *in; /* input buffer */
81 unsigned char *out; /* output buffer (double-sized when reading) */
82 unsigned char *next; /* next output data to deliver or write */
84 unsigned have; /* amount of output data unused at next */
85 int eof; /* true if end of input file reached */
86 gint64 start; /* where the gzip data started, for rewinding */
87 gint64 raw; /* where the raw data started, for seeking */
88 int compression; /* 0: ?, 1: uncompressed, 2: zlib */
90 gint64 skip; /* amount to skip (already rewound if backwards) */
91 int seek; /* true if seek request pending */
92 /* error information */
93 int err; /* error code */
95 unsigned int avail_in; /* number of bytes available at next_in */
96 unsigned char *next_in; /* next input byte */
98 /* zlib inflate stream */
99 z_stream strm; /* stream structure in-place (not a pointer) */
102 GPtrArray *fast_seek;
106 /* values for gz_state compression */
107 #define UNKNOWN 0 /* look for a gzip header */
108 #define UNCOMPRESSED 1 /* copy input directly */
110 #define ZLIB 2 /* decompress a zlib stream */
111 #define GZIP_AFTER_HEADER 3
114 static int /* gz_load */
115 raw_read(FILE_T state, unsigned char *buf, unsigned int count, unsigned *have)
121 ret = read(state->fd, buf + *have, count - *have);
125 state->raw_pos += ret;
126 } while (*have < count);
136 static int /* gz_avail */
137 fill_in_buffer(FILE_T state)
141 if (state->eof == 0) {
142 if (raw_read(state, state->in, state->size, (unsigned *)&(state->avail_in)) == -1)
144 state->next_in = state->in;
149 #define ZLIB_WINSIZE 32768
151 struct fast_seek_point {
152 gint64 out; /* corresponding offset in uncompressed data */
153 gint64 in; /* offset in input file of first full byte */
158 int bits; /* number of bits (1-7) from byte at in - 1, or 0 */
159 unsigned char window[ZLIB_WINSIZE]; /* preceding 32K of uncompressed data */
161 /* be gentle with Z_STREAM_END, 8 bytes more... Another solution would be to comment checks out */
168 struct zlib_cur_seek_point {
169 unsigned char window[ZLIB_WINSIZE]; /* preceding 32K of uncompressed data */
174 #define SPAN G_GINT64_CONSTANT(1048576)
175 static struct fast_seek_point *
176 fast_seek_find(FILE_T file, gint64 pos)
178 struct fast_seek_point *smallest = NULL;
179 struct fast_seek_point *item;
182 if (!file->fast_seek)
185 for (low = 0, max = file->fast_seek->len; low < max; ) {
187 item = file->fast_seek->pdata[i];
191 else if (pos > item->out) {
202 fast_seek_header(FILE_T file, gint64 in_pos, gint64 out_pos, int compression)
204 struct fast_seek_point *item = NULL;
206 if (file->fast_seek->len != 0)
207 item = file->fast_seek->pdata[file->fast_seek->len - 1];
209 if (!item || item->out < out_pos) {
210 struct fast_seek_point *val = g_malloc(sizeof(struct fast_seek_point));
213 val->compression = compression;
215 g_ptr_array_add(file->fast_seek, val);
220 fast_seek_reset(FILE_T state _U_)
223 if (state->compression == ZLIB && state->fast_seek_cur) {
224 struct zlib_cur_seek_point *cur = (struct zlib_cur_seek_point *) state->fast_seek_cur;
233 /* Get next byte from input, or -1 if end or error. */
234 #define NEXT() ((state->avail_in == 0 && fill_in_buffer(state) == -1) ? -1 : \
235 (state->avail_in == 0 ? -1 : \
236 (state->avail_in--, *(state->next_in)++)))
238 /* Get a four-byte little-endian integer and return 0 on success and the value
239 in *ret. Otherwise -1 is returned and *ret is not modified. */
241 gz_next4(FILE_T state, guint32 *ret)
247 val += (unsigned)NEXT() << 8;
248 val += (guint32)NEXT() << 16;
252 val += (guint32)ch << 24;
258 zlib_fast_seek_add(FILE_T file, struct zlib_cur_seek_point *point, int bits, gint64 in_pos, gint64 out_pos)
260 /* it's for sure after gzip header, so file->fast_seek->len != 0 */
261 struct fast_seek_point *item = file->fast_seek->pdata[file->fast_seek->len - 1];;
263 /* Glib has got Balanced Binary Trees (GTree) but I couldn't find a way to do quick search for nearest (and smaller) value to seek (It's what fast_seek_find() do)
264 * Inserting value in middle of sorted array is expensive, so we want to add only in the end.
265 * It's not big deal, cause first-read don't usually invoke seeking
267 if (item->out + SPAN < out_pos) {
268 struct fast_seek_point *val = g_malloc(sizeof(struct fast_seek_point));
271 val->compression = ZLIB;
273 val->data.zlib.bits = bits;
274 if (point->pos != 0) {
275 unsigned int left = ZLIB_WINSIZE - point->pos;
277 memcpy(val->data.zlib.window, point->window + point->pos, left);
278 memcpy(val->data.zlib.window + left, point->window, point->pos);
280 memcpy(val->data.zlib.window, point->window, ZLIB_WINSIZE);
282 val->data.zlib.adler = file->strm.adler;
283 val->data.zlib.total_out = file->strm.total_out;
284 g_ptr_array_add(file->fast_seek, val);
288 static void /* gz_decomp */
289 zlib_read(FILE_T state, unsigned char *buf, unsigned int count)
291 int ret = 0; /* XXX */
293 z_streamp strm = &(state->strm);
295 unsigned char *buf2 = buf;
296 unsigned int count2 = count;
298 strm->avail_out = count;
299 strm->next_out = buf;
301 /* fill output buffer up to end of deflate stream or error */
303 /* get more input for inflate() */
304 if (state->avail_in == 0 && fill_in_buffer(state) == -1)
306 if (state->avail_in == 0) {
307 state->err = WTAP_ERR_ZLIB + Z_DATA_ERROR;
311 strm->avail_in = state->avail_in;
312 strm->next_in = state->next_in;
313 /* decompress and handle errors */
314 /* ret = inflate(strm, Z_NO_FLUSH); */
315 ret = inflate(strm, Z_BLOCK);
316 state->avail_in = strm->avail_in;
317 state->next_in = strm->next_in;
318 if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
319 state->err = WTAP_ERR_ZLIB + Z_STREAM_ERROR;
322 if (ret == Z_MEM_ERROR) {
323 state->err = WTAP_ERR_ZLIB + Z_MEM_ERROR; /* ENOMEM? */
326 if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
327 state->err = WTAP_ERR_ZLIB + Z_DATA_ERROR;
331 strm->adler = crc32(strm->adler, buf2, count2 - strm->avail_out);
332 if (state->fast_seek_cur) {
333 struct zlib_cur_seek_point *cur = (struct zlib_cur_seek_point *) state->fast_seek_cur;
334 unsigned int ready = count2 - strm->avail_out;
336 if (ready < ZLIB_WINSIZE) {
337 unsigned left = ZLIB_WINSIZE - cur->pos;
340 memcpy(cur->window + cur->pos, buf2, left);
342 memcpy(cur->window, buf2 + left, ready - left);
344 cur->pos = ready - left;
347 memcpy(cur->window + cur->pos, buf2, ready);
352 if (cur->have >= ZLIB_WINSIZE)
353 cur->have = ZLIB_WINSIZE;
356 memcpy(cur->window, buf2 + (ready - ZLIB_WINSIZE), ZLIB_WINSIZE);
358 cur->have = ZLIB_WINSIZE;
361 if (cur->have >= ZLIB_WINSIZE && ret != Z_STREAM_END && (strm->data_type & 128) && !(strm->data_type & 64))
362 zlib_fast_seek_add(state, cur, (strm->data_type & 7), state->raw_pos - strm->avail_in, state->pos + (count - strm->avail_out));
364 buf2 = (buf2 + count2 - strm->avail_out);
365 count2 = strm->avail_out;
367 } while (strm->avail_out && ret != Z_STREAM_END);
369 /* update available output and crc check value */
371 state->have = count - strm->avail_out;
373 /* Check gzip trailer if at end of deflate stream.
374 We don't fail immediately here, we just set an error
375 indication, so that we try to process what data we
376 got before the error. The next attempt to read
377 something past that data will get the error. */
378 if (ret == Z_STREAM_END) {
379 if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1)
380 state->err = WTAP_ERR_ZLIB + Z_DATA_ERROR;
381 else if (crc != strm->adler)
382 state->err = WTAP_ERR_ZLIB + Z_DATA_ERROR;
383 else if (len != (strm->total_out & 0xffffffffL))
384 state->err = WTAP_ERR_ZLIB + Z_DATA_ERROR;
385 state->compression = UNKNOWN; /* ready for next stream, once have is 0 */
386 g_free(state->fast_seek_cur);
387 state->fast_seek_cur = NULL;
393 gz_head(FILE_T state)
395 /* get some data in the input buffer */
396 if (state->avail_in == 0) {
397 if (fill_in_buffer(state) == -1)
399 if (state->avail_in == 0)
403 /* look for the gzip magic header bytes 31 and 139 */
405 if (state->next_in[0] == 31) {
408 if (state->avail_in == 0 && fill_in_buffer(state) == -1)
410 if (state->avail_in && state->next_in[0] == 139) {
414 /* we have a gzip header, woo hoo! */
418 /* skip rest of header */
419 if (NEXT() != 8) { /* compression method */
420 state->err = WTAP_ERR_ZLIB + Z_DATA_ERROR;
424 if (flags & 0xe0) { /* reserved flag bits */
425 state->err = WTAP_ERR_ZLIB + Z_DATA_ERROR;
428 NEXT(); /* modification time */
432 NEXT(); /* extra flags */
433 NEXT(); /* operating system */
434 if (flags & 4) { /* extra field */
435 len = (unsigned)NEXT();
436 len += (unsigned)NEXT() << 8;
441 if (flags & 8) /* file name */
444 if (flags & 16) /* comment */
447 if (flags & 2) { /* header crc */
451 /* an unexpected end of file is not checked for here -- it will be
452 noticed on the first request for uncompressed data */
454 /* set up for decompression */
455 inflateReset(&(state->strm));
456 state->strm.adler = crc32(0L, Z_NULL, 0);
457 state->compression = ZLIB;
459 if (state->fast_seek) {
460 struct zlib_cur_seek_point *cur = g_malloc(sizeof(struct zlib_cur_seek_point));
462 cur->pos = cur->have = 0;
463 g_free(state->fast_seek_cur);
464 state->fast_seek_cur = cur;
465 fast_seek_header(state, state->raw_pos - state->avail_in, state->pos, GZIP_AFTER_HEADER);
470 /* not a gzip file -- save first byte (31) and fall to raw i/o */
477 /* { 0xFD, '7', 'z', 'X', 'Z', 0x00 } */
478 /* FD 37 7A 58 5A 00 */
480 if (state->fast_seek)
481 fast_seek_header(state, state->raw_pos - state->avail_in - state->have, state->pos, UNCOMPRESSED);
483 /* doing raw i/o, save start of raw data for seeking, copy any leftover
484 input to output -- this assumes that the output buffer is larger than
485 the input buffer, which also assures space for gzungetc() */
486 state->raw = state->pos;
487 state->next = state->out;
488 if (state->avail_in) {
489 memcpy(state->next + state->have, state->next_in, state->avail_in);
490 state->have += state->avail_in;
493 state->compression = UNCOMPRESSED;
497 static int /* gz_make */
498 fill_out_buffer(FILE_T state)
500 if (state->compression == UNKNOWN) { /* look for gzip header */
501 if (gz_head(state) == -1)
503 if (state->have) /* got some data from gz_head() */
506 if (state->compression == UNCOMPRESSED) { /* straight copy */
507 if (raw_read(state, state->out, state->size /* << 1 */, &(state->have)) == -1)
509 state->next = state->out;
512 else if (state->compression == ZLIB) { /* decompress */
513 zlib_read(state, state->out, state->size << 1);
520 gz_skip(FILE_T state, gint64 len)
524 /* skip over len bytes or reach end-of-file, whichever comes first */
527 /* We have stuff in the output buffer; skip over
529 n = (gint64)state->have > len ? (unsigned)len : state->have;
534 } else if (state->err) {
535 /* We have nothing in the output buffer, and
536 we have an error that may not have been
537 reported yet; that means we can't generate
538 any more data into the output buffer, so
539 return an error indication. */
541 } else if (state->eof && state->avail_in == 0) {
542 /* We have nothing in the output buffer, and
543 we're at the end of the input; just return. */
546 /* We have nothing in the output buffer, and
547 we can generate more data; get more output,
548 looking for header if required. */
549 if (fill_out_buffer(state) == -1)
556 gz_reset(FILE_T state)
558 state->have = 0; /* no output data available */
559 state->eof = 0; /* not at end of file */
560 state->compression = UNKNOWN; /* look for gzip header */
562 state->seek = 0; /* no seek request pending */
563 state->err = 0; /* clear error */
564 state->pos = 0; /* no uncompressed data yet */
565 state->avail_in = 0; /* no input data yet */
571 #ifdef _STATBUF_ST_BLKSIZE /* XXX, _STATBUF_ST_BLKSIZE portable? */
574 int want = GZBUFSIZE;
580 /* allocate FILE_T structure to return */
581 state = g_try_malloc(sizeof *state);
585 state->fast_seek_cur = NULL;
586 state->fast_seek = NULL;
588 /* open the file with the appropriate mode (or just use fd) */
591 /* save the current position for rewinding (only if reading) */
592 state->start = ws_lseek64(state->fd, 0, SEEK_CUR);
593 if (state->start == -1) state->start = 0;
594 state->raw_pos = state->start;
596 /* initialize stream */
599 #ifdef _STATBUF_ST_BLKSIZE
600 if (fstat(fd, &st) >= 0) {
601 want = st.st_blksize;
602 /* XXX, verify result? */
606 /* allocate buffers */
607 state->in = g_try_malloc(want);
608 state->out = g_try_malloc(want << 1);
610 if (state->in == NULL || state->out == NULL) {
619 /* allocate inflate memory */
620 state->strm.zalloc = Z_NULL;
621 state->strm.zfree = Z_NULL;
622 state->strm.opaque = Z_NULL;
623 state->strm.avail_in = 0;
624 state->strm.next_in = Z_NULL;
625 if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */
638 file_open(const char *path)
643 /* open file and do correct filename conversions.
645 XXX - do we need O_LARGEFILE? On UN*X, if we need to do
646 something special to get large file support, the configure
647 script should have set us up with the appropriate #defines,
648 so we should be getting a large-file-enabled file descriptor
649 here. Pre-Large File Summit UN*Xes, and possibly even some
650 post-LFS UN*Xes, might require O_LARGEFILE here, though.
651 If so, we should probably handle that in ws_open(). */
652 if ((fd = ws_open(path, O_RDONLY|O_BINARY, 0666)) == -1)
655 /* open file handle */
666 file_set_random_access(FILE_T stream, gboolean random _U_, GPtrArray *seek)
668 stream->fast_seek = seek;
672 file_seek(FILE_T file, gint64 offset, int whence, int *err)
674 struct fast_seek_point *here;
677 /* can only seek from start or relative to current position */
678 if (whence != SEEK_SET && whence != SEEK_CUR) {
679 g_assert_not_reached();
686 /* normalize offset to a SEEK_CUR specification */
687 if (whence == SEEK_SET)
690 offset += file->skip;
694 if ((here = fast_seek_find(file, file->pos + offset)) && (offset < 0 || offset > SPAN || here->compression == UNCOMPRESSED)) {
698 if (here->compression == ZLIB) {
699 off = here->in - (here->data.zlib.bits ? 1 : 0);
701 } else if (here->compression == GZIP_AFTER_HEADER) {
707 off2 = (file->pos + offset);
708 off = here->in + (off2 - here->out);
711 if (ws_lseek64(file->fd, off, SEEK_SET) == -1) {
715 fast_seek_reset(file);
725 if (here->compression == ZLIB) {
726 z_stream *strm = &file->strm;
730 strm->adler = here->data.zlib.adler;
731 strm->total_out = here->data.zlib.total_out;
732 if (here->data.zlib.bits) {
740 (void)inflatePrime(strm, here->data.zlib.bits, ret >> (8 - here->data.zlib.bits));
742 (void)inflateSetDictionary(strm, here->data.zlib.window, ZLIB_WINSIZE);
743 file->compression = ZLIB;
744 } else if (here->compression == GZIP_AFTER_HEADER) {
745 z_stream *strm = &file->strm;
748 strm->adler = crc32(0L, Z_NULL, 0);
749 file->compression = ZLIB;
752 file->compression = here->compression;
754 offset = (file->pos + offset) - off2;
756 /* g_print("OK! %ld\n", offset); */
762 return file->pos + offset;
765 /* if within raw area while reading, just go there */
766 if (file->compression == UNCOMPRESSED && file->pos + offset >= file->raw) {
767 if (ws_lseek64(file->fd, offset - file->have, SEEK_CUR) == -1) {
771 file->raw_pos += (offset - file->have);
781 /* calculate skip amount, rewinding if needed for back seek when reading */
784 if (offset < 0) { /* before start of file! */
788 /* rewind, then skip to offset */
790 /* back up and start over */
791 if (ws_lseek64(file->fd, file->start, SEEK_SET) == -1) {
795 fast_seek_reset(file);
796 file->raw_pos = file->start;
800 /* skip what's in output buffer (one less gzgetc() check) */
801 n = (gint64)file->have > offset ? (unsigned)offset : file->have;
807 /* request skip (if not zero) */
812 return file->pos + offset;
816 file_tell(FILE_T stream)
818 /* return position */
819 return stream->pos + (stream->seek ? stream->skip : 0);
823 file_read(void *buf, unsigned int len, FILE_T file)
827 /* if len is zero, avoid unnecessary operations */
831 /* process a skip request */
834 if (gz_skip(file, file->skip) == -1)
838 /* get len bytes to buf, or less than len if at the end */
842 /* We have stuff in the output buffer; copy
844 n = file->have > len ? len : file->have;
845 memcpy(buf, file->next, n);
848 } else if (file->err) {
849 /* We have nothing in the output buffer, and
850 we have an error that may not have been
851 reported yet; that means we can't generate
852 any more data into the output buffer, so
853 return an error indication. */
855 } else if (file->eof && file->avail_in == 0) {
856 /* We have nothing in the output buffer, and
857 we're at the end of the input; just return
858 with what we've gotten so far. */
861 /* We have nothing in the output buffer, and
862 we can generate more data; get more output,
863 looking for header if required, and
864 keep looping to process the new stuff
865 in the output buffer. */
866 if (fill_out_buffer(file) == -1)
868 continue; /* no progress yet -- go back to memcpy() above */
870 /* update progress */
872 buf = (char *)buf + n;
881 file_getc(FILE_T file)
883 unsigned char buf[1];
886 /* check that we're reading and that there's no error */
890 /* try output buffer (no need to check for skip request) */
894 return *(file->next)++;
897 ret = file_read(buf, 1, file);
898 return ret < 1 ? -1 : buf[0];
902 file_gets(char *buf, int len, FILE_T file)
908 /* check parameters */
909 if (buf == NULL || len < 1)
912 /* check that there's no error */
916 /* process a skip request */
919 if (gz_skip(file, file->skip) == -1)
923 /* copy output bytes up to new line or len - 1, whichever comes first --
924 append a terminating zero to the string (we don't check for a zero in
925 the contents, let the user worry about that) */
927 left = (unsigned)len - 1;
929 /* assure that something is in the output buffer */
930 if (file->have == 0) {
931 /* We have nothing in the output buffer. */
933 /* We have an error that may not have
934 been reported yet; that means we
935 can't generate any more data into
936 the output buffer, so return an
940 if (fill_out_buffer(file) == -1)
941 return NULL; /* error */
942 if (file->have == 0) { /* end of file */
943 if (buf == str) /* got bupkus */
945 break; /* got something -- return it */
949 /* look for end-of-line in current output buffer */
950 n = file->have > left ? left : file->have;
951 eol = memchr(file->next, '\n', n);
953 n = (unsigned)(eol - file->next) + 1;
955 /* copy through end-of-line, or remainder if not found */
956 memcpy(buf, file->next, n);
962 } while (left && eol == NULL);
964 /* found end-of-line or out of space -- terminate string and return it */
970 file_eof(FILE_T file)
972 /* return end-of-file state */
973 return (file->eof && file->avail_in == 0 && file->have == 0);
977 * Routine to return a Wiretap error code (0 for no error, an errno
978 * for a file error, or a WTAP_ERR_ code for other errors) for an
982 file_error(FILE_T fh)
988 file_clearerr(FILE_T stream)
990 /* clear error and end-of-file */
996 file_close(FILE_T file)
1000 /* free memory and close file */
1003 inflateEnd(&(file->strm));
1008 g_free(file->fast_seek_cur);
1015 /* internal gzip file state data structure for writing */
1016 struct wtap_writer {
1017 int fd; /* file descriptor */
1018 gint64 pos; /* current position in uncompressed data */
1019 unsigned size; /* buffer size, zero if not allocated yet */
1020 unsigned want; /* requested buffer size, default is GZBUFSIZE */
1021 unsigned char *in; /* input buffer */
1022 unsigned char *out; /* output buffer (double-sized when reading) */
1023 unsigned char *next; /* next output data to deliver or write */
1024 int level; /* compression level */
1025 int strategy; /* compression strategy */
1026 int err; /* error code */
1027 /* zlib deflate stream */
1028 z_stream strm; /* stream structure in-place (not a pointer) */
1032 gzwfile_open(const char *path)
1038 fd = ws_open(path, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666);
1041 state = gzwfile_fdopen(fd);
1042 if (state == NULL) {
1051 gzwfile_fdopen(int fd)
1055 /* allocate wtap_writer structure to return */
1056 state = g_try_malloc(sizeof *state);
1060 state->size = 0; /* no buffers allocated yet */
1061 state->want = GZBUFSIZE; /* requested buffer size */
1063 state->level = Z_DEFAULT_COMPRESSION;
1064 state->strategy = Z_DEFAULT_STRATEGY;
1066 /* initialize stream */
1067 state->err = Z_OK; /* clear error */
1068 state->pos = 0; /* no uncompressed data yet */
1069 state->strm.avail_in = 0; /* no input data yet */
1075 /* Initialize state for writing a gzip file. Mark initialization by setting
1076 state->size to non-zero. Return -1, and set state->err, on failure;
1077 return 0 on success. */
1079 gz_init(GZWFILE_T state)
1082 z_streamp strm = &(state->strm);
1084 /* allocate input and output buffers */
1085 state->in = g_try_malloc(state->want);
1086 state->out = g_try_malloc(state->want);
1087 if (state->in == NULL || state->out == NULL) {
1090 state->err = WTAP_ERR_ZLIB + Z_MEM_ERROR; /* ENOMEM? */
1094 /* allocate deflate memory, set up for gzip compression */
1095 strm->zalloc = Z_NULL;
1096 strm->zfree = Z_NULL;
1097 strm->opaque = Z_NULL;
1098 ret = deflateInit2(strm, state->level, Z_DEFLATED,
1099 15 + 16, 8, state->strategy);
1103 state->err = WTAP_ERR_ZLIB + Z_MEM_ERROR; /* ENOMEM? */
1107 /* mark state as initialized */
1108 state->size = state->want;
1110 /* initialize write buffer */
1111 strm->avail_out = state->size;
1112 strm->next_out = state->out;
1113 state->next = strm->next_out;
1117 /* Compress whatever is at avail_in and next_in and write to the output file.
1118 Return -1, and set state->err, if there is an error writing to the output
1119 file; return 0 on success.
1120 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
1121 then the deflate() state is reset to start a new gzip stream. */
1123 gz_comp(GZWFILE_T state, int flush)
1127 z_streamp strm = &(state->strm);
1129 /* allocate memory if this is the first time through */
1130 if (state->size == 0 && gz_init(state) == -1)
1133 /* run deflate() on provided input until it produces no more output */
1136 /* write out current buffer contents if full, or if flushing, but if
1137 doing Z_FINISH then don't write until we get to Z_STREAM_END */
1138 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
1139 (flush != Z_FINISH || ret == Z_STREAM_END))) {
1140 have = (unsigned)(strm->next_out - state->next);
1142 got = write(state->fd, state->next, have);
1147 if ((unsigned)got != have) {
1148 state->err = WTAP_ERR_SHORT_WRITE;
1152 if (strm->avail_out == 0) {
1153 strm->avail_out = state->size;
1154 strm->next_out = state->out;
1156 state->next = strm->next_out;
1160 have = strm->avail_out;
1161 ret = deflate(strm, flush);
1162 if (ret == Z_STREAM_ERROR) {
1163 state->err = WTAP_ERR_ZLIB + Z_STREAM_ERROR;
1166 have -= strm->avail_out;
1169 /* if that completed a deflate stream, allow another to start */
1170 if (flush == Z_FINISH)
1173 /* all done, no errors */
1177 /* Write out len bytes from buf. Return 0, and set state->err, on
1178 failure or on an attempt to write 0 bytes (in which case state->err
1179 is Z_OK); return the number of bytes written on success. */
1181 gzwfile_write(GZWFILE_T state, const void *buf, unsigned len)
1187 strm = &(state->strm);
1189 /* check that there's no error */
1190 if (state->err != Z_OK)
1193 /* if len is zero, avoid unnecessary operations */
1197 /* allocate memory if this is the first time through */
1198 if (state->size == 0 && gz_init(state) == -1)
1201 /* for small len, copy to input buffer, otherwise compress directly */
1202 if (len < state->size) {
1203 /* copy to input buffer, compress when full */
1205 if (strm->avail_in == 0)
1206 strm->next_in = state->in;
1207 n = state->size - strm->avail_in;
1210 memcpy(strm->next_in + strm->avail_in, buf, n);
1211 strm->avail_in += n;
1213 buf = (char *)buf + n;
1215 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
1220 /* consume whatever's left in the input buffer */
1221 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
1224 /* directly compress user buffer to file */
1225 strm->avail_in = len;
1226 strm->next_in = (voidp)buf;
1228 if (gz_comp(state, Z_NO_FLUSH) == -1)
1232 /* input was all buffered or compressed (put will fit in int) */
1236 /* Flush out what we've written so far. Returns -1, and sets state->err,
1237 on failure; returns 0 on success. */
1239 gzwfile_flush(GZWFILE_T state)
1241 /* check that there's no error */
1242 if (state->err != Z_OK)
1245 /* compress remaining data with Z_SYNC_FLUSH */
1246 gz_comp(state, Z_SYNC_FLUSH);
1247 if (state->err != Z_OK)
1252 /* Flush out all data written, and close the file. Returns a Wiretap
1253 error on failure; returns 0 on success. */
1255 gzwfile_close(GZWFILE_T state)
1259 /* flush, free memory, and close file */
1260 if (gz_comp(state, Z_FINISH) == -1 && ret == 0)
1262 (void)deflateEnd(&(state->strm));
1266 if (close(state->fd) == -1 && ret == 0)
1273 gzwfile_geterr(GZWFILE_T state)