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 */
94 char *err_info; /* additional error information string for some errors */
96 unsigned int avail_in; /* number of bytes available at next_in */
97 unsigned char *next_in; /* next input byte */
99 /* zlib inflate stream */
100 z_stream strm; /* stream structure in-place (not a pointer) */
103 GPtrArray *fast_seek;
107 /* values for gz_state compression */
108 #define UNKNOWN 0 /* look for a gzip header */
109 #define UNCOMPRESSED 1 /* copy input directly */
111 #define ZLIB 2 /* decompress a zlib stream */
112 #define GZIP_AFTER_HEADER 3
115 static int /* gz_load */
116 raw_read(FILE_T state, unsigned char *buf, unsigned int count, unsigned *have)
122 ret = read(state->fd, buf + *have, count - *have);
126 state->raw_pos += ret;
127 } while (*have < count);
130 state->err_info = NULL;
138 static int /* gz_avail */
139 fill_in_buffer(FILE_T state)
143 if (state->eof == 0) {
144 if (raw_read(state, state->in, state->size, (unsigned *)&(state->avail_in)) == -1)
146 state->next_in = state->in;
151 #define ZLIB_WINSIZE 32768
153 struct fast_seek_point {
154 gint64 out; /* corresponding offset in uncompressed data */
155 gint64 in; /* offset in input file of first full byte */
160 int bits; /* number of bits (1-7) from byte at in - 1, or 0 */
161 unsigned char window[ZLIB_WINSIZE]; /* preceding 32K of uncompressed data */
163 /* be gentle with Z_STREAM_END, 8 bytes more... Another solution would be to comment checks out */
170 struct zlib_cur_seek_point {
171 unsigned char window[ZLIB_WINSIZE]; /* preceding 32K of uncompressed data */
176 #define SPAN G_GINT64_CONSTANT(1048576)
177 static struct fast_seek_point *
178 fast_seek_find(FILE_T file, gint64 pos)
180 struct fast_seek_point *smallest = NULL;
181 struct fast_seek_point *item;
184 if (!file->fast_seek)
187 for (low = 0, max = file->fast_seek->len; low < max; ) {
189 item = file->fast_seek->pdata[i];
193 else if (pos > item->out) {
204 fast_seek_header(FILE_T file, gint64 in_pos, gint64 out_pos, int compression)
206 struct fast_seek_point *item = NULL;
208 if (file->fast_seek->len != 0)
209 item = file->fast_seek->pdata[file->fast_seek->len - 1];
211 if (!item || item->out < out_pos) {
212 struct fast_seek_point *val = g_malloc(sizeof(struct fast_seek_point));
215 val->compression = compression;
217 g_ptr_array_add(file->fast_seek, val);
222 fast_seek_reset(FILE_T state _U_)
225 if (state->compression == ZLIB && state->fast_seek_cur) {
226 struct zlib_cur_seek_point *cur = (struct zlib_cur_seek_point *) state->fast_seek_cur;
235 /* Get next byte from input, or -1 if end or error.
239 * 1) errors from raw_read(), and thus from fill_in_buffer(), are
240 * "sticky", and fill_in_buffer() won't do any reading if there's
243 * 2) GZ_GETC() returns -1 on an EOF;
245 * so it's safe to make multiple GZ_GETC() calls and only check the
246 * last one for an error. */
247 #define GZ_GETC() ((state->avail_in == 0 && fill_in_buffer(state) == -1) ? -1 : \
248 (state->avail_in == 0 ? -1 : \
249 (state->avail_in--, *(state->next_in)++)))
251 /* Get a one-byte integer and return 0 on success and the value in *ret.
252 Otherwise -1 is returned, state->err is set, and *ret is not modified. */
254 gz_next1(FILE_T state, guint8 *ret)
260 if (state->err == 0) {
262 state->err = WTAP_ERR_SHORT_READ;
263 state->err_info = NULL;
271 /* Get a two-byte little-endian integer and return 0 on success and the value
272 in *ret. Otherwise -1 is returned, state->err is set, and *ret is not
275 gz_next2(FILE_T state, guint16 *ret)
283 if (state->err == 0) {
285 state->err = WTAP_ERR_SHORT_READ;
286 state->err_info = NULL;
290 val += (guint16)ch << 8;
295 /* Get a four-byte little-endian integer and return 0 on success and the value
296 in *ret. Otherwise -1 is returned, state->err is set, and *ret is not
299 gz_next4(FILE_T state, guint32 *ret)
305 val += (unsigned)GZ_GETC() << 8;
306 val += (guint32)GZ_GETC() << 16;
309 if (state->err == 0) {
311 state->err = WTAP_ERR_SHORT_READ;
312 state->err_info = NULL;
316 val += (guint32)ch << 24;
321 /* Skip the specified number of bytes and return 0 on success. Otherwise -1
324 gz_skipn(FILE_T state, size_t n)
327 if (GZ_GETC() == -1) {
328 if (state->err == 0) {
330 state->err = WTAP_ERR_SHORT_READ;
331 state->err_info = NULL;
340 /* Skip a null-terminated string and return 0 on success. Otherwise -1
343 gz_skipzstr(FILE_T state)
347 /* It's null-terminated, so scan until we read a byte with
348 the value 0 or get an error. */
349 while ((ch = GZ_GETC()) > 0)
352 if (state->err == 0) {
354 state->err = WTAP_ERR_SHORT_READ;
355 state->err_info = NULL;
363 zlib_fast_seek_add(FILE_T file, struct zlib_cur_seek_point *point, int bits, gint64 in_pos, gint64 out_pos)
365 /* it's for sure after gzip header, so file->fast_seek->len != 0 */
366 struct fast_seek_point *item = file->fast_seek->pdata[file->fast_seek->len - 1];;
368 /* 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)
369 * Inserting value in middle of sorted array is expensive, so we want to add only in the end.
370 * It's not big deal, cause first-read don't usually invoke seeking
372 if (item->out + SPAN < out_pos) {
373 struct fast_seek_point *val = g_malloc(sizeof(struct fast_seek_point));
376 val->compression = ZLIB;
378 val->data.zlib.bits = bits;
379 if (point->pos != 0) {
380 unsigned int left = ZLIB_WINSIZE - point->pos;
382 memcpy(val->data.zlib.window, point->window + point->pos, left);
383 memcpy(val->data.zlib.window + left, point->window, point->pos);
385 memcpy(val->data.zlib.window, point->window, ZLIB_WINSIZE);
387 val->data.zlib.adler = file->strm.adler;
388 val->data.zlib.total_out = file->strm.total_out;
389 g_ptr_array_add(file->fast_seek, val);
393 static void /* gz_decomp */
394 zlib_read(FILE_T state, unsigned char *buf, unsigned int count)
396 int ret = 0; /* XXX */
398 z_streamp strm = &(state->strm);
400 unsigned char *buf2 = buf;
401 unsigned int count2 = count;
403 strm->avail_out = count;
404 strm->next_out = buf;
406 /* fill output buffer up to end of deflate stream or error */
408 /* get more input for inflate() */
409 if (state->avail_in == 0 && fill_in_buffer(state) == -1)
411 if (state->avail_in == 0) {
413 state->err = WTAP_ERR_SHORT_READ;
414 state->err_info = NULL;
418 strm->avail_in = state->avail_in;
419 strm->next_in = state->next_in;
420 /* decompress and handle errors */
421 /* ret = inflate(strm, Z_NO_FLUSH); */
422 ret = inflate(strm, Z_BLOCK);
423 state->avail_in = strm->avail_in;
424 state->next_in = strm->next_in;
425 if (ret == Z_STREAM_ERROR) {
426 state->err = WTAP_ERR_DECOMPRESS;
427 state->err_info = strm->msg;
430 if (ret == Z_NEED_DICT) {
431 state->err = WTAP_ERR_DECOMPRESS;
432 state->err_info = "preset dictionary needed";
435 if (ret == Z_MEM_ERROR) {
436 /* This means "not enough memory". */
438 state->err_info = NULL;
441 if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
442 state->err = WTAP_ERR_DECOMPRESS;
443 state->err_info = strm->msg;
450 strm->adler = crc32(strm->adler, buf2, count2 - strm->avail_out);
451 if (state->fast_seek_cur) {
452 struct zlib_cur_seek_point *cur = (struct zlib_cur_seek_point *) state->fast_seek_cur;
453 unsigned int ready = count2 - strm->avail_out;
455 if (ready < ZLIB_WINSIZE) {
456 unsigned left = ZLIB_WINSIZE - cur->pos;
459 memcpy(cur->window + cur->pos, buf2, left);
461 memcpy(cur->window, buf2 + left, ready - left);
463 cur->pos = ready - left;
466 memcpy(cur->window + cur->pos, buf2, ready);
471 if (cur->have >= ZLIB_WINSIZE)
472 cur->have = ZLIB_WINSIZE;
475 memcpy(cur->window, buf2 + (ready - ZLIB_WINSIZE), ZLIB_WINSIZE);
477 cur->have = ZLIB_WINSIZE;
480 if (cur->have >= ZLIB_WINSIZE && ret != Z_STREAM_END && (strm->data_type & 128) && !(strm->data_type & 64))
481 zlib_fast_seek_add(state, cur, (strm->data_type & 7), state->raw_pos - strm->avail_in, state->pos + (count - strm->avail_out));
483 buf2 = (buf2 + count2 - strm->avail_out);
484 count2 = strm->avail_out;
486 } while (strm->avail_out && ret != Z_STREAM_END);
488 /* update available output and crc check value */
490 state->have = count - strm->avail_out;
492 /* Check gzip trailer if at end of deflate stream.
493 We don't fail immediately here, we just set an error
494 indication, so that we try to process what data we
495 got before the error. The next attempt to read
496 something past that data will get the error. */
497 if (ret == Z_STREAM_END) {
498 if (gz_next4(state, &crc) != -1 &&
499 gz_next4(state, &len) != -1) {
500 if (crc != strm->adler) {
501 state->err = WTAP_ERR_DECOMPRESS;
502 state->err_info = "bad CRC";
503 } else if (len != (strm->total_out & 0xffffffffL)) {
504 state->err = WTAP_ERR_DECOMPRESS;
505 state->err_info = "length field wrong";
508 state->compression = UNKNOWN; /* ready for next stream, once have is 0 */
509 g_free(state->fast_seek_cur);
510 state->fast_seek_cur = NULL;
516 gz_head(FILE_T state)
518 /* get some data in the input buffer */
519 if (state->avail_in == 0) {
520 if (fill_in_buffer(state) == -1)
522 if (state->avail_in == 0)
526 /* look for the gzip magic header bytes 31 and 139 */
528 if (state->next_in[0] == 31) {
531 if (state->avail_in == 0 && fill_in_buffer(state) == -1)
533 if (state->avail_in && state->next_in[0] == 139) {
539 /* we have a gzip header, woo hoo! */
543 /* read rest of header */
545 /* compression method (CM) */
546 if (gz_next1(state, &cm) == -1)
549 state->err = WTAP_ERR_DECOMPRESS;
550 state->err_info = "unknown compression method";
555 if (gz_next1(state, &flags) == -1)
557 if (flags & 0xe0) { /* reserved flag bits */
558 state->err = WTAP_ERR_DECOMPRESS;
559 state->err_info = "reserved flag bits set";
563 /* modification time (MTIME) */
564 if (gz_skipn(state, 4) == -1)
567 /* extra flags (XFL) */
568 if (gz_skipn(state, 1) == -1)
571 /* operating system (OS) */
572 if (gz_skipn(state, 1) == -1)
576 /* extra field - get XLEN */
577 if (gz_next2(state, &len) == -1)
580 /* skip the extra field */
581 if (gz_skipn(state, len) == -1)
586 if (gz_skipzstr(state) == -1)
591 if (gz_skipzstr(state) == -1)
596 if (gz_next2(state, &hcrc) == -1)
598 /* XXX - check the CRC? */
601 /* set up for decompression */
602 inflateReset(&(state->strm));
603 state->strm.adler = crc32(0L, Z_NULL, 0);
604 state->compression = ZLIB;
606 if (state->fast_seek) {
607 struct zlib_cur_seek_point *cur = g_malloc(sizeof(struct zlib_cur_seek_point));
609 cur->pos = cur->have = 0;
610 g_free(state->fast_seek_cur);
611 state->fast_seek_cur = cur;
612 fast_seek_header(state, state->raw_pos - state->avail_in, state->pos, GZIP_AFTER_HEADER);
617 /* not a gzip file -- save first byte (31) and fall to raw i/o */
624 /* { 0xFD, '7', 'z', 'X', 'Z', 0x00 } */
625 /* FD 37 7A 58 5A 00 */
627 if (state->fast_seek)
628 fast_seek_header(state, state->raw_pos - state->avail_in - state->have, state->pos, UNCOMPRESSED);
630 /* doing raw i/o, save start of raw data for seeking, copy any leftover
631 input to output -- this assumes that the output buffer is larger than
632 the input buffer, which also assures space for gzungetc() */
633 state->raw = state->pos;
634 state->next = state->out;
635 if (state->avail_in) {
636 memcpy(state->next + state->have, state->next_in, state->avail_in);
637 state->have += state->avail_in;
640 state->compression = UNCOMPRESSED;
644 static int /* gz_make */
645 fill_out_buffer(FILE_T state)
647 if (state->compression == UNKNOWN) { /* look for gzip header */
648 if (gz_head(state) == -1)
650 if (state->have) /* got some data from gz_head() */
653 if (state->compression == UNCOMPRESSED) { /* straight copy */
654 if (raw_read(state, state->out, state->size /* << 1 */, &(state->have)) == -1)
656 state->next = state->out;
659 else if (state->compression == ZLIB) { /* decompress */
660 zlib_read(state, state->out, state->size << 1);
667 gz_skip(FILE_T state, gint64 len)
671 /* skip over len bytes or reach end-of-file, whichever comes first */
674 /* We have stuff in the output buffer; skip over
676 n = (gint64)state->have > len ? (unsigned)len : state->have;
681 } else if (state->err) {
682 /* We have nothing in the output buffer, and
683 we have an error that may not have been
684 reported yet; that means we can't generate
685 any more data into the output buffer, so
686 return an error indication. */
688 } else if (state->eof && state->avail_in == 0) {
689 /* We have nothing in the output buffer, and
690 we're at the end of the input; just return. */
693 /* We have nothing in the output buffer, and
694 we can generate more data; get more output,
695 looking for header if required. */
696 if (fill_out_buffer(state) == -1)
703 gz_reset(FILE_T state)
705 state->have = 0; /* no output data available */
706 state->eof = 0; /* not at end of file */
707 state->compression = UNKNOWN; /* look for gzip header */
709 state->seek = 0; /* no seek request pending */
710 state->err = 0; /* clear error */
711 state->err_info = NULL;
712 state->pos = 0; /* no uncompressed data yet */
713 state->avail_in = 0; /* no input data yet */
719 #ifdef _STATBUF_ST_BLKSIZE /* XXX, _STATBUF_ST_BLKSIZE portable? */
722 int want = GZBUFSIZE;
728 /* allocate FILE_T structure to return */
729 state = g_try_malloc(sizeof *state);
733 state->fast_seek_cur = NULL;
734 state->fast_seek = NULL;
736 /* open the file with the appropriate mode (or just use fd) */
739 /* save the current position for rewinding (only if reading) */
740 state->start = ws_lseek64(state->fd, 0, SEEK_CUR);
741 if (state->start == -1) state->start = 0;
742 state->raw_pos = state->start;
744 /* initialize stream */
747 #ifdef _STATBUF_ST_BLKSIZE
748 if (fstat(fd, &st) >= 0) {
749 want = st.st_blksize;
750 /* XXX, verify result? */
754 /* allocate buffers */
755 state->in = g_try_malloc(want);
756 state->out = g_try_malloc(want << 1);
758 if (state->in == NULL || state->out == NULL) {
767 /* allocate inflate memory */
768 state->strm.zalloc = Z_NULL;
769 state->strm.zfree = Z_NULL;
770 state->strm.opaque = Z_NULL;
771 state->strm.avail_in = 0;
772 state->strm.next_in = Z_NULL;
773 if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */
786 file_open(const char *path)
791 /* open file and do correct filename conversions.
793 XXX - do we need O_LARGEFILE? On UN*X, if we need to do
794 something special to get large file support, the configure
795 script should have set us up with the appropriate #defines,
796 so we should be getting a large-file-enabled file descriptor
797 here. Pre-Large File Summit UN*Xes, and possibly even some
798 post-LFS UN*Xes, might require O_LARGEFILE here, though.
799 If so, we should probably handle that in ws_open(). */
800 if ((fd = ws_open(path, O_RDONLY|O_BINARY, 0666)) == -1)
803 /* open file handle */
814 file_set_random_access(FILE_T stream, gboolean random _U_, GPtrArray *seek)
816 stream->fast_seek = seek;
820 file_seek(FILE_T file, gint64 offset, int whence, int *err)
822 struct fast_seek_point *here;
825 /* can only seek from start or relative to current position */
826 if (whence != SEEK_SET && whence != SEEK_CUR) {
827 g_assert_not_reached();
834 /* normalize offset to a SEEK_CUR specification */
835 if (whence == SEEK_SET)
838 offset += file->skip;
842 if ((here = fast_seek_find(file, file->pos + offset)) && (offset < 0 || offset > SPAN || here->compression == UNCOMPRESSED)) {
846 if (here->compression == ZLIB) {
847 off = here->in - (here->data.zlib.bits ? 1 : 0);
849 } else if (here->compression == GZIP_AFTER_HEADER) {
855 off2 = (file->pos + offset);
856 off = here->in + (off2 - here->out);
859 if (ws_lseek64(file->fd, off, SEEK_SET) == -1) {
863 fast_seek_reset(file);
870 file->err_info = NULL;
874 if (here->compression == ZLIB) {
875 z_stream *strm = &file->strm;
879 strm->adler = here->data.zlib.adler;
880 strm->total_out = here->data.zlib.total_out;
881 if (here->data.zlib.bits) {
885 if (state->err == 0) {
887 *err = WTAP_ERR_SHORT_READ;
893 (void)inflatePrime(strm, here->data.zlib.bits, ret >> (8 - here->data.zlib.bits));
895 (void)inflateSetDictionary(strm, here->data.zlib.window, ZLIB_WINSIZE);
896 file->compression = ZLIB;
897 } else if (here->compression == GZIP_AFTER_HEADER) {
898 z_stream *strm = &file->strm;
901 strm->adler = crc32(0L, Z_NULL, 0);
902 file->compression = ZLIB;
905 file->compression = here->compression;
907 offset = (file->pos + offset) - off2;
909 /* g_print("OK! %ld\n", offset); */
915 return file->pos + offset;
918 /* if within raw area while reading, just go there */
919 if (file->compression == UNCOMPRESSED && file->pos + offset >= file->raw) {
920 if (ws_lseek64(file->fd, offset - file->have, SEEK_CUR) == -1) {
924 file->raw_pos += (offset - file->have);
929 file->err_info = NULL;
935 /* calculate skip amount, rewinding if needed for back seek when reading */
938 if (offset < 0) { /* before start of file! */
942 /* rewind, then skip to offset */
944 /* back up and start over */
945 if (ws_lseek64(file->fd, file->start, SEEK_SET) == -1) {
949 fast_seek_reset(file);
950 file->raw_pos = file->start;
954 /* skip what's in output buffer (one less gzgetc() check) */
955 n = (gint64)file->have > offset ? (unsigned)offset : file->have;
961 /* request skip (if not zero) */
966 return file->pos + offset;
970 file_tell(FILE_T stream)
972 /* return position */
973 return stream->pos + (stream->seek ? stream->skip : 0);
977 file_read(void *buf, unsigned int len, FILE_T file)
981 /* if len is zero, avoid unnecessary operations */
985 /* process a skip request */
988 if (gz_skip(file, file->skip) == -1)
992 /* get len bytes to buf, or less than len if at the end */
996 /* We have stuff in the output buffer; copy
998 n = file->have > len ? len : file->have;
999 memcpy(buf, file->next, n);
1002 } else if (file->err) {
1003 /* We have nothing in the output buffer, and
1004 we have an error that may not have been
1005 reported yet; that means we can't generate
1006 any more data into the output buffer, so
1007 return an error indication. */
1009 } else if (file->eof && file->avail_in == 0) {
1010 /* We have nothing in the output buffer, and
1011 we're at the end of the input; just return
1012 with what we've gotten so far. */
1015 /* We have nothing in the output buffer, and
1016 we can generate more data; get more output,
1017 looking for header if required, and
1018 keep looping to process the new stuff
1019 in the output buffer. */
1020 if (fill_out_buffer(file) == -1)
1022 continue; /* no progress yet -- go back to memcpy() above */
1024 /* update progress */
1026 buf = (char *)buf + n;
1035 file_getc(FILE_T file)
1037 unsigned char buf[1];
1040 /* check that we're reading and that there's no error */
1044 /* try output buffer (no need to check for skip request) */
1048 return *(file->next)++;
1051 ret = file_read(buf, 1, file);
1052 return ret < 1 ? -1 : buf[0];
1056 file_gets(char *buf, int len, FILE_T file)
1062 /* check parameters */
1063 if (buf == NULL || len < 1)
1066 /* check that there's no error */
1070 /* process a skip request */
1073 if (gz_skip(file, file->skip) == -1)
1077 /* copy output bytes up to new line or len - 1, whichever comes first --
1078 append a terminating zero to the string (we don't check for a zero in
1079 the contents, let the user worry about that) */
1081 left = (unsigned)len - 1;
1083 /* assure that something is in the output buffer */
1084 if (file->have == 0) {
1085 /* We have nothing in the output buffer. */
1087 /* We have an error that may not have
1088 been reported yet; that means we
1089 can't generate any more data into
1090 the output buffer, so return an
1091 error indication. */
1094 if (fill_out_buffer(file) == -1)
1095 return NULL; /* error */
1096 if (file->have == 0) { /* end of file */
1097 if (buf == str) /* got bupkus */
1099 break; /* got something -- return it */
1103 /* look for end-of-line in current output buffer */
1104 n = file->have > left ? left : file->have;
1105 eol = memchr(file->next, '\n', n);
1107 n = (unsigned)(eol - file->next) + 1;
1109 /* copy through end-of-line, or remainder if not found */
1110 memcpy(buf, file->next, n);
1116 } while (left && eol == NULL);
1118 /* found end-of-line or out of space -- terminate string and return it */
1124 file_eof(FILE_T file)
1126 /* return end-of-file state */
1127 return (file->eof && file->avail_in == 0 && file->have == 0);
1131 * Routine to return a Wiretap error code (0 for no error, an errno
1132 * for a file error, or a WTAP_ERR_ code for other errors) for an
1133 * I/O stream. Also returns an error string for some errors.
1136 file_error(FILE_T fh, gchar **err_info)
1139 *err_info = (fh->err_info == NULL) ? NULL : g_strdup(fh->err_info);
1146 file_clearerr(FILE_T stream)
1148 /* clear error and end-of-file */
1150 stream->err_info = NULL;
1155 file_close(FILE_T file)
1159 /* free memory and close file */
1162 inflateEnd(&(file->strm));
1167 g_free(file->fast_seek_cur);
1169 file->err_info = NULL;
1175 /* internal gzip file state data structure for writing */
1176 struct wtap_writer {
1177 int fd; /* file descriptor */
1178 gint64 pos; /* current position in uncompressed data */
1179 unsigned size; /* buffer size, zero if not allocated yet */
1180 unsigned want; /* requested buffer size, default is GZBUFSIZE */
1181 unsigned char *in; /* input buffer */
1182 unsigned char *out; /* output buffer (double-sized when reading) */
1183 unsigned char *next; /* next output data to deliver or write */
1184 int level; /* compression level */
1185 int strategy; /* compression strategy */
1186 int err; /* error code */
1187 /* zlib deflate stream */
1188 z_stream strm; /* stream structure in-place (not a pointer) */
1192 gzwfile_open(const char *path)
1198 fd = ws_open(path, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666);
1201 state = gzwfile_fdopen(fd);
1202 if (state == NULL) {
1211 gzwfile_fdopen(int fd)
1215 /* allocate wtap_writer structure to return */
1216 state = g_try_malloc(sizeof *state);
1220 state->size = 0; /* no buffers allocated yet */
1221 state->want = GZBUFSIZE; /* requested buffer size */
1223 state->level = Z_DEFAULT_COMPRESSION;
1224 state->strategy = Z_DEFAULT_STRATEGY;
1226 /* initialize stream */
1227 state->err = Z_OK; /* clear error */
1228 state->pos = 0; /* no uncompressed data yet */
1229 state->strm.avail_in = 0; /* no input data yet */
1235 /* Initialize state for writing a gzip file. Mark initialization by setting
1236 state->size to non-zero. Return -1, and set state->err, on failure;
1237 return 0 on success. */
1239 gz_init(GZWFILE_T state)
1242 z_streamp strm = &(state->strm);
1244 /* allocate input and output buffers */
1245 state->in = g_try_malloc(state->want);
1246 state->out = g_try_malloc(state->want);
1247 if (state->in == NULL || state->out == NULL) {
1250 state->err = ENOMEM;
1254 /* allocate deflate memory, set up for gzip compression */
1255 strm->zalloc = Z_NULL;
1256 strm->zfree = Z_NULL;
1257 strm->opaque = Z_NULL;
1258 ret = deflateInit2(strm, state->level, Z_DEFLATED,
1259 15 + 16, 8, state->strategy);
1263 if (ret == Z_MEM_ERROR) {
1264 /* This means "not enough memory". */
1265 state->err = ENOMEM;
1267 /* This "shouldn't happen". */
1268 state->err = WTAP_ERR_INTERNAL;
1273 /* mark state as initialized */
1274 state->size = state->want;
1276 /* initialize write buffer */
1277 strm->avail_out = state->size;
1278 strm->next_out = state->out;
1279 state->next = strm->next_out;
1283 /* Compress whatever is at avail_in and next_in and write to the output file.
1284 Return -1, and set state->err, if there is an error writing to the output
1285 file; return 0 on success.
1286 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
1287 then the deflate() state is reset to start a new gzip stream. */
1289 gz_comp(GZWFILE_T state, int flush)
1293 z_streamp strm = &(state->strm);
1295 /* allocate memory if this is the first time through */
1296 if (state->size == 0 && gz_init(state) == -1)
1299 /* run deflate() on provided input until it produces no more output */
1302 /* write out current buffer contents if full, or if flushing, but if
1303 doing Z_FINISH then don't write until we get to Z_STREAM_END */
1304 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
1305 (flush != Z_FINISH || ret == Z_STREAM_END))) {
1306 have = (unsigned)(strm->next_out - state->next);
1308 got = write(state->fd, state->next, have);
1313 if ((unsigned)got != have) {
1314 state->err = WTAP_ERR_SHORT_WRITE;
1318 if (strm->avail_out == 0) {
1319 strm->avail_out = state->size;
1320 strm->next_out = state->out;
1322 state->next = strm->next_out;
1326 have = strm->avail_out;
1327 ret = deflate(strm, flush);
1328 if (ret == Z_STREAM_ERROR) {
1329 /* This "shouldn't happen". */
1330 state->err = WTAP_ERR_INTERNAL;
1333 have -= strm->avail_out;
1336 /* if that completed a deflate stream, allow another to start */
1337 if (flush == Z_FINISH)
1340 /* all done, no errors */
1344 /* Write out len bytes from buf. Return 0, and set state->err, on
1345 failure or on an attempt to write 0 bytes (in which case state->err
1346 is Z_OK); return the number of bytes written on success. */
1348 gzwfile_write(GZWFILE_T state, const void *buf, unsigned len)
1354 strm = &(state->strm);
1356 /* check that there's no error */
1357 if (state->err != Z_OK)
1360 /* if len is zero, avoid unnecessary operations */
1364 /* allocate memory if this is the first time through */
1365 if (state->size == 0 && gz_init(state) == -1)
1368 /* for small len, copy to input buffer, otherwise compress directly */
1369 if (len < state->size) {
1370 /* copy to input buffer, compress when full */
1372 if (strm->avail_in == 0)
1373 strm->next_in = state->in;
1374 n = state->size - strm->avail_in;
1377 memcpy(strm->next_in + strm->avail_in, buf, n);
1378 strm->avail_in += n;
1380 buf = (char *)buf + n;
1382 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
1387 /* consume whatever's left in the input buffer */
1388 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
1391 /* directly compress user buffer to file */
1392 strm->avail_in = len;
1393 strm->next_in = (voidp)buf;
1395 if (gz_comp(state, Z_NO_FLUSH) == -1)
1399 /* input was all buffered or compressed (put will fit in int) */
1403 /* Flush out what we've written so far. Returns -1, and sets state->err,
1404 on failure; returns 0 on success. */
1406 gzwfile_flush(GZWFILE_T state)
1408 /* check that there's no error */
1409 if (state->err != Z_OK)
1412 /* compress remaining data with Z_SYNC_FLUSH */
1413 gz_comp(state, Z_SYNC_FLUSH);
1414 if (state->err != Z_OK)
1419 /* Flush out all data written, and close the file. Returns a Wiretap
1420 error on failure; returns 0 on success. */
1422 gzwfile_close(GZWFILE_T state)
1426 /* flush, free memory, and close file */
1427 if (gz_comp(state, Z_FINISH) == -1 && ret == 0)
1429 (void)deflateEnd(&(state->strm));
1433 if (close(state->fd) == -1 && ret == 0)
1440 gzwfile_geterr(GZWFILE_T state)