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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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.
48 #endif /* HAVE_UNISTD_H */
54 #endif /* HAVE_FCNTL_H */
57 #include "file_wrappers.h"
58 #include <wsutil/file_util.h>
62 #endif /* HAVE_LIBZ */
65 * See RFC 1952 for a description of the gzip file format.
67 * Some other compressed file formats we might want to support:
69 * XZ format: http://tukaani.org/xz/
71 * Bzip2 format: http://bzip.org/
75 * List of extensions for compressed files.
76 * If we add support for more compressed file types, this table
77 * might be expanded to include routines to handle the various
80 static const char *compressed_file_extensions[] = {
88 * Return a GSList of all the compressed file extensions.
89 * The data pointers all point to items in compressed_file_extensions[],
90 * so the GSList can just be freed with g_slist_free().
93 wtap_get_compressed_file_extensions(void)
95 const char **extension;
99 for (extension = &compressed_file_extensions[0]; *extension != NULL;
101 extensions = g_slist_append(extensions, (gpointer)(*extension));
105 /* #define GZBUFSIZE 8192 */
106 #define GZBUFSIZE 4096
109 int fd; /* file descriptor */
110 gint64 raw_pos; /* current position in file (just to not call lseek()) */
111 gint64 pos; /* current position in uncompressed data */
112 guint size; /* buffer size */
113 unsigned char *in; /* input buffer */
114 unsigned char *out; /* output buffer (double-sized when reading) */
115 unsigned char *next; /* next output data to deliver or write */
117 guint have; /* amount of output data unused at next */
118 int eof; /* true if end of input file reached */
119 gint64 start; /* where the gzip data started, for rewinding */
120 gint64 raw; /* where the raw data started, for seeking */
121 int compression; /* 0: ?, 1: uncompressed, 2: zlib */
122 gboolean is_compressed; /* FALSE if completely uncompressed, TRUE otherwise */
124 gint64 skip; /* amount to skip (already rewound if backwards) */
125 int seek; /* true if seek request pending */
126 /* error information */
127 int err; /* error code */
128 const char *err_info; /* additional error information string for some errors */
130 guint avail_in; /* number of bytes available at next_in */
131 unsigned char *next_in; /* next input byte */
133 /* zlib inflate stream */
134 z_stream strm; /* stream structure in-place (not a pointer) */
135 int dont_check_crc; /* 1 if we aren't supposed to check the CRC */
138 GPtrArray *fast_seek;
142 /* values for wtap_reader compression */
143 #define UNKNOWN 0 /* look for a gzip header */
144 #define UNCOMPRESSED 1 /* copy input directly */
146 #define ZLIB 2 /* decompress a zlib stream */
147 #define GZIP_AFTER_HEADER 3
150 static int /* gz_load */
151 raw_read(FILE_T state, unsigned char *buf, unsigned int count, guint *have)
157 ret = read(state->fd, buf + *have, count - *have);
160 *have += (unsigned)ret;
161 state->raw_pos += ret;
162 } while (*have < count);
165 state->err_info = NULL;
173 static int /* gz_avail */
174 fill_in_buffer(FILE_T state)
178 if (state->eof == 0) {
179 if (raw_read(state, state->in, state->size, &(state->avail_in)) == -1)
181 state->next_in = state->in;
186 #define ZLIB_WINSIZE 32768
188 struct fast_seek_point {
189 gint64 out; /* corresponding offset in uncompressed data */
190 gint64 in; /* offset in input file of first full byte */
195 #ifdef HAVE_INFLATEPRIME
196 int bits; /* number of bits (1-7) from byte at in - 1, or 0 */
198 unsigned char window[ZLIB_WINSIZE]; /* preceding 32K of uncompressed data */
200 /* be gentle with Z_STREAM_END, 8 bytes more... Another solution would be to comment checks out */
207 struct zlib_cur_seek_point {
208 unsigned char window[ZLIB_WINSIZE]; /* preceding 32K of uncompressed data */
213 #define SPAN G_GINT64_CONSTANT(1048576)
214 static struct fast_seek_point *
215 fast_seek_find(FILE_T file, gint64 pos)
217 struct fast_seek_point *smallest = NULL;
218 struct fast_seek_point *item;
221 if (!file->fast_seek)
224 for (low = 0, max = file->fast_seek->len; low < max; ) {
226 item = (struct fast_seek_point *)file->fast_seek->pdata[i];
230 else if (pos > item->out) {
241 fast_seek_header(FILE_T file, gint64 in_pos, gint64 out_pos, int compression)
243 struct fast_seek_point *item = NULL;
245 if (file->fast_seek->len != 0)
246 item = (struct fast_seek_point *)file->fast_seek->pdata[file->fast_seek->len - 1];
248 if (!item || item->out < out_pos) {
249 struct fast_seek_point *val = g_new(struct fast_seek_point,1);
252 val->compression = compression;
254 g_ptr_array_add(file->fast_seek, val);
259 fast_seek_reset(FILE_T state _U_)
262 if (state->compression == ZLIB && state->fast_seek_cur) {
263 struct zlib_cur_seek_point *cur = (struct zlib_cur_seek_point *) state->fast_seek_cur;
272 /* Get next byte from input, or -1 if end or error.
276 * 1) errors from raw_read(), and thus from fill_in_buffer(), are
277 * "sticky", and fill_in_buffer() won't do any reading if there's
280 * 2) GZ_GETC() returns -1 on an EOF;
282 * so it's safe to make multiple GZ_GETC() calls and only check the
283 * last one for an error. */
284 #define GZ_GETC() ((state->avail_in == 0 && fill_in_buffer(state) == -1) ? -1 : \
285 (state->avail_in == 0 ? -1 : \
286 (state->avail_in--, *(state->next_in)++)))
288 /* Get a one-byte integer and return 0 on success and the value in *ret.
289 Otherwise -1 is returned, state->err is set, and *ret is not modified. */
291 gz_next1(FILE_T state, guint8 *ret)
297 if (state->err == 0) {
299 state->err = WTAP_ERR_SHORT_READ;
300 state->err_info = NULL;
308 /* Get a two-byte little-endian integer and return 0 on success and the value
309 in *ret. Otherwise -1 is returned, state->err is set, and *ret is not
312 gz_next2(FILE_T state, guint16 *ret)
320 if (state->err == 0) {
322 state->err = WTAP_ERR_SHORT_READ;
323 state->err_info = NULL;
327 val += (guint16)ch << 8;
332 /* Get a four-byte little-endian integer and return 0 on success and the value
333 in *ret. Otherwise -1 is returned, state->err is set, and *ret is not
336 gz_next4(FILE_T state, guint32 *ret)
342 val += (unsigned)GZ_GETC() << 8;
343 val += (guint32)GZ_GETC() << 16;
346 if (state->err == 0) {
348 state->err = WTAP_ERR_SHORT_READ;
349 state->err_info = NULL;
353 val += (guint32)ch << 24;
358 /* Skip the specified number of bytes and return 0 on success. Otherwise -1
361 gz_skipn(FILE_T state, size_t n)
364 if (GZ_GETC() == -1) {
365 if (state->err == 0) {
367 state->err = WTAP_ERR_SHORT_READ;
368 state->err_info = NULL;
377 /* Skip a null-terminated string and return 0 on success. Otherwise -1
380 gz_skipzstr(FILE_T state)
384 /* It's null-terminated, so scan until we read a byte with
385 the value 0 or get an error. */
386 while ((ch = GZ_GETC()) > 0)
389 if (state->err == 0) {
391 state->err = WTAP_ERR_SHORT_READ;
392 state->err_info = NULL;
400 zlib_fast_seek_add(FILE_T file, struct zlib_cur_seek_point *point, int bits, gint64 in_pos, gint64 out_pos)
402 /* it's for sure after gzip header, so file->fast_seek->len != 0 */
403 struct fast_seek_point *item = (struct fast_seek_point *)file->fast_seek->pdata[file->fast_seek->len - 1];
405 #ifndef HAVE_INFLATEPRIME
410 /* 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)
411 * Inserting value in middle of sorted array is expensive, so we want to add only in the end.
412 * It's not big deal, cause first-read don't usually invoke seeking
414 if (item->out + SPAN < out_pos) {
415 struct fast_seek_point *val = g_new(struct fast_seek_point,1);
418 val->compression = ZLIB;
419 #ifdef HAVE_INFLATEPRIME
420 val->data.zlib.bits = bits;
422 if (point->pos != 0) {
423 unsigned int left = ZLIB_WINSIZE - point->pos;
425 memcpy(val->data.zlib.window, point->window + point->pos, left);
426 memcpy(val->data.zlib.window + left, point->window, point->pos);
428 memcpy(val->data.zlib.window, point->window, ZLIB_WINSIZE);
431 * XXX - strm.adler is a uLong in at least some versions
432 * of zlib, and uLong is an unsigned long in at least
433 * some of those versions, which means it's 64-bit
434 * on LP64 platforms, even though the checksum is
435 * 32-bit. We assume the actual Adler checksum
436 * is in the lower 32 bits of strm.adler; as the
437 * checksum in the file is only 32 bits, we save only
438 * those lower 32 bits, and cast away any additional
439 * bits to squelch warnings.
441 * The same applies to strm.total_out.
443 val->data.zlib.adler = (guint32) file->strm.adler;
444 val->data.zlib.total_out = (guint32) file->strm.total_out;
445 g_ptr_array_add(file->fast_seek, val);
449 static void /* gz_decomp */
450 zlib_read(FILE_T state, unsigned char *buf, unsigned int count)
452 int ret = 0; /* XXX */
454 z_streamp strm = &(state->strm);
456 unsigned char *buf2 = buf;
457 unsigned int count2 = count;
459 strm->avail_out = count;
460 strm->next_out = buf;
462 /* fill output buffer up to end of deflate stream or error */
464 /* get more input for inflate() */
465 if (state->avail_in == 0 && fill_in_buffer(state) == -1)
467 if (state->avail_in == 0) {
469 state->err = WTAP_ERR_SHORT_READ;
470 state->err_info = NULL;
474 strm->avail_in = state->avail_in;
475 strm->next_in = state->next_in;
476 /* decompress and handle errors */
478 ret = inflate(strm, Z_BLOCK);
480 ret = inflate(strm, Z_NO_FLUSH);
482 state->avail_in = strm->avail_in;
483 state->next_in = strm->next_in;
484 if (ret == Z_STREAM_ERROR) {
485 state->err = WTAP_ERR_DECOMPRESS;
486 state->err_info = strm->msg;
489 if (ret == Z_NEED_DICT) {
490 state->err = WTAP_ERR_DECOMPRESS;
491 state->err_info = "preset dictionary needed";
494 if (ret == Z_MEM_ERROR) {
495 /* This means "not enough memory". */
497 state->err_info = NULL;
500 if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
501 state->err = WTAP_ERR_DECOMPRESS;
502 state->err_info = strm->msg;
509 strm->adler = crc32(strm->adler, buf2, count2 - strm->avail_out);
511 if (state->fast_seek_cur) {
512 struct zlib_cur_seek_point *cur = (struct zlib_cur_seek_point *) state->fast_seek_cur;
513 unsigned int ready = count2 - strm->avail_out;
515 if (ready < ZLIB_WINSIZE) {
516 guint left = ZLIB_WINSIZE - cur->pos;
519 memcpy(cur->window + cur->pos, buf2, left);
521 memcpy(cur->window, buf2 + left, ready - left);
523 cur->pos = ready - left;
526 memcpy(cur->window + cur->pos, buf2, ready);
531 if (cur->have >= ZLIB_WINSIZE)
532 cur->have = ZLIB_WINSIZE;
535 memcpy(cur->window, buf2 + (ready - ZLIB_WINSIZE), ZLIB_WINSIZE);
537 cur->have = ZLIB_WINSIZE;
540 if (cur->have >= ZLIB_WINSIZE && ret != Z_STREAM_END && (strm->data_type & 128) && !(strm->data_type & 64))
541 zlib_fast_seek_add(state, cur, (strm->data_type & 7), state->raw_pos - strm->avail_in, state->pos + (count - strm->avail_out));
544 buf2 = (buf2 + count2 - strm->avail_out);
545 count2 = strm->avail_out;
547 } while (strm->avail_out && ret != Z_STREAM_END);
549 /* update available output and crc check value */
551 state->have = count - strm->avail_out;
553 /* Check gzip trailer if at end of deflate stream.
554 We don't fail immediately here, we just set an error
555 indication, so that we try to process what data we
556 got before the error. The next attempt to read
557 something past that data will get the error. */
558 if (ret == Z_STREAM_END) {
559 if (gz_next4(state, &crc) != -1 &&
560 gz_next4(state, &len) != -1) {
561 if (crc != strm->adler && !state->dont_check_crc) {
562 state->err = WTAP_ERR_DECOMPRESS;
563 state->err_info = "bad CRC";
564 } else if (len != (strm->total_out & 0xffffffffL)) {
565 state->err = WTAP_ERR_DECOMPRESS;
566 state->err_info = "length field wrong";
569 state->compression = UNKNOWN; /* ready for next stream, once have is 0 */
570 g_free(state->fast_seek_cur);
571 state->fast_seek_cur = NULL;
577 gz_head(FILE_T state)
579 /* get some data in the input buffer */
580 if (state->avail_in == 0) {
581 if (fill_in_buffer(state) == -1)
583 if (state->avail_in == 0)
587 /* look for the gzip magic header bytes 31 and 139 */
589 if (state->next_in[0] == 31) {
592 if (state->avail_in == 0 && fill_in_buffer(state) == -1)
594 if (state->avail_in && state->next_in[0] == 139) {
600 /* we have a gzip header, woo hoo! */
604 /* read rest of header */
606 /* compression method (CM) */
607 if (gz_next1(state, &cm) == -1)
610 state->err = WTAP_ERR_DECOMPRESS;
611 state->err_info = "unknown compression method";
616 if (gz_next1(state, &flags) == -1)
618 if (flags & 0xe0) { /* reserved flag bits */
619 state->err = WTAP_ERR_DECOMPRESS;
620 state->err_info = "reserved flag bits set";
624 /* modification time (MTIME) */
625 if (gz_skipn(state, 4) == -1)
628 /* extra flags (XFL) */
629 if (gz_skipn(state, 1) == -1)
632 /* operating system (OS) */
633 if (gz_skipn(state, 1) == -1)
637 /* extra field - get XLEN */
638 if (gz_next2(state, &len) == -1)
641 /* skip the extra field */
642 if (gz_skipn(state, len) == -1)
647 if (gz_skipzstr(state) == -1)
652 if (gz_skipzstr(state) == -1)
657 if (gz_next2(state, &hcrc) == -1)
659 /* XXX - check the CRC? */
662 /* set up for decompression */
663 inflateReset(&(state->strm));
664 state->strm.adler = crc32(0L, Z_NULL, 0);
665 state->compression = ZLIB;
666 state->is_compressed = TRUE;
668 if (state->fast_seek) {
669 struct zlib_cur_seek_point *cur = g_new(struct zlib_cur_seek_point,1);
671 cur->pos = cur->have = 0;
672 g_free(state->fast_seek_cur);
673 state->fast_seek_cur = cur;
674 fast_seek_header(state, state->raw_pos - state->avail_in, state->pos, GZIP_AFTER_HEADER);
680 /* not a gzip file -- save first byte (31) and fall to raw i/o */
687 /* { 0xFD, '7', 'z', 'X', 'Z', 0x00 } */
688 /* FD 37 7A 58 5A 00 */
690 if (state->fast_seek)
691 fast_seek_header(state, state->raw_pos - state->avail_in - state->have, state->pos, UNCOMPRESSED);
693 /* doing raw i/o, save start of raw data for seeking, copy any leftover
694 input to output -- this assumes that the output buffer is larger than
695 the input buffer, which also assures space for gzungetc() */
696 state->raw = state->pos;
697 state->next = state->out;
698 if (state->avail_in) {
699 memcpy(state->next + state->have, state->next_in, state->avail_in);
700 state->have += state->avail_in;
703 state->compression = UNCOMPRESSED;
707 static int /* gz_make */
708 fill_out_buffer(FILE_T state)
710 if (state->compression == UNKNOWN) { /* look for gzip header */
711 if (gz_head(state) == -1)
713 if (state->have) /* got some data from gz_head() */
716 if (state->compression == UNCOMPRESSED) { /* straight copy */
717 if (raw_read(state, state->out, state->size /* << 1 */, &(state->have)) == -1)
719 state->next = state->out;
722 else if (state->compression == ZLIB) { /* decompress */
723 zlib_read(state, state->out, state->size << 1);
730 gz_skip(FILE_T state, gint64 len)
734 /* skip over len bytes or reach end-of-file, whichever comes first */
737 /* We have stuff in the output buffer; skip over
739 n = (gint64)state->have > len ? (unsigned)len : state->have;
744 } else if (state->err) {
745 /* We have nothing in the output buffer, and
746 we have an error that may not have been
747 reported yet; that means we can't generate
748 any more data into the output buffer, so
749 return an error indication. */
751 } else if (state->eof && state->avail_in == 0) {
752 /* We have nothing in the output buffer, and
753 we're at the end of the input; just return. */
756 /* We have nothing in the output buffer, and
757 we can generate more data; get more output,
758 looking for header if required. */
759 if (fill_out_buffer(state) == -1)
766 gz_reset(FILE_T state)
768 state->have = 0; /* no output data available */
769 state->eof = 0; /* not at end of file */
770 state->compression = UNKNOWN; /* look for gzip header */
772 state->seek = 0; /* no seek request pending */
773 state->err = 0; /* clear error */
774 state->err_info = NULL;
775 state->pos = 0; /* no uncompressed data yet */
776 state->avail_in = 0; /* no input data yet */
782 #ifdef _STATBUF_ST_BLKSIZE /* XXX, _STATBUF_ST_BLKSIZE portable? */
785 int want = GZBUFSIZE;
791 /* allocate FILE_T structure to return */
792 state = (FILE_T)g_try_malloc(sizeof *state);
796 state->fast_seek_cur = NULL;
797 state->fast_seek = NULL;
799 /* open the file with the appropriate mode (or just use fd) */
802 /* we don't yet know whether it's compressed */
803 state->is_compressed = FALSE;
805 /* save the current position for rewinding (only if reading) */
806 state->start = ws_lseek64(state->fd, 0, SEEK_CUR);
807 if (state->start == -1) state->start = 0;
808 state->raw_pos = state->start;
810 /* initialize stream */
813 #ifdef _STATBUF_ST_BLKSIZE
814 if (fstat(fd, &st) >= 0) {
815 want = st.st_blksize;
816 /* XXX, verify result? */
820 /* allocate buffers */
821 state->in = (unsigned char *)g_try_malloc(want);
822 state->out = (unsigned char *)g_try_malloc(want << 1);
824 if (state->in == NULL || state->out == NULL) {
833 /* allocate inflate memory */
834 state->strm.zalloc = Z_NULL;
835 state->strm.zfree = Z_NULL;
836 state->strm.opaque = Z_NULL;
837 state->strm.avail_in = 0;
838 state->strm.next_in = Z_NULL;
839 if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */
847 /* for now, assume we should check the crc */
848 state->dont_check_crc = 0;
855 file_open(const char *path)
863 /* open file and do correct filename conversions.
865 XXX - do we need O_LARGEFILE? On UN*X, if we need to do
866 something special to get large file support, the configure
867 script should have set us up with the appropriate #defines,
868 so we should be getting a large-file-enabled file descriptor
869 here. Pre-Large File Summit UN*Xes, and possibly even some
870 post-LFS UN*Xes, might require O_LARGEFILE here, though.
871 If so, we should probably handle that in ws_open(). */
872 if ((fd = ws_open(path, O_RDONLY|O_BINARY, 0000)) == -1)
875 /* open file handle */
876 ft = file_fdopen(fd);
884 * If this file's name ends in ".caz", it's probably a compressed
885 * Windows Sniffer file. The compression is gzip, but if we
886 * process the CRC as specified by RFC 1952, the computed CRC
887 * doesn't match the stored CRC.
889 * Compressed Windows Sniffer files don't all have the same CRC
890 * value; is it just random crap, or are they running the CRC on
891 * a different set of data than you're supposed to (e.g., not
892 * CRCing some of the data), or something such as that?
894 * For now, we just set a flag to ignore CRC errors.
896 suffixp = strrchr(path, '.');
897 if (suffixp != NULL) {
898 if (g_ascii_strcasecmp(suffixp, ".caz") == 0)
899 ft->dont_check_crc = 1;
907 file_set_random_access(FILE_T stream, gboolean random_flag _U_, GPtrArray *seek)
909 stream->fast_seek = seek;
913 file_seek(FILE_T file, gint64 offset, int whence, int *err)
915 struct fast_seek_point *here;
918 /* can only seek from start or relative to current position */
919 if (whence != SEEK_SET && whence != SEEK_CUR) {
920 g_assert_not_reached();
927 /* normalize offset to a SEEK_CUR specification */
928 if (whence == SEEK_SET)
931 offset += file->skip;
934 if (offset < 0 && file->next) {
936 * This is guaranteed to fit in an unsigned int.
937 * To squelch compiler warnings, we cast the
940 guint had = (unsigned)(file->next - file->out);
941 if (-offset <= had) {
943 * Offset is negative, so -offset is
944 * non-negative, and -offset is
945 * <= an unsigned and thus fits in an
946 * unsigned. Get that value and
947 * adjust appropriately.
949 * (Casting offset to unsigned makes
950 * it positive, which is not what we
951 * would want, so we cast -offset
954 guint adjustment = (unsigned)(-offset);
955 file->have += adjustment;
956 file->next -= adjustment;
957 file->pos -= adjustment;
963 if ((here = fast_seek_find(file, file->pos + offset)) && (offset < 0 || offset > SPAN || here->compression == UNCOMPRESSED)) {
967 if (here->compression == ZLIB) {
968 #ifdef HAVE_INFLATEPRIME
969 off = here->in - (here->data.zlib.bits ? 1 : 0);
974 } else if (here->compression == GZIP_AFTER_HEADER) {
980 off2 = (file->pos + offset);
981 off = here->in + (off2 - here->out);
984 if (ws_lseek64(file->fd, off, SEEK_SET) == -1) {
988 fast_seek_reset(file);
995 file->err_info = NULL;
999 if (here->compression == ZLIB) {
1000 z_stream *strm = &file->strm;
1003 strm->adler = here->data.zlib.adler;
1004 strm->total_out = here->data.zlib.total_out;
1005 #ifdef HAVE_INFLATEPRIME
1006 if (here->data.zlib.bits) {
1007 FILE_T state = file;
1008 int ret = GZ_GETC();
1011 if (state->err == 0) {
1013 *err = WTAP_ERR_SHORT_READ;
1018 (void)inflatePrime(strm, here->data.zlib.bits, ret >> (8 - here->data.zlib.bits));
1021 (void)inflateSetDictionary(strm, here->data.zlib.window, ZLIB_WINSIZE);
1022 file->compression = ZLIB;
1023 } else if (here->compression == GZIP_AFTER_HEADER) {
1024 z_stream *strm = &file->strm;
1027 strm->adler = crc32(0L, Z_NULL, 0);
1028 file->compression = ZLIB;
1031 file->compression = here->compression;
1033 offset = (file->pos + offset) - off2;
1035 /* g_print("OK! %ld\n", offset); */
1039 file->skip = offset;
1041 return file->pos + offset;
1044 /* if within raw area while reading, just go there */
1045 if (file->compression == UNCOMPRESSED && file->pos + offset >= file->raw
1046 && (offset < 0 || offset >= file->have) /* seek only when we don't have that offset in buffer */)
1048 if (ws_lseek64(file->fd, offset - file->have, SEEK_CUR) == -1) {
1052 file->raw_pos += (offset - file->have);
1057 file->err_info = NULL;
1059 file->pos += offset;
1063 /* calculate skip amount, rewinding if needed for back seek when reading */
1065 offset += file->pos;
1066 if (offset < 0) { /* before start of file! */
1070 /* rewind, then skip to offset */
1072 /* back up and start over */
1073 if (ws_lseek64(file->fd, file->start, SEEK_SET) == -1) {
1077 fast_seek_reset(file);
1078 file->raw_pos = file->start;
1082 /* skip what's in output buffer (one less gzgetc() check) */
1083 n = (gint64)file->have > offset ? (unsigned)offset : file->have;
1089 /* request skip (if not zero) */
1092 file->skip = offset;
1094 return file->pos + offset;
1098 * Skip forward the specified number of bytes in the file.
1099 * Currently implemented as a wrapper around file_seek(),
1100 * but if, for example, we ever add support for reading
1101 * sequentially from a pipe, this could instead just skip
1102 * forward by reading the bytes in question.
1105 file_skip(FILE_T file, gint64 delta, int *err)
1107 return file_seek(file, delta, SEEK_CUR, err);
1111 file_tell(FILE_T stream)
1113 /* return position */
1114 return stream->pos + (stream->seek ? stream->skip : 0);
1118 file_tell_raw(FILE_T stream)
1120 return stream->raw_pos;
1124 file_fstat(FILE_T stream, ws_statb64 *statb, int *err)
1126 if (ws_fstat64(stream->fd, statb) == -1) {
1135 file_iscompressed(FILE_T stream)
1137 return stream->is_compressed;
1141 file_read(void *buf, unsigned int len, FILE_T file)
1145 /* if len is zero, avoid unnecessary operations */
1149 /* process a skip request */
1152 if (gz_skip(file, file->skip) == -1)
1156 /* get len bytes to buf, or less than len if at the end */
1160 /* We have stuff in the output buffer; copy
1162 n = file->have > len ? len : file->have;
1163 memcpy(buf, file->next, n);
1166 } else if (file->err) {
1167 /* We have nothing in the output buffer, and
1168 we have an error that may not have been
1169 reported yet; that means we can't generate
1170 any more data into the output buffer, so
1171 return an error indication. */
1173 } else if (file->eof && file->avail_in == 0) {
1174 /* We have nothing in the output buffer, and
1175 we're at the end of the input; just return
1176 with what we've gotten so far. */
1179 /* We have nothing in the output buffer, and
1180 we can generate more data; get more output,
1181 looking for header if required, and
1182 keep looping to process the new stuff
1183 in the output buffer. */
1184 if (fill_out_buffer(file) == -1)
1186 continue; /* no progress yet -- go back to memcpy() above */
1188 /* update progress */
1190 buf = (char *)buf + n;
1199 file_getc(FILE_T file)
1201 unsigned char buf[1];
1204 /* check that we're reading and that there's no error */
1208 /* try output buffer (no need to check for skip request) */
1212 return *(file->next)++;
1215 ret = file_read(buf, 1, file);
1216 return ret < 1 ? -1 : buf[0];
1220 file_gets(char *buf, int len, FILE_T file)
1226 /* check parameters */
1227 if (buf == NULL || len < 1)
1230 /* check that there's no error */
1234 /* process a skip request */
1237 if (gz_skip(file, file->skip) == -1)
1241 /* copy output bytes up to new line or len - 1, whichever comes first --
1242 append a terminating zero to the string (we don't check for a zero in
1243 the contents, let the user worry about that) */
1245 left = (unsigned)len - 1;
1247 /* assure that something is in the output buffer */
1248 if (file->have == 0) {
1249 /* We have nothing in the output buffer. */
1251 /* We have an error that may not have
1252 been reported yet; that means we
1253 can't generate any more data into
1254 the output buffer, so return an
1255 error indication. */
1258 if (fill_out_buffer(file) == -1)
1259 return NULL; /* error */
1260 if (file->have == 0) { /* end of file */
1261 if (buf == str) /* got bupkus */
1263 break; /* got something -- return it */
1267 /* look for end-of-line in current output buffer */
1268 n = file->have > left ? left : file->have;
1269 eol = (unsigned char *)memchr(file->next, '\n', n);
1271 n = (unsigned)(eol - file->next) + 1;
1273 /* copy through end-of-line, or remainder if not found */
1274 memcpy(buf, file->next, n);
1280 } while (left && eol == NULL);
1282 /* found end-of-line or out of space -- terminate string and return it */
1288 file_eof(FILE_T file)
1290 /* return end-of-file state */
1291 return (file->eof && file->avail_in == 0 && file->have == 0);
1295 * Routine to return a Wiretap error code (0 for no error, an errno
1296 * for a file error, or a WTAP_ERR_ code for other errors) for an
1297 * I/O stream. Also returns an error string for some errors.
1300 file_error(FILE_T fh, gchar **err_info)
1303 *err_info = (fh->err_info == NULL) ? NULL : g_strdup(fh->err_info);
1310 file_clearerr(FILE_T stream)
1312 /* clear error and end-of-file */
1314 stream->err_info = NULL;
1319 file_fdclose(FILE_T file)
1326 file_fdreopen(FILE_T file, const char *path)
1330 if ((fd = ws_open(path, O_RDONLY|O_BINARY, 0000)) == -1)
1337 file_close(FILE_T file)
1341 /* free memory and close file */
1344 inflateEnd(&(file->strm));
1349 g_free(file->fast_seek_cur);
1351 file->err_info = NULL;
1354 * If fd is -1, somebody's done a file_closefd() on us, so
1355 * we don't need to close the FD itself, and shouldn't do
1363 /* internal gzip file state data structure for writing */
1364 struct wtap_writer {
1365 int fd; /* file descriptor */
1366 gint64 pos; /* current position in uncompressed data */
1367 guint size; /* buffer size, zero if not allocated yet */
1368 guint want; /* requested buffer size, default is GZBUFSIZE */
1369 unsigned char *in; /* input buffer */
1370 unsigned char *out; /* output buffer (double-sized when reading) */
1371 unsigned char *next; /* next output data to deliver or write */
1372 int level; /* compression level */
1373 int strategy; /* compression strategy */
1374 int err; /* error code */
1375 /* zlib deflate stream */
1376 z_stream strm; /* stream structure in-place (not a pointer) */
1380 gzwfile_open(const char *path)
1386 fd = ws_open(path, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666);
1389 state = gzwfile_fdopen(fd);
1390 if (state == NULL) {
1399 gzwfile_fdopen(int fd)
1403 /* allocate wtap_writer structure to return */
1404 state = (GZWFILE_T)g_try_malloc(sizeof *state);
1408 state->size = 0; /* no buffers allocated yet */
1409 state->want = GZBUFSIZE; /* requested buffer size */
1411 state->level = Z_DEFAULT_COMPRESSION;
1412 state->strategy = Z_DEFAULT_STRATEGY;
1414 /* initialize stream */
1415 state->err = Z_OK; /* clear error */
1416 state->pos = 0; /* no uncompressed data yet */
1417 state->strm.avail_in = 0; /* no input data yet */
1423 /* Initialize state for writing a gzip file. Mark initialization by setting
1424 state->size to non-zero. Return -1, and set state->err, on failure;
1425 return 0 on success. */
1427 gz_init(GZWFILE_T state)
1430 z_streamp strm = &(state->strm);
1432 /* allocate input and output buffers */
1433 state->in = (unsigned char *)g_try_malloc(state->want);
1434 state->out = (unsigned char *)g_try_malloc(state->want);
1435 if (state->in == NULL || state->out == NULL) {
1438 state->err = ENOMEM;
1442 /* allocate deflate memory, set up for gzip compression */
1443 strm->zalloc = Z_NULL;
1444 strm->zfree = Z_NULL;
1445 strm->opaque = Z_NULL;
1446 ret = deflateInit2(strm, state->level, Z_DEFLATED,
1447 15 + 16, 8, state->strategy);
1451 if (ret == Z_MEM_ERROR) {
1452 /* This means "not enough memory". */
1453 state->err = ENOMEM;
1455 /* This "shouldn't happen". */
1456 state->err = WTAP_ERR_INTERNAL;
1461 /* mark state as initialized */
1462 state->size = state->want;
1464 /* initialize write buffer */
1465 strm->avail_out = state->size;
1466 strm->next_out = state->out;
1467 state->next = strm->next_out;
1471 /* Compress whatever is at avail_in and next_in and write to the output file.
1472 Return -1, and set state->err, if there is an error writing to the output
1473 file; return 0 on success.
1474 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
1475 then the deflate() state is reset to start a new gzip stream. */
1477 gz_comp(GZWFILE_T state, int flush)
1482 z_streamp strm = &(state->strm);
1484 /* allocate memory if this is the first time through */
1485 if (state->size == 0 && gz_init(state) == -1)
1488 /* run deflate() on provided input until it produces no more output */
1491 /* write out current buffer contents if full, or if flushing, but if
1492 doing Z_FINISH then don't write until we get to Z_STREAM_END */
1493 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
1494 (flush != Z_FINISH || ret == Z_STREAM_END))) {
1495 have = strm->next_out - state->next;
1497 got = write(state->fd, state->next, (unsigned int)have);
1502 if ((ptrdiff_t)got != have) {
1503 state->err = WTAP_ERR_SHORT_WRITE;
1507 if (strm->avail_out == 0) {
1508 strm->avail_out = state->size;
1509 strm->next_out = state->out;
1511 state->next = strm->next_out;
1515 have = strm->avail_out;
1516 ret = deflate(strm, flush);
1517 if (ret == Z_STREAM_ERROR) {
1518 /* This "shouldn't happen". */
1519 state->err = WTAP_ERR_INTERNAL;
1522 have -= strm->avail_out;
1525 /* if that completed a deflate stream, allow another to start */
1526 if (flush == Z_FINISH)
1529 /* all done, no errors */
1533 /* Write out len bytes from buf. Return 0, and set state->err, on
1534 failure or on an attempt to write 0 bytes (in which case state->err
1535 is Z_OK); return the number of bytes written on success. */
1537 gzwfile_write(GZWFILE_T state, const void *buf, guint len)
1543 strm = &(state->strm);
1545 /* check that there's no error */
1546 if (state->err != Z_OK)
1549 /* if len is zero, avoid unnecessary operations */
1553 /* allocate memory if this is the first time through */
1554 if (state->size == 0 && gz_init(state) == -1)
1557 /* for small len, copy to input buffer, otherwise compress directly */
1558 if (len < state->size) {
1559 /* copy to input buffer, compress when full */
1561 if (strm->avail_in == 0)
1562 strm->next_in = state->in;
1563 n = state->size - strm->avail_in;
1566 memcpy(strm->next_in + strm->avail_in, buf, n);
1567 strm->avail_in += n;
1569 buf = (char *)buf + n;
1571 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
1576 /* consume whatever's left in the input buffer */
1577 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
1580 /* directly compress user buffer to file */
1581 strm->avail_in = len;
1582 strm->next_in = (voidp)buf;
1584 if (gz_comp(state, Z_NO_FLUSH) == -1)
1588 /* input was all buffered or compressed (put will fit in int) */
1592 /* Flush out what we've written so far. Returns -1, and sets state->err,
1593 on failure; returns 0 on success. */
1595 gzwfile_flush(GZWFILE_T state)
1597 /* check that there's no error */
1598 if (state->err != Z_OK)
1601 /* compress remaining data with Z_SYNC_FLUSH */
1602 gz_comp(state, Z_SYNC_FLUSH);
1603 if (state->err != Z_OK)
1608 /* Flush out all data written, and close the file. Returns a Wiretap
1609 error on failure; returns 0 on success. */
1611 gzwfile_close(GZWFILE_T state)
1615 /* flush, free memory, and close file */
1616 if (gz_comp(state, Z_FINISH) == -1 && ret == 0)
1618 (void)deflateEnd(&(state->strm));
1622 if (close(state->fd) == -1 && ret == 0)
1629 gzwfile_geterr(GZWFILE_T state)