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>
64 #endif /* HAVE_LIBZ */
67 * See RFC 1952 for a description of the gzip file format.
69 * Some other compressed file formats we might want to support:
71 * XZ format: http://tukaani.org/xz/
73 * Bzip2 format: http://bzip.org/
76 /* #define GZBUFSIZE 8192 */
77 #define GZBUFSIZE 4096
80 int fd; /* file descriptor */
81 gint64 raw_pos; /* current position in file (just to not call lseek()) */
82 gint64 pos; /* current position in uncompressed data */
83 unsigned size; /* buffer size */
84 unsigned char *in; /* input buffer */
85 unsigned char *out; /* output buffer (double-sized when reading) */
86 unsigned char *next; /* next output data to deliver or write */
88 unsigned have; /* amount of output data unused at next */
89 int eof; /* true if end of input file reached */
90 gint64 start; /* where the gzip data started, for rewinding */
91 gint64 raw; /* where the raw data started, for seeking */
92 int compression; /* 0: ?, 1: uncompressed, 2: zlib */
94 gint64 skip; /* amount to skip (already rewound if backwards) */
95 int seek; /* true if seek request pending */
96 /* error information */
97 int err; /* error code */
98 const char *err_info; /* additional error information string for some errors */
100 unsigned int avail_in; /* number of bytes available at next_in */
101 unsigned char *next_in; /* next input byte */
103 /* zlib inflate stream */
104 z_stream strm; /* stream structure in-place (not a pointer) */
105 int dont_check_crc; /* 1 if we aren't supposed to check the CRC */
108 GPtrArray *fast_seek;
112 /* values for gz_state compression */
113 #define UNKNOWN 0 /* look for a gzip header */
114 #define UNCOMPRESSED 1 /* copy input directly */
116 #define ZLIB 2 /* decompress a zlib stream */
117 #define GZIP_AFTER_HEADER 3
120 static int /* gz_load */
121 raw_read(FILE_T state, unsigned char *buf, unsigned int count, unsigned *have)
127 ret = read(state->fd, buf + *have, count - *have);
131 state->raw_pos += ret;
132 } while (*have < count);
135 state->err_info = NULL;
143 static int /* gz_avail */
144 fill_in_buffer(FILE_T state)
148 if (state->eof == 0) {
149 if (raw_read(state, state->in, state->size, (unsigned *)&(state->avail_in)) == -1)
151 state->next_in = state->in;
156 #define ZLIB_WINSIZE 32768
158 struct fast_seek_point {
159 gint64 out; /* corresponding offset in uncompressed data */
160 gint64 in; /* offset in input file of first full byte */
165 #ifdef HAVE_INFLATEPRIME
166 int bits; /* number of bits (1-7) from byte at in - 1, or 0 */
168 unsigned char window[ZLIB_WINSIZE]; /* preceding 32K of uncompressed data */
170 /* be gentle with Z_STREAM_END, 8 bytes more... Another solution would be to comment checks out */
177 struct zlib_cur_seek_point {
178 unsigned char window[ZLIB_WINSIZE]; /* preceding 32K of uncompressed data */
183 #define SPAN G_GINT64_CONSTANT(1048576)
184 static struct fast_seek_point *
185 fast_seek_find(FILE_T file, gint64 pos)
187 struct fast_seek_point *smallest = NULL;
188 struct fast_seek_point *item;
191 if (!file->fast_seek)
194 for (low = 0, max = file->fast_seek->len; low < max; ) {
196 item = file->fast_seek->pdata[i];
200 else if (pos > item->out) {
211 fast_seek_header(FILE_T file, gint64 in_pos, gint64 out_pos, int compression)
213 struct fast_seek_point *item = NULL;
215 if (file->fast_seek->len != 0)
216 item = file->fast_seek->pdata[file->fast_seek->len - 1];
218 if (!item || item->out < out_pos) {
219 struct fast_seek_point *val = g_malloc(sizeof(struct fast_seek_point));
222 val->compression = compression;
224 g_ptr_array_add(file->fast_seek, val);
229 fast_seek_reset(FILE_T state _U_)
232 if (state->compression == ZLIB && state->fast_seek_cur) {
233 struct zlib_cur_seek_point *cur = (struct zlib_cur_seek_point *) state->fast_seek_cur;
242 /* Get next byte from input, or -1 if end or error.
246 * 1) errors from raw_read(), and thus from fill_in_buffer(), are
247 * "sticky", and fill_in_buffer() won't do any reading if there's
250 * 2) GZ_GETC() returns -1 on an EOF;
252 * so it's safe to make multiple GZ_GETC() calls and only check the
253 * last one for an error. */
254 #define GZ_GETC() ((state->avail_in == 0 && fill_in_buffer(state) == -1) ? -1 : \
255 (state->avail_in == 0 ? -1 : \
256 (state->avail_in--, *(state->next_in)++)))
258 /* Get a one-byte integer and return 0 on success and the value in *ret.
259 Otherwise -1 is returned, state->err is set, and *ret is not modified. */
261 gz_next1(FILE_T state, guint8 *ret)
267 if (state->err == 0) {
269 state->err = WTAP_ERR_SHORT_READ;
270 state->err_info = NULL;
278 /* Get a two-byte little-endian integer and return 0 on success and the value
279 in *ret. Otherwise -1 is returned, state->err is set, and *ret is not
282 gz_next2(FILE_T state, guint16 *ret)
290 if (state->err == 0) {
292 state->err = WTAP_ERR_SHORT_READ;
293 state->err_info = NULL;
297 val += (guint16)ch << 8;
302 /* Get a four-byte little-endian integer and return 0 on success and the value
303 in *ret. Otherwise -1 is returned, state->err is set, and *ret is not
306 gz_next4(FILE_T state, guint32 *ret)
312 val += (unsigned)GZ_GETC() << 8;
313 val += (guint32)GZ_GETC() << 16;
316 if (state->err == 0) {
318 state->err = WTAP_ERR_SHORT_READ;
319 state->err_info = NULL;
323 val += (guint32)ch << 24;
328 /* Skip the specified number of bytes and return 0 on success. Otherwise -1
331 gz_skipn(FILE_T state, size_t n)
334 if (GZ_GETC() == -1) {
335 if (state->err == 0) {
337 state->err = WTAP_ERR_SHORT_READ;
338 state->err_info = NULL;
347 /* Skip a null-terminated string and return 0 on success. Otherwise -1
350 gz_skipzstr(FILE_T state)
354 /* It's null-terminated, so scan until we read a byte with
355 the value 0 or get an error. */
356 while ((ch = GZ_GETC()) > 0)
359 if (state->err == 0) {
361 state->err = WTAP_ERR_SHORT_READ;
362 state->err_info = NULL;
370 zlib_fast_seek_add(FILE_T file, struct zlib_cur_seek_point *point, int bits, gint64 in_pos, gint64 out_pos)
372 /* it's for sure after gzip header, so file->fast_seek->len != 0 */
373 struct fast_seek_point *item = file->fast_seek->pdata[file->fast_seek->len - 1];;
375 #ifndef HAVE_INFLATEPRIME
380 /* 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)
381 * Inserting value in middle of sorted array is expensive, so we want to add only in the end.
382 * It's not big deal, cause first-read don't usually invoke seeking
384 if (item->out + SPAN < out_pos) {
385 struct fast_seek_point *val = g_malloc(sizeof(struct fast_seek_point));
388 val->compression = ZLIB;
389 #ifdef HAVE_INFLATEPRIME
390 val->data.zlib.bits = bits;
392 if (point->pos != 0) {
393 unsigned int left = ZLIB_WINSIZE - point->pos;
395 memcpy(val->data.zlib.window, point->window + point->pos, left);
396 memcpy(val->data.zlib.window + left, point->window, point->pos);
398 memcpy(val->data.zlib.window, point->window, ZLIB_WINSIZE);
400 val->data.zlib.adler = file->strm.adler;
401 val->data.zlib.total_out = file->strm.total_out;
402 g_ptr_array_add(file->fast_seek, val);
406 static void /* gz_decomp */
407 zlib_read(FILE_T state, unsigned char *buf, unsigned int count)
409 int ret = 0; /* XXX */
411 z_streamp strm = &(state->strm);
413 unsigned char *buf2 = buf;
414 unsigned int count2 = count;
416 strm->avail_out = count;
417 strm->next_out = buf;
419 /* fill output buffer up to end of deflate stream or error */
421 /* get more input for inflate() */
422 if (state->avail_in == 0 && fill_in_buffer(state) == -1)
424 if (state->avail_in == 0) {
426 state->err = WTAP_ERR_SHORT_READ;
427 state->err_info = NULL;
431 strm->avail_in = state->avail_in;
432 strm->next_in = state->next_in;
433 /* decompress and handle errors */
434 /* ret = inflate(strm, Z_NO_FLUSH); */
435 ret = inflate(strm, Z_BLOCK);
436 state->avail_in = strm->avail_in;
437 state->next_in = strm->next_in;
438 if (ret == Z_STREAM_ERROR) {
439 state->err = WTAP_ERR_DECOMPRESS;
440 state->err_info = strm->msg;
443 if (ret == Z_NEED_DICT) {
444 state->err = WTAP_ERR_DECOMPRESS;
445 state->err_info = "preset dictionary needed";
448 if (ret == Z_MEM_ERROR) {
449 /* This means "not enough memory". */
451 state->err_info = NULL;
454 if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
455 state->err = WTAP_ERR_DECOMPRESS;
456 state->err_info = strm->msg;
463 strm->adler = crc32(strm->adler, buf2, count2 - strm->avail_out);
464 if (state->fast_seek_cur) {
465 struct zlib_cur_seek_point *cur = (struct zlib_cur_seek_point *) state->fast_seek_cur;
466 unsigned int ready = count2 - strm->avail_out;
468 if (ready < ZLIB_WINSIZE) {
469 unsigned left = ZLIB_WINSIZE - cur->pos;
472 memcpy(cur->window + cur->pos, buf2, left);
474 memcpy(cur->window, buf2 + left, ready - left);
476 cur->pos = ready - left;
479 memcpy(cur->window + cur->pos, buf2, ready);
484 if (cur->have >= ZLIB_WINSIZE)
485 cur->have = ZLIB_WINSIZE;
488 memcpy(cur->window, buf2 + (ready - ZLIB_WINSIZE), ZLIB_WINSIZE);
490 cur->have = ZLIB_WINSIZE;
493 if (cur->have >= ZLIB_WINSIZE && ret != Z_STREAM_END && (strm->data_type & 128) && !(strm->data_type & 64))
494 zlib_fast_seek_add(state, cur, (strm->data_type & 7), state->raw_pos - strm->avail_in, state->pos + (count - strm->avail_out));
496 buf2 = (buf2 + count2 - strm->avail_out);
497 count2 = strm->avail_out;
499 } while (strm->avail_out && ret != Z_STREAM_END);
501 /* update available output and crc check value */
503 state->have = count - strm->avail_out;
505 /* Check gzip trailer if at end of deflate stream.
506 We don't fail immediately here, we just set an error
507 indication, so that we try to process what data we
508 got before the error. The next attempt to read
509 something past that data will get the error. */
510 if (ret == Z_STREAM_END) {
511 if (gz_next4(state, &crc) != -1 &&
512 gz_next4(state, &len) != -1) {
514 * XXX - compressed Windows Sniffer don't
515 * all have the same CRC value; is it just
516 * random crap, or are they running the
517 * CRC on a different set of data than
518 * you're supposed to (e.g., not CRCing
519 * some of the data), or something such
522 if (crc != strm->adler && !state->dont_check_crc) {
523 state->err = WTAP_ERR_DECOMPRESS;
524 state->err_info = "bad CRC";
525 } else if (len != (strm->total_out & 0xffffffffL)) {
526 state->err = WTAP_ERR_DECOMPRESS;
527 state->err_info = "length field wrong";
530 state->compression = UNKNOWN; /* ready for next stream, once have is 0 */
531 g_free(state->fast_seek_cur);
532 state->fast_seek_cur = NULL;
538 gz_head(FILE_T state)
540 /* get some data in the input buffer */
541 if (state->avail_in == 0) {
542 if (fill_in_buffer(state) == -1)
544 if (state->avail_in == 0)
548 /* look for the gzip magic header bytes 31 and 139 */
550 if (state->next_in[0] == 31) {
553 if (state->avail_in == 0 && fill_in_buffer(state) == -1)
555 if (state->avail_in && state->next_in[0] == 139) {
561 /* we have a gzip header, woo hoo! */
565 /* read rest of header */
567 /* compression method (CM) */
568 if (gz_next1(state, &cm) == -1)
571 state->err = WTAP_ERR_DECOMPRESS;
572 state->err_info = "unknown compression method";
577 if (gz_next1(state, &flags) == -1)
579 if (flags & 0xe0) { /* reserved flag bits */
580 state->err = WTAP_ERR_DECOMPRESS;
581 state->err_info = "reserved flag bits set";
585 /* modification time (MTIME) */
586 if (gz_skipn(state, 4) == -1)
589 /* extra flags (XFL) */
590 if (gz_skipn(state, 1) == -1)
593 /* operating system (OS) */
594 if (gz_skipn(state, 1) == -1)
598 /* extra field - get XLEN */
599 if (gz_next2(state, &len) == -1)
602 /* skip the extra field */
603 if (gz_skipn(state, len) == -1)
608 if (gz_skipzstr(state) == -1)
613 if (gz_skipzstr(state) == -1)
618 if (gz_next2(state, &hcrc) == -1)
620 /* XXX - check the CRC? */
623 /* set up for decompression */
624 inflateReset(&(state->strm));
625 state->strm.adler = crc32(0L, Z_NULL, 0);
626 state->compression = ZLIB;
628 if (state->fast_seek) {
629 struct zlib_cur_seek_point *cur = g_malloc(sizeof(struct zlib_cur_seek_point));
631 cur->pos = cur->have = 0;
632 g_free(state->fast_seek_cur);
633 state->fast_seek_cur = cur;
634 fast_seek_header(state, state->raw_pos - state->avail_in, state->pos, GZIP_AFTER_HEADER);
639 /* not a gzip file -- save first byte (31) and fall to raw i/o */
646 /* { 0xFD, '7', 'z', 'X', 'Z', 0x00 } */
647 /* FD 37 7A 58 5A 00 */
649 if (state->fast_seek)
650 fast_seek_header(state, state->raw_pos - state->avail_in - state->have, state->pos, UNCOMPRESSED);
652 /* doing raw i/o, save start of raw data for seeking, copy any leftover
653 input to output -- this assumes that the output buffer is larger than
654 the input buffer, which also assures space for gzungetc() */
655 state->raw = state->pos;
656 state->next = state->out;
657 if (state->avail_in) {
658 memcpy(state->next + state->have, state->next_in, state->avail_in);
659 state->have += state->avail_in;
662 state->compression = UNCOMPRESSED;
666 static int /* gz_make */
667 fill_out_buffer(FILE_T state)
669 if (state->compression == UNKNOWN) { /* look for gzip header */
670 if (gz_head(state) == -1)
672 if (state->have) /* got some data from gz_head() */
675 if (state->compression == UNCOMPRESSED) { /* straight copy */
676 if (raw_read(state, state->out, state->size /* << 1 */, &(state->have)) == -1)
678 state->next = state->out;
681 else if (state->compression == ZLIB) { /* decompress */
682 zlib_read(state, state->out, state->size << 1);
689 gz_skip(FILE_T state, gint64 len)
693 /* skip over len bytes or reach end-of-file, whichever comes first */
696 /* We have stuff in the output buffer; skip over
698 n = (gint64)state->have > len ? (unsigned)len : state->have;
703 } else if (state->err) {
704 /* We have nothing in the output buffer, and
705 we have an error that may not have been
706 reported yet; that means we can't generate
707 any more data into the output buffer, so
708 return an error indication. */
710 } else if (state->eof && state->avail_in == 0) {
711 /* We have nothing in the output buffer, and
712 we're at the end of the input; just return. */
715 /* We have nothing in the output buffer, and
716 we can generate more data; get more output,
717 looking for header if required. */
718 if (fill_out_buffer(state) == -1)
725 gz_reset(FILE_T state)
727 state->have = 0; /* no output data available */
728 state->eof = 0; /* not at end of file */
729 state->compression = UNKNOWN; /* look for gzip header */
731 state->seek = 0; /* no seek request pending */
732 state->err = 0; /* clear error */
733 state->err_info = NULL;
734 state->pos = 0; /* no uncompressed data yet */
735 state->avail_in = 0; /* no input data yet */
741 #ifdef _STATBUF_ST_BLKSIZE /* XXX, _STATBUF_ST_BLKSIZE portable? */
744 int want = GZBUFSIZE;
750 /* allocate FILE_T structure to return */
751 state = g_try_malloc(sizeof *state);
755 state->fast_seek_cur = NULL;
756 state->fast_seek = NULL;
758 /* open the file with the appropriate mode (or just use fd) */
761 /* save the current position for rewinding (only if reading) */
762 state->start = ws_lseek64(state->fd, 0, SEEK_CUR);
763 if (state->start == -1) state->start = 0;
764 state->raw_pos = state->start;
766 /* initialize stream */
769 #ifdef _STATBUF_ST_BLKSIZE
770 if (fstat(fd, &st) >= 0) {
771 want = st.st_blksize;
772 /* XXX, verify result? */
776 /* allocate buffers */
777 state->in = g_try_malloc(want);
778 state->out = g_try_malloc(want << 1);
780 if (state->in == NULL || state->out == NULL) {
789 /* allocate inflate memory */
790 state->strm.zalloc = Z_NULL;
791 state->strm.zfree = Z_NULL;
792 state->strm.opaque = Z_NULL;
793 state->strm.avail_in = 0;
794 state->strm.next_in = Z_NULL;
795 if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */
803 /* for now, assume we should check the crc */
804 state->dont_check_crc = 0;
811 file_open(const char *path)
819 /* open file and do correct filename conversions.
821 XXX - do we need O_LARGEFILE? On UN*X, if we need to do
822 something special to get large file support, the configure
823 script should have set us up with the appropriate #defines,
824 so we should be getting a large-file-enabled file descriptor
825 here. Pre-Large File Summit UN*Xes, and possibly even some
826 post-LFS UN*Xes, might require O_LARGEFILE here, though.
827 If so, we should probably handle that in ws_open(). */
828 if ((fd = ws_open(path, O_RDONLY|O_BINARY, 0000)) == -1)
831 /* open file handle */
840 * If this file's name ends in ".caz", it's probably a compressed
841 * Windows Sniffer file. The compression is gzip, but they don't
842 * bother filling in the CRC; we set a flag to ignore CRC errors.
844 suffixp = strrchr(path, '.');
845 if (suffixp != NULL) {
846 if (g_ascii_strcasecmp(suffixp, ".caz") == 0)
847 ft->dont_check_crc = 1;
855 file_set_random_access(FILE_T stream, gboolean random _U_, GPtrArray *seek)
857 stream->fast_seek = seek;
861 file_seek(FILE_T file, gint64 offset, int whence, int *err)
863 struct fast_seek_point *here;
866 /* can only seek from start or relative to current position */
867 if (whence != SEEK_SET && whence != SEEK_CUR) {
868 g_assert_not_reached();
875 /* normalize offset to a SEEK_CUR specification */
876 if (whence == SEEK_SET)
879 offset += file->skip;
883 if ((here = fast_seek_find(file, file->pos + offset)) && (offset < 0 || offset > SPAN || here->compression == UNCOMPRESSED)) {
887 if (here->compression == ZLIB) {
888 #ifdef HAVE_INFLATEPRIME
889 off = here->in - (here->data.zlib.bits ? 1 : 0);
894 } else if (here->compression == GZIP_AFTER_HEADER) {
900 off2 = (file->pos + offset);
901 off = here->in + (off2 - here->out);
904 if (ws_lseek64(file->fd, off, SEEK_SET) == -1) {
908 fast_seek_reset(file);
915 file->err_info = NULL;
919 if (here->compression == ZLIB) {
920 z_stream *strm = &file->strm;
923 strm->adler = here->data.zlib.adler;
924 strm->total_out = here->data.zlib.total_out;
925 #ifdef HAVE_INFLATEPRIME
926 if (here->data.zlib.bits) {
931 if (state->err == 0) {
933 *err = WTAP_ERR_SHORT_READ;
938 (void)inflatePrime(strm, here->data.zlib.bits, ret >> (8 - here->data.zlib.bits));
941 (void)inflateSetDictionary(strm, here->data.zlib.window, ZLIB_WINSIZE);
942 file->compression = ZLIB;
943 } else if (here->compression == GZIP_AFTER_HEADER) {
944 z_stream *strm = &file->strm;
947 strm->adler = crc32(0L, Z_NULL, 0);
948 file->compression = ZLIB;
951 file->compression = here->compression;
953 offset = (file->pos + offset) - off2;
955 /* g_print("OK! %ld\n", offset); */
961 return file->pos + offset;
964 /* if within raw area while reading, just go there */
965 if (file->compression == UNCOMPRESSED && file->pos + offset >= file->raw) {
966 if (ws_lseek64(file->fd, offset - file->have, SEEK_CUR) == -1) {
970 file->raw_pos += (offset - file->have);
975 file->err_info = NULL;
981 /* calculate skip amount, rewinding if needed for back seek when reading */
984 if (offset < 0) { /* before start of file! */
988 /* rewind, then skip to offset */
990 /* back up and start over */
991 if (ws_lseek64(file->fd, file->start, SEEK_SET) == -1) {
995 fast_seek_reset(file);
996 file->raw_pos = file->start;
1000 /* skip what's in output buffer (one less gzgetc() check) */
1001 n = (gint64)file->have > offset ? (unsigned)offset : file->have;
1007 /* request skip (if not zero) */
1010 file->skip = offset;
1012 return file->pos + offset;
1016 file_tell(FILE_T stream)
1018 /* return position */
1019 return stream->pos + (stream->seek ? stream->skip : 0);
1023 file_tell_raw(FILE_T stream)
1025 return stream->raw_pos;
1029 file_fstat(FILE_T stream, ws_statb64 *statb, int *err)
1031 if (ws_fstat64(stream->fd, statb) == -1) {
1040 file_read(void *buf, unsigned int len, FILE_T file)
1044 /* if len is zero, avoid unnecessary operations */
1048 /* process a skip request */
1051 if (gz_skip(file, file->skip) == -1)
1055 /* get len bytes to buf, or less than len if at the end */
1059 /* We have stuff in the output buffer; copy
1061 n = file->have > len ? len : file->have;
1062 memcpy(buf, file->next, n);
1065 } else if (file->err) {
1066 /* We have nothing in the output buffer, and
1067 we have an error that may not have been
1068 reported yet; that means we can't generate
1069 any more data into the output buffer, so
1070 return an error indication. */
1072 } else if (file->eof && file->avail_in == 0) {
1073 /* We have nothing in the output buffer, and
1074 we're at the end of the input; just return
1075 with what we've gotten so far. */
1078 /* We have nothing in the output buffer, and
1079 we can generate more data; get more output,
1080 looking for header if required, and
1081 keep looping to process the new stuff
1082 in the output buffer. */
1083 if (fill_out_buffer(file) == -1)
1085 continue; /* no progress yet -- go back to memcpy() above */
1087 /* update progress */
1089 buf = (char *)buf + n;
1098 file_getc(FILE_T file)
1100 unsigned char buf[1];
1103 /* check that we're reading and that there's no error */
1107 /* try output buffer (no need to check for skip request) */
1111 return *(file->next)++;
1114 ret = file_read(buf, 1, file);
1115 return ret < 1 ? -1 : buf[0];
1119 file_gets(char *buf, int len, FILE_T file)
1125 /* check parameters */
1126 if (buf == NULL || len < 1)
1129 /* check that there's no error */
1133 /* process a skip request */
1136 if (gz_skip(file, file->skip) == -1)
1140 /* copy output bytes up to new line or len - 1, whichever comes first --
1141 append a terminating zero to the string (we don't check for a zero in
1142 the contents, let the user worry about that) */
1144 left = (unsigned)len - 1;
1146 /* assure that something is in the output buffer */
1147 if (file->have == 0) {
1148 /* We have nothing in the output buffer. */
1150 /* We have an error that may not have
1151 been reported yet; that means we
1152 can't generate any more data into
1153 the output buffer, so return an
1154 error indication. */
1157 if (fill_out_buffer(file) == -1)
1158 return NULL; /* error */
1159 if (file->have == 0) { /* end of file */
1160 if (buf == str) /* got bupkus */
1162 break; /* got something -- return it */
1166 /* look for end-of-line in current output buffer */
1167 n = file->have > left ? left : file->have;
1168 eol = memchr(file->next, '\n', n);
1170 n = (unsigned)(eol - file->next) + 1;
1172 /* copy through end-of-line, or remainder if not found */
1173 memcpy(buf, file->next, n);
1179 } while (left && eol == NULL);
1181 /* found end-of-line or out of space -- terminate string and return it */
1187 file_eof(FILE_T file)
1189 /* return end-of-file state */
1190 return (file->eof && file->avail_in == 0 && file->have == 0);
1194 * Routine to return a Wiretap error code (0 for no error, an errno
1195 * for a file error, or a WTAP_ERR_ code for other errors) for an
1196 * I/O stream. Also returns an error string for some errors.
1199 file_error(FILE_T fh, gchar **err_info)
1202 *err_info = (fh->err_info == NULL) ? NULL : g_strdup(fh->err_info);
1209 file_clearerr(FILE_T stream)
1211 /* clear error and end-of-file */
1213 stream->err_info = NULL;
1218 file_close(FILE_T file)
1222 /* free memory and close file */
1225 inflateEnd(&(file->strm));
1230 g_free(file->fast_seek_cur);
1232 file->err_info = NULL;
1234 return ws_close(fd);
1238 /* internal gzip file state data structure for writing */
1239 struct wtap_writer {
1240 int fd; /* file descriptor */
1241 gint64 pos; /* current position in uncompressed data */
1242 unsigned size; /* buffer size, zero if not allocated yet */
1243 unsigned want; /* requested buffer size, default is GZBUFSIZE */
1244 unsigned char *in; /* input buffer */
1245 unsigned char *out; /* output buffer (double-sized when reading) */
1246 unsigned char *next; /* next output data to deliver or write */
1247 int level; /* compression level */
1248 int strategy; /* compression strategy */
1249 int err; /* error code */
1250 /* zlib deflate stream */
1251 z_stream strm; /* stream structure in-place (not a pointer) */
1255 gzwfile_open(const char *path)
1261 fd = ws_open(path, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666);
1264 state = gzwfile_fdopen(fd);
1265 if (state == NULL) {
1274 gzwfile_fdopen(int fd)
1278 /* allocate wtap_writer structure to return */
1279 state = g_try_malloc(sizeof *state);
1283 state->size = 0; /* no buffers allocated yet */
1284 state->want = GZBUFSIZE; /* requested buffer size */
1286 state->level = Z_DEFAULT_COMPRESSION;
1287 state->strategy = Z_DEFAULT_STRATEGY;
1289 /* initialize stream */
1290 state->err = Z_OK; /* clear error */
1291 state->pos = 0; /* no uncompressed data yet */
1292 state->strm.avail_in = 0; /* no input data yet */
1298 /* Initialize state for writing a gzip file. Mark initialization by setting
1299 state->size to non-zero. Return -1, and set state->err, on failure;
1300 return 0 on success. */
1302 gz_init(GZWFILE_T state)
1305 z_streamp strm = &(state->strm);
1307 /* allocate input and output buffers */
1308 state->in = g_try_malloc(state->want);
1309 state->out = g_try_malloc(state->want);
1310 if (state->in == NULL || state->out == NULL) {
1313 state->err = ENOMEM;
1317 /* allocate deflate memory, set up for gzip compression */
1318 strm->zalloc = Z_NULL;
1319 strm->zfree = Z_NULL;
1320 strm->opaque = Z_NULL;
1321 ret = deflateInit2(strm, state->level, Z_DEFLATED,
1322 15 + 16, 8, state->strategy);
1326 if (ret == Z_MEM_ERROR) {
1327 /* This means "not enough memory". */
1328 state->err = ENOMEM;
1330 /* This "shouldn't happen". */
1331 state->err = WTAP_ERR_INTERNAL;
1336 /* mark state as initialized */
1337 state->size = state->want;
1339 /* initialize write buffer */
1340 strm->avail_out = state->size;
1341 strm->next_out = state->out;
1342 state->next = strm->next_out;
1346 /* Compress whatever is at avail_in and next_in and write to the output file.
1347 Return -1, and set state->err, if there is an error writing to the output
1348 file; return 0 on success.
1349 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
1350 then the deflate() state is reset to start a new gzip stream. */
1352 gz_comp(GZWFILE_T state, int flush)
1356 z_streamp strm = &(state->strm);
1358 /* allocate memory if this is the first time through */
1359 if (state->size == 0 && gz_init(state) == -1)
1362 /* run deflate() on provided input until it produces no more output */
1365 /* write out current buffer contents if full, or if flushing, but if
1366 doing Z_FINISH then don't write until we get to Z_STREAM_END */
1367 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
1368 (flush != Z_FINISH || ret == Z_STREAM_END))) {
1369 have = (unsigned)(strm->next_out - state->next);
1371 got = write(state->fd, state->next, have);
1376 if ((unsigned)got != have) {
1377 state->err = WTAP_ERR_SHORT_WRITE;
1381 if (strm->avail_out == 0) {
1382 strm->avail_out = state->size;
1383 strm->next_out = state->out;
1385 state->next = strm->next_out;
1389 have = strm->avail_out;
1390 ret = deflate(strm, flush);
1391 if (ret == Z_STREAM_ERROR) {
1392 /* This "shouldn't happen". */
1393 state->err = WTAP_ERR_INTERNAL;
1396 have -= strm->avail_out;
1399 /* if that completed a deflate stream, allow another to start */
1400 if (flush == Z_FINISH)
1403 /* all done, no errors */
1407 /* Write out len bytes from buf. Return 0, and set state->err, on
1408 failure or on an attempt to write 0 bytes (in which case state->err
1409 is Z_OK); return the number of bytes written on success. */
1411 gzwfile_write(GZWFILE_T state, const void *buf, unsigned len)
1417 strm = &(state->strm);
1419 /* check that there's no error */
1420 if (state->err != Z_OK)
1423 /* if len is zero, avoid unnecessary operations */
1427 /* allocate memory if this is the first time through */
1428 if (state->size == 0 && gz_init(state) == -1)
1431 /* for small len, copy to input buffer, otherwise compress directly */
1432 if (len < state->size) {
1433 /* copy to input buffer, compress when full */
1435 if (strm->avail_in == 0)
1436 strm->next_in = state->in;
1437 n = state->size - strm->avail_in;
1440 memcpy(strm->next_in + strm->avail_in, buf, n);
1441 strm->avail_in += n;
1443 buf = (char *)buf + n;
1445 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
1450 /* consume whatever's left in the input buffer */
1451 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
1454 /* directly compress user buffer to file */
1455 strm->avail_in = len;
1456 strm->next_in = (voidp)buf;
1458 if (gz_comp(state, Z_NO_FLUSH) == -1)
1462 /* input was all buffered or compressed (put will fit in int) */
1466 /* Flush out what we've written so far. Returns -1, and sets state->err,
1467 on failure; returns 0 on success. */
1469 gzwfile_flush(GZWFILE_T state)
1471 /* check that there's no error */
1472 if (state->err != Z_OK)
1475 /* compress remaining data with Z_SYNC_FLUSH */
1476 gz_comp(state, Z_SYNC_FLUSH);
1477 if (state->err != Z_OK)
1482 /* Flush out all data written, and close the file. Returns a Wiretap
1483 error on failure; returns 0 on success. */
1485 gzwfile_close(GZWFILE_T state)
1489 /* flush, free memory, and close file */
1490 if (gz_comp(state, Z_FINISH) == -1 && ret == 0)
1492 (void)deflateEnd(&(state->strm));
1496 if (close(state->fd) == -1 && ret == 0)
1503 gzwfile_geterr(GZWFILE_T state)