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) */
101 int dont_check_crc; /* 1 if we aren't supposed to check the CRC */
104 GPtrArray *fast_seek;
108 /* values for gz_state compression */
109 #define UNKNOWN 0 /* look for a gzip header */
110 #define UNCOMPRESSED 1 /* copy input directly */
112 #define ZLIB 2 /* decompress a zlib stream */
113 #define GZIP_AFTER_HEADER 3
116 static int /* gz_load */
117 raw_read(FILE_T state, unsigned char *buf, unsigned int count, unsigned *have)
123 ret = read(state->fd, buf + *have, count - *have);
127 state->raw_pos += ret;
128 } while (*have < count);
131 state->err_info = NULL;
139 static int /* gz_avail */
140 fill_in_buffer(FILE_T state)
144 if (state->eof == 0) {
145 if (raw_read(state, state->in, state->size, (unsigned *)&(state->avail_in)) == -1)
147 state->next_in = state->in;
152 #define ZLIB_WINSIZE 32768
154 struct fast_seek_point {
155 gint64 out; /* corresponding offset in uncompressed data */
156 gint64 in; /* offset in input file of first full byte */
161 #ifdef HAVE_INFLATEPRIME
162 int bits; /* number of bits (1-7) from byte at in - 1, or 0 */
164 unsigned char window[ZLIB_WINSIZE]; /* preceding 32K of uncompressed data */
166 /* be gentle with Z_STREAM_END, 8 bytes more... Another solution would be to comment checks out */
173 struct zlib_cur_seek_point {
174 unsigned char window[ZLIB_WINSIZE]; /* preceding 32K of uncompressed data */
179 #define SPAN G_GINT64_CONSTANT(1048576)
180 static struct fast_seek_point *
181 fast_seek_find(FILE_T file, gint64 pos)
183 struct fast_seek_point *smallest = NULL;
184 struct fast_seek_point *item;
187 if (!file->fast_seek)
190 for (low = 0, max = file->fast_seek->len; low < max; ) {
192 item = file->fast_seek->pdata[i];
196 else if (pos > item->out) {
207 fast_seek_header(FILE_T file, gint64 in_pos, gint64 out_pos, int compression)
209 struct fast_seek_point *item = NULL;
211 if (file->fast_seek->len != 0)
212 item = file->fast_seek->pdata[file->fast_seek->len - 1];
214 if (!item || item->out < out_pos) {
215 struct fast_seek_point *val = g_malloc(sizeof(struct fast_seek_point));
218 val->compression = compression;
220 g_ptr_array_add(file->fast_seek, val);
225 fast_seek_reset(FILE_T state _U_)
228 if (state->compression == ZLIB && state->fast_seek_cur) {
229 struct zlib_cur_seek_point *cur = (struct zlib_cur_seek_point *) state->fast_seek_cur;
238 /* Get next byte from input, or -1 if end or error.
242 * 1) errors from raw_read(), and thus from fill_in_buffer(), are
243 * "sticky", and fill_in_buffer() won't do any reading if there's
246 * 2) GZ_GETC() returns -1 on an EOF;
248 * so it's safe to make multiple GZ_GETC() calls and only check the
249 * last one for an error. */
250 #define GZ_GETC() ((state->avail_in == 0 && fill_in_buffer(state) == -1) ? -1 : \
251 (state->avail_in == 0 ? -1 : \
252 (state->avail_in--, *(state->next_in)++)))
254 /* Get a one-byte integer and return 0 on success and the value in *ret.
255 Otherwise -1 is returned, state->err is set, and *ret is not modified. */
257 gz_next1(FILE_T state, guint8 *ret)
263 if (state->err == 0) {
265 state->err = WTAP_ERR_SHORT_READ;
266 state->err_info = NULL;
274 /* Get a two-byte little-endian integer and return 0 on success and the value
275 in *ret. Otherwise -1 is returned, state->err is set, and *ret is not
278 gz_next2(FILE_T state, guint16 *ret)
286 if (state->err == 0) {
288 state->err = WTAP_ERR_SHORT_READ;
289 state->err_info = NULL;
293 val += (guint16)ch << 8;
298 /* Get a four-byte little-endian integer and return 0 on success and the value
299 in *ret. Otherwise -1 is returned, state->err is set, and *ret is not
302 gz_next4(FILE_T state, guint32 *ret)
308 val += (unsigned)GZ_GETC() << 8;
309 val += (guint32)GZ_GETC() << 16;
312 if (state->err == 0) {
314 state->err = WTAP_ERR_SHORT_READ;
315 state->err_info = NULL;
319 val += (guint32)ch << 24;
324 /* Skip the specified number of bytes and return 0 on success. Otherwise -1
327 gz_skipn(FILE_T state, size_t n)
330 if (GZ_GETC() == -1) {
331 if (state->err == 0) {
333 state->err = WTAP_ERR_SHORT_READ;
334 state->err_info = NULL;
343 /* Skip a null-terminated string and return 0 on success. Otherwise -1
346 gz_skipzstr(FILE_T state)
350 /* It's null-terminated, so scan until we read a byte with
351 the value 0 or get an error. */
352 while ((ch = GZ_GETC()) > 0)
355 if (state->err == 0) {
357 state->err = WTAP_ERR_SHORT_READ;
358 state->err_info = NULL;
366 zlib_fast_seek_add(FILE_T file, struct zlib_cur_seek_point *point, int bits, gint64 in_pos, gint64 out_pos)
368 /* it's for sure after gzip header, so file->fast_seek->len != 0 */
369 struct fast_seek_point *item = file->fast_seek->pdata[file->fast_seek->len - 1];;
371 #ifndef HAVE_INFLATEPRIME
376 /* 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)
377 * Inserting value in middle of sorted array is expensive, so we want to add only in the end.
378 * It's not big deal, cause first-read don't usually invoke seeking
380 if (item->out + SPAN < out_pos) {
381 struct fast_seek_point *val = g_malloc(sizeof(struct fast_seek_point));
384 val->compression = ZLIB;
385 #ifdef HAVE_INFLATEPRIME
386 val->data.zlib.bits = bits;
388 if (point->pos != 0) {
389 unsigned int left = ZLIB_WINSIZE - point->pos;
391 memcpy(val->data.zlib.window, point->window + point->pos, left);
392 memcpy(val->data.zlib.window + left, point->window, point->pos);
394 memcpy(val->data.zlib.window, point->window, ZLIB_WINSIZE);
396 val->data.zlib.adler = file->strm.adler;
397 val->data.zlib.total_out = file->strm.total_out;
398 g_ptr_array_add(file->fast_seek, val);
402 static void /* gz_decomp */
403 zlib_read(FILE_T state, unsigned char *buf, unsigned int count)
405 int ret = 0; /* XXX */
407 z_streamp strm = &(state->strm);
409 unsigned char *buf2 = buf;
410 unsigned int count2 = count;
412 strm->avail_out = count;
413 strm->next_out = buf;
415 /* fill output buffer up to end of deflate stream or error */
417 /* get more input for inflate() */
418 if (state->avail_in == 0 && fill_in_buffer(state) == -1)
420 if (state->avail_in == 0) {
422 state->err = WTAP_ERR_SHORT_READ;
423 state->err_info = NULL;
427 strm->avail_in = state->avail_in;
428 strm->next_in = state->next_in;
429 /* decompress and handle errors */
430 /* ret = inflate(strm, Z_NO_FLUSH); */
431 ret = inflate(strm, Z_BLOCK);
432 state->avail_in = strm->avail_in;
433 state->next_in = strm->next_in;
434 if (ret == Z_STREAM_ERROR) {
435 state->err = WTAP_ERR_DECOMPRESS;
436 state->err_info = strm->msg;
439 if (ret == Z_NEED_DICT) {
440 state->err = WTAP_ERR_DECOMPRESS;
441 state->err_info = "preset dictionary needed";
444 if (ret == Z_MEM_ERROR) {
445 /* This means "not enough memory". */
447 state->err_info = NULL;
450 if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
451 state->err = WTAP_ERR_DECOMPRESS;
452 state->err_info = strm->msg;
459 strm->adler = crc32(strm->adler, buf2, count2 - strm->avail_out);
460 if (state->fast_seek_cur) {
461 struct zlib_cur_seek_point *cur = (struct zlib_cur_seek_point *) state->fast_seek_cur;
462 unsigned int ready = count2 - strm->avail_out;
464 if (ready < ZLIB_WINSIZE) {
465 unsigned left = ZLIB_WINSIZE - cur->pos;
468 memcpy(cur->window + cur->pos, buf2, left);
470 memcpy(cur->window, buf2 + left, ready - left);
472 cur->pos = ready - left;
475 memcpy(cur->window + cur->pos, buf2, ready);
480 if (cur->have >= ZLIB_WINSIZE)
481 cur->have = ZLIB_WINSIZE;
484 memcpy(cur->window, buf2 + (ready - ZLIB_WINSIZE), ZLIB_WINSIZE);
486 cur->have = ZLIB_WINSIZE;
489 if (cur->have >= ZLIB_WINSIZE && ret != Z_STREAM_END && (strm->data_type & 128) && !(strm->data_type & 64))
490 zlib_fast_seek_add(state, cur, (strm->data_type & 7), state->raw_pos - strm->avail_in, state->pos + (count - strm->avail_out));
492 buf2 = (buf2 + count2 - strm->avail_out);
493 count2 = strm->avail_out;
495 } while (strm->avail_out && ret != Z_STREAM_END);
497 /* update available output and crc check value */
499 state->have = count - strm->avail_out;
501 /* Check gzip trailer if at end of deflate stream.
502 We don't fail immediately here, we just set an error
503 indication, so that we try to process what data we
504 got before the error. The next attempt to read
505 something past that data will get the error. */
506 if (ret == Z_STREAM_END) {
507 if (gz_next4(state, &crc) != -1 &&
508 gz_next4(state, &len) != -1) {
510 * XXX - compressed Windows Sniffer don't
511 * all have the same CRC value; is it just
512 * random crap, or are they running the
513 * CRC on a different set of data than
514 * you're supposed to (e.g., not CRCing
515 * some of the data), or something such
518 if (crc != strm->adler && !state->dont_check_crc) {
519 state->err = WTAP_ERR_DECOMPRESS;
520 state->err_info = "bad CRC";
521 } else if (len != (strm->total_out & 0xffffffffL)) {
522 state->err = WTAP_ERR_DECOMPRESS;
523 state->err_info = "length field wrong";
526 state->compression = UNKNOWN; /* ready for next stream, once have is 0 */
527 g_free(state->fast_seek_cur);
528 state->fast_seek_cur = NULL;
534 gz_head(FILE_T state)
536 /* get some data in the input buffer */
537 if (state->avail_in == 0) {
538 if (fill_in_buffer(state) == -1)
540 if (state->avail_in == 0)
544 /* look for the gzip magic header bytes 31 and 139 */
546 if (state->next_in[0] == 31) {
549 if (state->avail_in == 0 && fill_in_buffer(state) == -1)
551 if (state->avail_in && state->next_in[0] == 139) {
557 /* we have a gzip header, woo hoo! */
561 /* read rest of header */
563 /* compression method (CM) */
564 if (gz_next1(state, &cm) == -1)
567 state->err = WTAP_ERR_DECOMPRESS;
568 state->err_info = "unknown compression method";
573 if (gz_next1(state, &flags) == -1)
575 if (flags & 0xe0) { /* reserved flag bits */
576 state->err = WTAP_ERR_DECOMPRESS;
577 state->err_info = "reserved flag bits set";
581 /* modification time (MTIME) */
582 if (gz_skipn(state, 4) == -1)
585 /* extra flags (XFL) */
586 if (gz_skipn(state, 1) == -1)
589 /* operating system (OS) */
590 if (gz_skipn(state, 1) == -1)
594 /* extra field - get XLEN */
595 if (gz_next2(state, &len) == -1)
598 /* skip the extra field */
599 if (gz_skipn(state, len) == -1)
604 if (gz_skipzstr(state) == -1)
609 if (gz_skipzstr(state) == -1)
614 if (gz_next2(state, &hcrc) == -1)
616 /* XXX - check the CRC? */
619 /* set up for decompression */
620 inflateReset(&(state->strm));
621 state->strm.adler = crc32(0L, Z_NULL, 0);
622 state->compression = ZLIB;
624 if (state->fast_seek) {
625 struct zlib_cur_seek_point *cur = g_malloc(sizeof(struct zlib_cur_seek_point));
627 cur->pos = cur->have = 0;
628 g_free(state->fast_seek_cur);
629 state->fast_seek_cur = cur;
630 fast_seek_header(state, state->raw_pos - state->avail_in, state->pos, GZIP_AFTER_HEADER);
635 /* not a gzip file -- save first byte (31) and fall to raw i/o */
642 /* { 0xFD, '7', 'z', 'X', 'Z', 0x00 } */
643 /* FD 37 7A 58 5A 00 */
645 if (state->fast_seek)
646 fast_seek_header(state, state->raw_pos - state->avail_in - state->have, state->pos, UNCOMPRESSED);
648 /* doing raw i/o, save start of raw data for seeking, copy any leftover
649 input to output -- this assumes that the output buffer is larger than
650 the input buffer, which also assures space for gzungetc() */
651 state->raw = state->pos;
652 state->next = state->out;
653 if (state->avail_in) {
654 memcpy(state->next + state->have, state->next_in, state->avail_in);
655 state->have += state->avail_in;
658 state->compression = UNCOMPRESSED;
662 static int /* gz_make */
663 fill_out_buffer(FILE_T state)
665 if (state->compression == UNKNOWN) { /* look for gzip header */
666 if (gz_head(state) == -1)
668 if (state->have) /* got some data from gz_head() */
671 if (state->compression == UNCOMPRESSED) { /* straight copy */
672 if (raw_read(state, state->out, state->size /* << 1 */, &(state->have)) == -1)
674 state->next = state->out;
677 else if (state->compression == ZLIB) { /* decompress */
678 zlib_read(state, state->out, state->size << 1);
685 gz_skip(FILE_T state, gint64 len)
689 /* skip over len bytes or reach end-of-file, whichever comes first */
692 /* We have stuff in the output buffer; skip over
694 n = (gint64)state->have > len ? (unsigned)len : state->have;
699 } else if (state->err) {
700 /* We have nothing in the output buffer, and
701 we have an error that may not have been
702 reported yet; that means we can't generate
703 any more data into the output buffer, so
704 return an error indication. */
706 } else if (state->eof && state->avail_in == 0) {
707 /* We have nothing in the output buffer, and
708 we're at the end of the input; just return. */
711 /* We have nothing in the output buffer, and
712 we can generate more data; get more output,
713 looking for header if required. */
714 if (fill_out_buffer(state) == -1)
721 gz_reset(FILE_T state)
723 state->have = 0; /* no output data available */
724 state->eof = 0; /* not at end of file */
725 state->compression = UNKNOWN; /* look for gzip header */
727 state->seek = 0; /* no seek request pending */
728 state->err = 0; /* clear error */
729 state->err_info = NULL;
730 state->pos = 0; /* no uncompressed data yet */
731 state->avail_in = 0; /* no input data yet */
737 #ifdef _STATBUF_ST_BLKSIZE /* XXX, _STATBUF_ST_BLKSIZE portable? */
740 int want = GZBUFSIZE;
746 /* allocate FILE_T structure to return */
747 state = g_try_malloc(sizeof *state);
751 state->fast_seek_cur = NULL;
752 state->fast_seek = NULL;
754 /* open the file with the appropriate mode (or just use fd) */
757 /* save the current position for rewinding (only if reading) */
758 state->start = ws_lseek64(state->fd, 0, SEEK_CUR);
759 if (state->start == -1) state->start = 0;
760 state->raw_pos = state->start;
762 /* initialize stream */
765 #ifdef _STATBUF_ST_BLKSIZE
766 if (fstat(fd, &st) >= 0) {
767 want = st.st_blksize;
768 /* XXX, verify result? */
772 /* allocate buffers */
773 state->in = g_try_malloc(want);
774 state->out = g_try_malloc(want << 1);
776 if (state->in == NULL || state->out == NULL) {
785 /* allocate inflate memory */
786 state->strm.zalloc = Z_NULL;
787 state->strm.zfree = Z_NULL;
788 state->strm.opaque = Z_NULL;
789 state->strm.avail_in = 0;
790 state->strm.next_in = Z_NULL;
791 if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */
799 /* for now, assume we should check the crc */
800 state->dont_check_crc = 0;
807 file_open(const char *path)
815 /* open file and do correct filename conversions.
817 XXX - do we need O_LARGEFILE? On UN*X, if we need to do
818 something special to get large file support, the configure
819 script should have set us up with the appropriate #defines,
820 so we should be getting a large-file-enabled file descriptor
821 here. Pre-Large File Summit UN*Xes, and possibly even some
822 post-LFS UN*Xes, might require O_LARGEFILE here, though.
823 If so, we should probably handle that in ws_open(). */
824 if ((fd = ws_open(path, O_RDONLY|O_BINARY, 0000)) == -1)
827 /* open file handle */
836 * If this file's name ends in ".caz", it's probably a compressed
837 * Windows Sniffer file. The compression is gzip, but they don't
838 * bother filling in the CRC; we set a flag to ignore CRC errors.
840 suffixp = strrchr(path, '.');
841 if (suffixp != NULL) {
842 if (g_ascii_strcasecmp(suffixp, ".caz") == 0)
843 ft->dont_check_crc = 1;
851 file_set_random_access(FILE_T stream, gboolean random _U_, GPtrArray *seek)
853 stream->fast_seek = seek;
857 file_seek(FILE_T file, gint64 offset, int whence, int *err)
859 struct fast_seek_point *here;
862 /* can only seek from start or relative to current position */
863 if (whence != SEEK_SET && whence != SEEK_CUR) {
864 g_assert_not_reached();
871 /* normalize offset to a SEEK_CUR specification */
872 if (whence == SEEK_SET)
875 offset += file->skip;
879 if ((here = fast_seek_find(file, file->pos + offset)) && (offset < 0 || offset > SPAN || here->compression == UNCOMPRESSED)) {
883 if (here->compression == ZLIB) {
884 #ifdef HAVE_INFLATEPRIME
885 off = here->in - (here->data.zlib.bits ? 1 : 0);
890 } else if (here->compression == GZIP_AFTER_HEADER) {
896 off2 = (file->pos + offset);
897 off = here->in + (off2 - here->out);
900 if (ws_lseek64(file->fd, off, SEEK_SET) == -1) {
904 fast_seek_reset(file);
911 file->err_info = NULL;
915 if (here->compression == ZLIB) {
916 z_stream *strm = &file->strm;
919 strm->adler = here->data.zlib.adler;
920 strm->total_out = here->data.zlib.total_out;
921 #ifdef HAVE_INFLATEPRIME
922 if (here->data.zlib.bits) {
927 if (state->err == 0) {
929 *err = WTAP_ERR_SHORT_READ;
934 (void)inflatePrime(strm, here->data.zlib.bits, ret >> (8 - here->data.zlib.bits));
937 (void)inflateSetDictionary(strm, here->data.zlib.window, ZLIB_WINSIZE);
938 file->compression = ZLIB;
939 } else if (here->compression == GZIP_AFTER_HEADER) {
940 z_stream *strm = &file->strm;
943 strm->adler = crc32(0L, Z_NULL, 0);
944 file->compression = ZLIB;
947 file->compression = here->compression;
949 offset = (file->pos + offset) - off2;
951 /* g_print("OK! %ld\n", offset); */
957 return file->pos + offset;
960 /* if within raw area while reading, just go there */
961 if (file->compression == UNCOMPRESSED && file->pos + offset >= file->raw) {
962 if (ws_lseek64(file->fd, offset - file->have, SEEK_CUR) == -1) {
966 file->raw_pos += (offset - file->have);
971 file->err_info = NULL;
977 /* calculate skip amount, rewinding if needed for back seek when reading */
980 if (offset < 0) { /* before start of file! */
984 /* rewind, then skip to offset */
986 /* back up and start over */
987 if (ws_lseek64(file->fd, file->start, SEEK_SET) == -1) {
991 fast_seek_reset(file);
992 file->raw_pos = file->start;
996 /* skip what's in output buffer (one less gzgetc() check) */
997 n = (gint64)file->have > offset ? (unsigned)offset : file->have;
1003 /* request skip (if not zero) */
1006 file->skip = offset;
1008 return file->pos + offset;
1012 file_tell(FILE_T stream)
1014 /* return position */
1015 return stream->pos + (stream->seek ? stream->skip : 0);
1019 file_tell_raw(FILE_T stream)
1021 return stream->raw_pos;
1025 file_fstat(FILE_T stream, ws_statb64 *statb, int *err)
1027 if (ws_fstat64(stream->fd, statb) == -1) {
1036 file_read(void *buf, unsigned int len, FILE_T file)
1040 /* if len is zero, avoid unnecessary operations */
1044 /* process a skip request */
1047 if (gz_skip(file, file->skip) == -1)
1051 /* get len bytes to buf, or less than len if at the end */
1055 /* We have stuff in the output buffer; copy
1057 n = file->have > len ? len : file->have;
1058 memcpy(buf, file->next, n);
1061 } else if (file->err) {
1062 /* We have nothing in the output buffer, and
1063 we have an error that may not have been
1064 reported yet; that means we can't generate
1065 any more data into the output buffer, so
1066 return an error indication. */
1068 } else if (file->eof && file->avail_in == 0) {
1069 /* We have nothing in the output buffer, and
1070 we're at the end of the input; just return
1071 with what we've gotten so far. */
1074 /* We have nothing in the output buffer, and
1075 we can generate more data; get more output,
1076 looking for header if required, and
1077 keep looping to process the new stuff
1078 in the output buffer. */
1079 if (fill_out_buffer(file) == -1)
1081 continue; /* no progress yet -- go back to memcpy() above */
1083 /* update progress */
1085 buf = (char *)buf + n;
1094 file_getc(FILE_T file)
1096 unsigned char buf[1];
1099 /* check that we're reading and that there's no error */
1103 /* try output buffer (no need to check for skip request) */
1107 return *(file->next)++;
1110 ret = file_read(buf, 1, file);
1111 return ret < 1 ? -1 : buf[0];
1115 file_gets(char *buf, int len, FILE_T file)
1121 /* check parameters */
1122 if (buf == NULL || len < 1)
1125 /* check that there's no error */
1129 /* process a skip request */
1132 if (gz_skip(file, file->skip) == -1)
1136 /* copy output bytes up to new line or len - 1, whichever comes first --
1137 append a terminating zero to the string (we don't check for a zero in
1138 the contents, let the user worry about that) */
1140 left = (unsigned)len - 1;
1142 /* assure that something is in the output buffer */
1143 if (file->have == 0) {
1144 /* We have nothing in the output buffer. */
1146 /* We have an error that may not have
1147 been reported yet; that means we
1148 can't generate any more data into
1149 the output buffer, so return an
1150 error indication. */
1153 if (fill_out_buffer(file) == -1)
1154 return NULL; /* error */
1155 if (file->have == 0) { /* end of file */
1156 if (buf == str) /* got bupkus */
1158 break; /* got something -- return it */
1162 /* look for end-of-line in current output buffer */
1163 n = file->have > left ? left : file->have;
1164 eol = memchr(file->next, '\n', n);
1166 n = (unsigned)(eol - file->next) + 1;
1168 /* copy through end-of-line, or remainder if not found */
1169 memcpy(buf, file->next, n);
1175 } while (left && eol == NULL);
1177 /* found end-of-line or out of space -- terminate string and return it */
1183 file_eof(FILE_T file)
1185 /* return end-of-file state */
1186 return (file->eof && file->avail_in == 0 && file->have == 0);
1190 * Routine to return a Wiretap error code (0 for no error, an errno
1191 * for a file error, or a WTAP_ERR_ code for other errors) for an
1192 * I/O stream. Also returns an error string for some errors.
1195 file_error(FILE_T fh, gchar **err_info)
1198 *err_info = (fh->err_info == NULL) ? NULL : g_strdup(fh->err_info);
1205 file_clearerr(FILE_T stream)
1207 /* clear error and end-of-file */
1209 stream->err_info = NULL;
1214 file_close(FILE_T file)
1218 /* free memory and close file */
1221 inflateEnd(&(file->strm));
1226 g_free(file->fast_seek_cur);
1228 file->err_info = NULL;
1230 return ws_close(fd);
1234 /* internal gzip file state data structure for writing */
1235 struct wtap_writer {
1236 int fd; /* file descriptor */
1237 gint64 pos; /* current position in uncompressed data */
1238 unsigned size; /* buffer size, zero if not allocated yet */
1239 unsigned want; /* requested buffer size, default is GZBUFSIZE */
1240 unsigned char *in; /* input buffer */
1241 unsigned char *out; /* output buffer (double-sized when reading) */
1242 unsigned char *next; /* next output data to deliver or write */
1243 int level; /* compression level */
1244 int strategy; /* compression strategy */
1245 int err; /* error code */
1246 /* zlib deflate stream */
1247 z_stream strm; /* stream structure in-place (not a pointer) */
1251 gzwfile_open(const char *path)
1257 fd = ws_open(path, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666);
1260 state = gzwfile_fdopen(fd);
1261 if (state == NULL) {
1270 gzwfile_fdopen(int fd)
1274 /* allocate wtap_writer structure to return */
1275 state = g_try_malloc(sizeof *state);
1279 state->size = 0; /* no buffers allocated yet */
1280 state->want = GZBUFSIZE; /* requested buffer size */
1282 state->level = Z_DEFAULT_COMPRESSION;
1283 state->strategy = Z_DEFAULT_STRATEGY;
1285 /* initialize stream */
1286 state->err = Z_OK; /* clear error */
1287 state->pos = 0; /* no uncompressed data yet */
1288 state->strm.avail_in = 0; /* no input data yet */
1294 /* Initialize state for writing a gzip file. Mark initialization by setting
1295 state->size to non-zero. Return -1, and set state->err, on failure;
1296 return 0 on success. */
1298 gz_init(GZWFILE_T state)
1301 z_streamp strm = &(state->strm);
1303 /* allocate input and output buffers */
1304 state->in = g_try_malloc(state->want);
1305 state->out = g_try_malloc(state->want);
1306 if (state->in == NULL || state->out == NULL) {
1309 state->err = ENOMEM;
1313 /* allocate deflate memory, set up for gzip compression */
1314 strm->zalloc = Z_NULL;
1315 strm->zfree = Z_NULL;
1316 strm->opaque = Z_NULL;
1317 ret = deflateInit2(strm, state->level, Z_DEFLATED,
1318 15 + 16, 8, state->strategy);
1322 if (ret == Z_MEM_ERROR) {
1323 /* This means "not enough memory". */
1324 state->err = ENOMEM;
1326 /* This "shouldn't happen". */
1327 state->err = WTAP_ERR_INTERNAL;
1332 /* mark state as initialized */
1333 state->size = state->want;
1335 /* initialize write buffer */
1336 strm->avail_out = state->size;
1337 strm->next_out = state->out;
1338 state->next = strm->next_out;
1342 /* Compress whatever is at avail_in and next_in and write to the output file.
1343 Return -1, and set state->err, if there is an error writing to the output
1344 file; return 0 on success.
1345 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
1346 then the deflate() state is reset to start a new gzip stream. */
1348 gz_comp(GZWFILE_T state, int flush)
1352 z_streamp strm = &(state->strm);
1354 /* allocate memory if this is the first time through */
1355 if (state->size == 0 && gz_init(state) == -1)
1358 /* run deflate() on provided input until it produces no more output */
1361 /* write out current buffer contents if full, or if flushing, but if
1362 doing Z_FINISH then don't write until we get to Z_STREAM_END */
1363 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
1364 (flush != Z_FINISH || ret == Z_STREAM_END))) {
1365 have = (unsigned)(strm->next_out - state->next);
1367 got = write(state->fd, state->next, have);
1372 if ((unsigned)got != have) {
1373 state->err = WTAP_ERR_SHORT_WRITE;
1377 if (strm->avail_out == 0) {
1378 strm->avail_out = state->size;
1379 strm->next_out = state->out;
1381 state->next = strm->next_out;
1385 have = strm->avail_out;
1386 ret = deflate(strm, flush);
1387 if (ret == Z_STREAM_ERROR) {
1388 /* This "shouldn't happen". */
1389 state->err = WTAP_ERR_INTERNAL;
1392 have -= strm->avail_out;
1395 /* if that completed a deflate stream, allow another to start */
1396 if (flush == Z_FINISH)
1399 /* all done, no errors */
1403 /* Write out len bytes from buf. Return 0, and set state->err, on
1404 failure or on an attempt to write 0 bytes (in which case state->err
1405 is Z_OK); return the number of bytes written on success. */
1407 gzwfile_write(GZWFILE_T state, const void *buf, unsigned len)
1413 strm = &(state->strm);
1415 /* check that there's no error */
1416 if (state->err != Z_OK)
1419 /* if len is zero, avoid unnecessary operations */
1423 /* allocate memory if this is the first time through */
1424 if (state->size == 0 && gz_init(state) == -1)
1427 /* for small len, copy to input buffer, otherwise compress directly */
1428 if (len < state->size) {
1429 /* copy to input buffer, compress when full */
1431 if (strm->avail_in == 0)
1432 strm->next_in = state->in;
1433 n = state->size - strm->avail_in;
1436 memcpy(strm->next_in + strm->avail_in, buf, n);
1437 strm->avail_in += n;
1439 buf = (char *)buf + n;
1441 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
1446 /* consume whatever's left in the input buffer */
1447 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
1450 /* directly compress user buffer to file */
1451 strm->avail_in = len;
1452 strm->next_in = (voidp)buf;
1454 if (gz_comp(state, Z_NO_FLUSH) == -1)
1458 /* input was all buffered or compressed (put will fit in int) */
1462 /* Flush out what we've written so far. Returns -1, and sets state->err,
1463 on failure; returns 0 on success. */
1465 gzwfile_flush(GZWFILE_T state)
1467 /* check that there's no error */
1468 if (state->err != Z_OK)
1471 /* compress remaining data with Z_SYNC_FLUSH */
1472 gz_comp(state, Z_SYNC_FLUSH);
1473 if (state->err != Z_OK)
1478 /* Flush out all data written, and close the file. Returns a Wiretap
1479 error on failure; returns 0 on success. */
1481 gzwfile_close(GZWFILE_T state)
1485 /* flush, free memory, and close file */
1486 if (gz_comp(state, Z_FINISH) == -1 && ret == 0)
1488 (void)deflateEnd(&(state->strm));
1492 if (close(state->fd) == -1 && ret == 0)
1499 gzwfile_geterr(GZWFILE_T state)