block->options is never null; don't check for it.
[metze/wireshark/wip.git] / wiretap / file_wrappers.c
1 /* file_wrappers.c
2  *
3  * Wiretap Library
4  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 /* file_access interface based heavily on zlib gzread.c and gzlib.c from zlib
22  * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
23  * under licence:
24  *
25  *  This software is provided 'as-is', without any express or implied
26  *  warranty.  In no event will the authors be held liable for any damages
27  *  arising from the use of this software.
28  *
29  *  Permission is granted to anyone to use this software for any purpose,
30  *  including commercial applications, and to alter it and redistribute it
31  *  freely, subject to the following restrictions:
32  *
33  *  1. The origin of this software must not be misrepresented; you must not
34  *     claim that you wrote the original software. If you use this software
35  *     in a product, an acknowledgment in the product documentation would be
36  *     appreciated but is not required.
37  *  2. Altered source versions must be plainly marked as such, and must not be
38  *     misrepresented as being the original software.
39  *  3. This notice may not be removed or altered from any source distribution.
40  */
41
42 #include <config.h>
43
44 #include <errno.h>
45 #include <string.h>
46 #include "wtap-int.h"
47 #include "file_wrappers.h"
48 #include <wsutil/file_util.h>
49
50 #ifdef HAVE_ZLIB
51 #define ZLIB_CONST
52 #include <zlib.h>
53 #endif /* HAVE_ZLIB */
54
55 /*
56  * See RFC 1952 for a description of the gzip file format.
57  *
58  * Some other compressed file formats we might want to support:
59  *
60  *      XZ format: http://tukaani.org/xz/
61  *
62  *      Bzip2 format: http://bzip.org/
63  */
64
65 /*
66  * List of extensions for compressed files.
67  * If we add support for more compressed file types, this table
68  * might be expanded to include routines to handle the various
69  * compression types.
70  */
71 const char *compressed_file_extension_table[] = {
72 #ifdef HAVE_ZLIB
73     "gz",
74 #endif
75     NULL
76 };
77
78 /* #define GZBUFSIZE 8192 */
79 #define GZBUFSIZE 4096
80
81 /* values for wtap_reader compression */
82 typedef enum {
83     UNKNOWN,       /* unknown - look for a gzip header */
84     UNCOMPRESSED,  /* uncompressed - copy input directly */
85 #ifdef HAVE_ZLIB
86     ZLIB,          /* decompress a zlib stream */
87     GZIP_AFTER_HEADER
88 #endif
89 } compression_t;
90
91 struct wtap_reader {
92     int fd;                    /* file descriptor */
93     gint64 raw_pos;            /* current position in file (just to not call lseek()) */
94     gint64 pos;                /* current position in uncompressed data */
95     guint size;                /* buffer size */
96     unsigned char *in;         /* input buffer */
97     unsigned char *out;        /* output buffer (double-sized when reading) */
98     unsigned char *next;       /* next output data to deliver or write */
99
100     guint have;                /* amount of output data unused at next */
101     gboolean eof;              /* TRUE if end of input file reached */
102     gint64 start;              /* where the gzip data started, for rewinding */
103     gint64 raw;                /* where the raw data started, for seeking */
104     compression_t compression; /* type of compression, if any */
105     gboolean is_compressed;    /* FALSE if completely uncompressed, TRUE otherwise */
106     /* seek request */
107     gint64 skip;               /* amount to skip (already rewound if backwards) */
108     gboolean seek_pending;     /* TRUE if seek request pending */
109     /* error information */
110     int err;                   /* error code */
111     const char *err_info;      /* additional error information string for some errors */
112
113     guint avail_in;            /* number of bytes available at next_in */
114     unsigned char *next_in;    /* next input byte */
115 #ifdef HAVE_ZLIB
116     /* zlib inflate stream */
117     z_stream strm;             /* stream structure in-place (not a pointer) */
118     gboolean dont_check_crc;   /* TRUE if we aren't supposed to check the CRC */
119 #endif
120     /* fast seeking */
121     GPtrArray *fast_seek;
122     void *fast_seek_cur;
123 };
124
125 static int     /* gz_load */
126 raw_read(FILE_T state, unsigned char *buf, unsigned int count, guint *have)
127 {
128     ssize_t ret;
129
130     *have = 0;
131     do {
132         ret = ws_read(state->fd, buf + *have, count - *have);
133         if (ret <= 0)
134             break;
135         *have += (unsigned)ret;
136         state->raw_pos += ret;
137     } while (*have < count);
138     if (ret < 0) {
139         state->err = errno;
140         state->err_info = NULL;
141         return -1;
142     }
143     if (ret == 0)
144         state->eof = TRUE;
145     return 0;
146 }
147
148 static int /* gz_avail */
149 fill_in_buffer(FILE_T state)
150 {
151     if (state->err)
152         return -1;
153     if (state->eof == 0) {
154         if (raw_read(state, state->in, state->size, &(state->avail_in)) == -1)
155             return -1;
156         state->next_in = state->in;
157     }
158     return 0;
159 }
160
161 #define ZLIB_WINSIZE 32768
162
163 struct fast_seek_point {
164     gint64 out;         /* corresponding offset in uncompressed data */
165     gint64 in;          /* offset in input file of first full byte */
166
167     compression_t compression;
168     union {
169         struct {
170 #ifdef HAVE_INFLATEPRIME
171             int bits;   /* number of bits (1-7) from byte at in - 1, or 0 */
172 #endif
173             unsigned char window[ZLIB_WINSIZE]; /* preceding 32K of uncompressed data */
174
175             /* be gentle with Z_STREAM_END, 8 bytes more... Another solution would be to comment checks out */
176             guint32 adler;
177             guint32 total_out;
178         } zlib;
179     } data;
180 };
181
182 struct zlib_cur_seek_point {
183     unsigned char window[ZLIB_WINSIZE]; /* preceding 32K of uncompressed data */
184     unsigned int pos;
185     unsigned int have;
186 };
187
188 #define SPAN G_GINT64_CONSTANT(1048576)
189 static struct fast_seek_point *
190 fast_seek_find(FILE_T file, gint64 pos)
191 {
192     struct fast_seek_point *smallest = NULL;
193     struct fast_seek_point *item;
194     guint low, i, max;
195
196     if (!file->fast_seek)
197         return NULL;
198
199     for (low = 0, max = file->fast_seek->len; low < max; ) {
200         i = (low + max) / 2;
201         item = (struct fast_seek_point *)file->fast_seek->pdata[i];
202
203         if (pos < item->out)
204             max = i;
205         else if (pos > item->out) {
206             smallest = item;
207             low = i + 1;
208         } else {
209             return item;
210         }
211     }
212     return smallest;
213 }
214
215 static void
216 fast_seek_header(FILE_T file, gint64 in_pos, gint64 out_pos,
217                  compression_t compression)
218 {
219     struct fast_seek_point *item = NULL;
220
221     if (file->fast_seek->len != 0)
222         item = (struct fast_seek_point *)file->fast_seek->pdata[file->fast_seek->len - 1];
223
224     if (!item || item->out < out_pos) {
225         struct fast_seek_point *val = g_new(struct fast_seek_point,1);
226         val->in = in_pos;
227         val->out = out_pos;
228         val->compression = compression;
229
230         g_ptr_array_add(file->fast_seek, val);
231     }
232 }
233
234 static void
235 fast_seek_reset(
236 #ifdef HAVE_ZLIB
237     FILE_T state)
238 #else
239     FILE_T state _U_)
240 #endif
241 {
242 #ifdef HAVE_ZLIB
243     if (state->compression == ZLIB && state->fast_seek_cur) {
244         struct zlib_cur_seek_point *cur = (struct zlib_cur_seek_point *) state->fast_seek_cur;
245
246         cur->have = 0;
247     }
248 #endif
249 }
250
251 #ifdef HAVE_ZLIB
252
253 /* Get next byte from input, or -1 if end or error.
254  *
255  * Note:
256  *
257  *      1) errors from raw_read(), and thus from fill_in_buffer(), are
258  *      "sticky", and fill_in_buffer() won't do any reading if there's
259  *      an error;
260  *
261  *      2) GZ_GETC() returns -1 on an EOF;
262  *
263  * so it's safe to make multiple GZ_GETC() calls and only check the
264  * last one for an error. */
265 #define GZ_GETC() ((state->avail_in == 0 && fill_in_buffer(state) == -1) ? -1 : \
266                    (state->avail_in == 0 ? -1 :                         \
267                     (state->avail_in--, *(state->next_in)++)))
268
269 /* Get a one-byte integer and return 0 on success and the value in *ret.
270    Otherwise -1 is returned, state->err is set, and *ret is not modified. */
271 static int
272 gz_next1(FILE_T state, guint8 *ret)
273 {
274     int ch;
275
276     ch = GZ_GETC();
277     if (ch == -1) {
278         if (state->err == 0) {
279             /* EOF */
280             state->err = WTAP_ERR_SHORT_READ;
281             state->err_info = NULL;
282         }
283         return -1;
284     }
285     *ret = ch;
286     return 0;
287 }
288
289 /* Get a two-byte little-endian integer and return 0 on success and the value
290    in *ret.  Otherwise -1 is returned, state->err is set, and *ret is not
291    modified. */
292 static int
293 gz_next2(FILE_T state, guint16 *ret)
294 {
295     guint16 val;
296     int ch;
297
298     val = GZ_GETC();
299     ch = GZ_GETC();
300     if (ch == -1) {
301         if (state->err == 0) {
302             /* EOF */
303             state->err = WTAP_ERR_SHORT_READ;
304             state->err_info = NULL;
305         }
306         return -1;
307     }
308     val += (guint16)ch << 8;
309     *ret = val;
310     return 0;
311 }
312
313 /* Get a four-byte little-endian integer and return 0 on success and the value
314    in *ret.  Otherwise -1 is returned, state->err is set, and *ret is not
315    modified. */
316 static int
317 gz_next4(FILE_T state, guint32 *ret)
318 {
319     guint32 val;
320     int ch;
321
322     val = GZ_GETC();
323     val += (unsigned)GZ_GETC() << 8;
324     val += (guint32)GZ_GETC() << 16;
325     ch = GZ_GETC();
326     if (ch == -1) {
327         if (state->err == 0) {
328             /* EOF */
329             state->err = WTAP_ERR_SHORT_READ;
330             state->err_info = NULL;
331         }
332         return -1;
333     }
334     val += (guint32)ch << 24;
335     *ret = val;
336     return 0;
337 }
338
339 /* Skip the specified number of bytes and return 0 on success.  Otherwise -1
340    is returned. */
341 static int
342 gz_skipn(FILE_T state, size_t n)
343 {
344     while (n != 0) {
345         if (GZ_GETC() == -1) {
346             if (state->err == 0) {
347                 /* EOF */
348                 state->err = WTAP_ERR_SHORT_READ;
349                 state->err_info = NULL;
350             }
351             return -1;
352         }
353         n--;
354     }
355     return 0;
356 }
357
358 /* Skip a null-terminated string and return 0 on success.  Otherwise -1
359    is returned. */
360 static int
361 gz_skipzstr(FILE_T state)
362 {
363     int ch;
364
365     /* It's null-terminated, so scan until we read a byte with
366        the value 0 or get an error. */
367     while ((ch = GZ_GETC()) > 0)
368         ;
369     if (ch == -1) {
370         if (state->err == 0) {
371             /* EOF */
372             state->err = WTAP_ERR_SHORT_READ;
373             state->err_info = NULL;
374         }
375         return -1;
376     }
377     return 0;
378 }
379
380 static void
381 zlib_fast_seek_add(FILE_T file, struct zlib_cur_seek_point *point, int bits, gint64 in_pos, gint64 out_pos)
382 {
383     /* it's for sure after gzip header, so file->fast_seek->len != 0 */
384     struct fast_seek_point *item = (struct fast_seek_point *)file->fast_seek->pdata[file->fast_seek->len - 1];
385
386 #ifndef HAVE_INFLATEPRIME
387     if (bits)
388         return;
389 #endif
390
391     /* 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)
392      *      Inserting value in middle of sorted array is expensive, so we want to add only in the end.
393      *      It's not big deal, cause first-read don't usually invoke seeking
394      */
395     if (item->out + SPAN < out_pos) {
396         struct fast_seek_point *val = g_new(struct fast_seek_point,1);
397         val->in = in_pos;
398         val->out = out_pos;
399         val->compression = ZLIB;
400 #ifdef HAVE_INFLATEPRIME
401         val->data.zlib.bits = bits;
402 #endif
403         if (point->pos != 0) {
404             unsigned int left = ZLIB_WINSIZE - point->pos;
405
406             memcpy(val->data.zlib.window, point->window + point->pos, left);
407             memcpy(val->data.zlib.window + left, point->window, point->pos);
408         } else
409             memcpy(val->data.zlib.window, point->window, ZLIB_WINSIZE);
410
411         /*
412          * XXX - strm.adler is a uLong in at least some versions
413          * of zlib, and uLong is an unsigned long in at least
414          * some of those versions, which means it's 64-bit
415          * on LP64 platforms, even though the checksum is
416          * 32-bit.  We assume the actual Adler checksum
417          * is in the lower 32 bits of strm.adler; as the
418          * checksum in the file is only 32 bits, we save only
419          * those lower 32 bits, and cast away any additional
420          * bits to squelch warnings.
421          *
422          * The same applies to strm.total_out.
423          */
424         val->data.zlib.adler = (guint32) file->strm.adler;
425         val->data.zlib.total_out = (guint32) file->strm.total_out;
426         g_ptr_array_add(file->fast_seek, val);
427     }
428 }
429
430 static void /* gz_decomp */
431 zlib_read(FILE_T state, unsigned char *buf, unsigned int count)
432 {
433     int ret = 0;        /* XXX */
434     guint32 crc, len;
435     z_streamp strm = &(state->strm);
436
437     unsigned char *buf2 = buf;
438     unsigned int count2 = count;
439
440     strm->avail_out = count;
441     strm->next_out = buf;
442
443     /* fill output buffer up to end of deflate stream or error */
444     do {
445         /* get more input for inflate() */
446         if (state->avail_in == 0 && fill_in_buffer(state) == -1)
447             break;
448         if (state->avail_in == 0) {
449             /* EOF */
450             state->err = WTAP_ERR_SHORT_READ;
451             state->err_info = NULL;
452             break;
453         }
454
455         strm->avail_in = state->avail_in;
456         strm->next_in = state->next_in;
457         /* decompress and handle errors */
458 #ifdef Z_BLOCK
459         ret = inflate(strm, Z_BLOCK);
460 #else
461         ret = inflate(strm, Z_NO_FLUSH);
462 #endif
463         state->avail_in = strm->avail_in;
464 #ifdef z_const
465 DIAG_OFF(cast-qual)
466         state->next_in = (unsigned char *)strm->next_in;
467 DIAG_ON(cast-qual)
468 #else
469         state->next_in = strm->next_in;
470 #endif
471         if (ret == Z_STREAM_ERROR) {
472             state->err = WTAP_ERR_DECOMPRESS;
473             state->err_info = strm->msg;
474             break;
475         }
476         if (ret == Z_NEED_DICT) {
477             state->err = WTAP_ERR_DECOMPRESS;
478             state->err_info = "preset dictionary needed";
479             break;
480         }
481         if (ret == Z_MEM_ERROR) {
482             /* This means "not enough memory". */
483             state->err = ENOMEM;
484             state->err_info = NULL;
485             break;
486         }
487         if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
488             state->err = WTAP_ERR_DECOMPRESS;
489             state->err_info = strm->msg;
490             break;
491         }
492         /*
493          * XXX - Z_BUF_ERROR?
494          */
495
496         strm->adler = crc32(strm->adler, buf2, count2 - strm->avail_out);
497 #ifdef Z_BLOCK
498         if (state->fast_seek_cur) {
499             struct zlib_cur_seek_point *cur = (struct zlib_cur_seek_point *) state->fast_seek_cur;
500             unsigned int ready = count2 - strm->avail_out;
501
502             if (ready < ZLIB_WINSIZE) {
503                 guint left = ZLIB_WINSIZE - cur->pos;
504
505                 if (ready >= left) {
506                     memcpy(cur->window + cur->pos, buf2, left);
507                     if (ready != left)
508                         memcpy(cur->window, buf2 + left, ready - left);
509
510                     cur->pos = ready - left;
511                     cur->have += ready;
512                 } else {
513                     memcpy(cur->window + cur->pos, buf2, ready);
514                     cur->pos += ready;
515                     cur->have += ready;
516                 }
517
518                 if (cur->have >= ZLIB_WINSIZE)
519                     cur->have = ZLIB_WINSIZE;
520
521             } else {
522                 memcpy(cur->window, buf2 + (ready - ZLIB_WINSIZE), ZLIB_WINSIZE);
523                 cur->pos = 0;
524                 cur->have = ZLIB_WINSIZE;
525             }
526
527             if (cur->have >= ZLIB_WINSIZE && ret != Z_STREAM_END && (strm->data_type & 128) && !(strm->data_type & 64))
528                 zlib_fast_seek_add(state, cur, (strm->data_type & 7), state->raw_pos - strm->avail_in, state->pos + (count - strm->avail_out));
529         }
530 #endif
531         buf2 = (buf2 + count2 - strm->avail_out);
532         count2 = strm->avail_out;
533
534     } while (strm->avail_out && ret != Z_STREAM_END);
535
536     /* update available output and crc check value */
537     state->next = buf;
538     state->have = count - strm->avail_out;
539
540     /* Check gzip trailer if at end of deflate stream.
541        We don't fail immediately here, we just set an error
542        indication, so that we try to process what data we
543        got before the error.  The next attempt to read
544        something past that data will get the error. */
545     if (ret == Z_STREAM_END) {
546         if (gz_next4(state, &crc) != -1 &&
547             gz_next4(state, &len) != -1) {
548             if (crc != strm->adler && !state->dont_check_crc) {
549                 state->err = WTAP_ERR_DECOMPRESS;
550                 state->err_info = "bad CRC";
551             } else if (len != (strm->total_out & 0xffffffffUL)) {
552                 state->err = WTAP_ERR_DECOMPRESS;
553                 state->err_info = "length field wrong";
554             }
555         }
556         state->compression = UNKNOWN;      /* ready for next stream, once have is 0 */
557         g_free(state->fast_seek_cur);
558         state->fast_seek_cur = NULL;
559     }
560 }
561 #endif
562
563 static int
564 gz_head(FILE_T state)
565 {
566     /* get some data in the input buffer */
567     if (state->avail_in == 0) {
568         if (fill_in_buffer(state) == -1)
569             return -1;
570         if (state->avail_in == 0)
571             return 0;
572     }
573
574     /* look for the gzip magic header bytes 31 and 139 */
575 #ifdef HAVE_ZLIB
576     if (state->next_in[0] == 31) {
577         state->avail_in--;
578         state->next_in++;
579         if (state->avail_in == 0 && fill_in_buffer(state) == -1)
580             return -1;
581         if (state->avail_in && state->next_in[0] == 139) {
582             guint8 cm;
583             guint8 flags;
584             guint16 len;
585             guint16 hcrc;
586
587             /* we have a gzip header, woo hoo! */
588             state->avail_in--;
589             state->next_in++;
590
591             /* read rest of header */
592
593             /* compression method (CM) */
594             if (gz_next1(state, &cm) == -1)
595                 return -1;
596             if (cm != 8) {
597                 state->err = WTAP_ERR_DECOMPRESS;
598                 state->err_info = "unknown compression method";
599                 return -1;
600             }
601
602             /* flags (FLG) */
603             if (gz_next1(state, &flags) == -1)
604                 return -1;
605             if (flags & 0xe0) {     /* reserved flag bits */
606                 state->err = WTAP_ERR_DECOMPRESS;
607                 state->err_info = "reserved flag bits set";
608                 return -1;
609             }
610
611             /* modification time (MTIME) */
612             if (gz_skipn(state, 4) == -1)
613                 return -1;
614
615             /* extra flags (XFL) */
616             if (gz_skipn(state, 1) == -1)
617                 return -1;
618
619             /* operating system (OS) */
620             if (gz_skipn(state, 1) == -1)
621                 return -1;
622
623             if (flags & 4) {
624                 /* extra field - get XLEN */
625                 if (gz_next2(state, &len) == -1)
626                     return -1;
627
628                 /* skip the extra field */
629                 if (gz_skipn(state, len) == -1)
630                     return -1;
631             }
632             if (flags & 8) {
633                 /* file name */
634                 if (gz_skipzstr(state) == -1)
635                     return -1;
636             }
637             if (flags & 16) {
638                 /* comment */
639                 if (gz_skipzstr(state) == -1)
640                     return -1;
641             }
642             if (flags & 2) {
643                 /* header crc */
644                 if (gz_next2(state, &hcrc) == -1)
645                     return -1;
646                 /* XXX - check the CRC? */
647             }
648
649             /* set up for decompression */
650             inflateReset(&(state->strm));
651             state->strm.adler = crc32(0L, Z_NULL, 0);
652             state->compression = ZLIB;
653             state->is_compressed = TRUE;
654 #ifdef Z_BLOCK
655             if (state->fast_seek) {
656                 struct zlib_cur_seek_point *cur = g_new(struct zlib_cur_seek_point,1);
657
658                 cur->pos = cur->have = 0;
659                 g_free(state->fast_seek_cur);
660                 state->fast_seek_cur = cur;
661                 fast_seek_header(state, state->raw_pos - state->avail_in, state->pos, GZIP_AFTER_HEADER);
662             }
663 #endif
664             return 0;
665         }
666         else {
667             /* not a gzip file -- save first byte (31) and fall to raw i/o */
668             state->out[0] = 31;
669             state->have = 1;
670         }
671     }
672 #endif
673 #ifdef HAVE_LIBXZ
674     /* { 0xFD, '7', 'z', 'X', 'Z', 0x00 } */
675     /* FD 37 7A 58 5A 00 */
676 #endif
677     if (state->fast_seek)
678         fast_seek_header(state, state->raw_pos - state->avail_in - state->have, state->pos, UNCOMPRESSED);
679
680     /* doing raw i/o, save start of raw data for seeking, copy any leftover
681        input to output -- this assumes that the output buffer is larger than
682        the input buffer, which also assures space for gzungetc() */
683     state->raw = state->pos;
684     state->next = state->out;
685     if (state->avail_in) {
686         memcpy(state->next + state->have, state->next_in, state->avail_in);
687         state->have += state->avail_in;
688         state->avail_in = 0;
689     }
690     state->compression = UNCOMPRESSED;
691     return 0;
692 }
693
694 static int /* gz_make */
695 fill_out_buffer(FILE_T state)
696 {
697     if (state->compression == UNKNOWN) {           /* look for gzip header */
698         if (gz_head(state) == -1)
699             return -1;
700         if (state->have)                /* got some data from gz_head() */
701             return 0;
702     }
703     if (state->compression == UNCOMPRESSED) {           /* straight copy */
704         if (raw_read(state, state->out, state->size /* << 1 */, &(state->have)) == -1)
705             return -1;
706         state->next = state->out;
707     }
708 #ifdef HAVE_ZLIB
709     else if (state->compression == ZLIB) {      /* decompress */
710         zlib_read(state, state->out, state->size << 1);
711     }
712 #endif
713     return 0;
714 }
715
716 static int
717 gz_skip(FILE_T state, gint64 len)
718 {
719     guint n;
720
721     /* skip over len bytes or reach end-of-file, whichever comes first */
722     while (len)
723         if (state->have) {
724             /* We have stuff in the output buffer; skip over
725                it. */
726             n = (gint64)state->have > len ? (unsigned)len : state->have;
727             state->have -= n;
728             state->next += n;
729             state->pos += n;
730             len -= n;
731         } else if (state->err) {
732             /* We have nothing in the output buffer, and
733                we have an error that may not have been
734                reported yet; that means we can't generate
735                any more data into the output buffer, so
736                return an error indication. */
737             return -1;
738         } else if (state->eof && state->avail_in == 0) {
739             /* We have nothing in the output buffer, and
740                we're at the end of the input; just return. */
741             break;
742         } else {
743             /* We have nothing in the output buffer, and
744                we can generate more data; get more output,
745                looking for header if required. */
746             if (fill_out_buffer(state) == -1)
747                 return -1;
748         }
749     return 0;
750 }
751
752 static void
753 gz_reset(FILE_T state)
754 {
755     state->have = 0;              /* no output data available */
756     state->eof = FALSE;           /* not at end of file */
757     state->compression = UNKNOWN; /* look for gzip header */
758
759     state->seek_pending = FALSE;  /* no seek request pending */
760     state->err = 0;               /* clear error */
761     state->err_info = NULL;
762     state->pos = 0;               /* no uncompressed data yet */
763     state->avail_in = 0;          /* no input data yet */
764 }
765
766 FILE_T
767 file_fdopen(int fd)
768 {
769 #ifdef _STATBUF_ST_BLKSIZE      /* XXX, _STATBUF_ST_BLKSIZE portable? */
770     ws_statb64 st;
771 #endif
772     int want = GZBUFSIZE;
773     FILE_T state;
774
775     if (fd == -1)
776         return NULL;
777
778     /* allocate FILE_T structure to return */
779     state = (FILE_T)g_try_malloc(sizeof *state);
780     if (state == NULL)
781         return NULL;
782
783     state->fast_seek_cur = NULL;
784     state->fast_seek = NULL;
785
786     /* open the file with the appropriate mode (or just use fd) */
787     state->fd = fd;
788
789     /* we don't yet know whether it's compressed */
790     state->is_compressed = FALSE;
791
792     /* save the current position for rewinding (only if reading) */
793     state->start = ws_lseek64(state->fd, 0, SEEK_CUR);
794     if (state->start == -1) state->start = 0;
795     state->raw_pos = state->start;
796
797     /* initialize stream */
798     gz_reset(state);
799
800 #ifdef _STATBUF_ST_BLKSIZE
801     if (ws_fstat64(fd, &st) >= 0) {
802         /*
803          * Yes, st_blksize can be bigger than an int; apparently,
804          * it's a long on LP64 Linux, for example.
805          *
806          * If the value is too big to fit into an int, just
807          * use the default.
808          */
809         if (st.st_blksize <= G_MAXINT)
810             want = (int)st.st_blksize;
811         /* XXX, verify result? */
812     }
813 #endif
814
815     /* allocate buffers */
816     state->in = (unsigned char *)g_try_malloc(want);
817     state->out = (unsigned char *)g_try_malloc(want << 1);
818     state->size = want;
819     if (state->in == NULL || state->out == NULL) {
820         g_free(state->out);
821         g_free(state->in);
822         g_free(state);
823         errno = ENOMEM;
824         return NULL;
825     }
826
827 #ifdef HAVE_ZLIB
828     /* allocate inflate memory */
829     state->strm.zalloc = Z_NULL;
830     state->strm.zfree = Z_NULL;
831     state->strm.opaque = Z_NULL;
832     state->strm.avail_in = 0;
833     state->strm.next_in = Z_NULL;
834     if (inflateInit2(&(state->strm), -15) != Z_OK) {    /* raw inflate */
835         g_free(state->out);
836         g_free(state->in);
837         g_free(state);
838         errno = ENOMEM;
839         return NULL;
840     }
841
842     /* for now, assume we should check the crc */
843     state->dont_check_crc = FALSE;
844 #endif
845     /* return stream */
846     return state;
847 }
848
849 FILE_T
850 file_open(const char *path)
851 {
852     int fd;
853     FILE_T ft;
854 #ifdef HAVE_ZLIB
855     const char *suffixp;
856 #endif
857
858     /* open file and do correct filename conversions.
859
860        XXX - do we need O_LARGEFILE?  On UN*X, if we need to do
861        something special to get large file support, the configure
862        script should have set us up with the appropriate #defines,
863        so we should be getting a large-file-enabled file descriptor
864        here.  Pre-Large File Summit UN*Xes, and possibly even some
865        post-LFS UN*Xes, might require O_LARGEFILE here, though.
866        If so, we should probably handle that in ws_open(). */
867     if ((fd = ws_open(path, O_RDONLY|O_BINARY, 0000)) == -1)
868         return NULL;
869
870     /* open file handle */
871     ft = file_fdopen(fd);
872     if (ft == NULL) {
873         ws_close(fd);
874         return NULL;
875     }
876
877 #ifdef HAVE_ZLIB
878     /*
879      * If this file's name ends in ".caz", it's probably a compressed
880      * Windows Sniffer file.  The compression is gzip, but if we
881      * process the CRC as specified by RFC 1952, the computed CRC
882      * doesn't match the stored CRC.
883      *
884      * Compressed Windows Sniffer files don't all have the same CRC
885      * value; is it just random crap, or are they running the CRC on
886      * a different set of data than you're supposed to (e.g., not
887      * CRCing some of the data), or something such as that?
888      *
889      * For now, we just set a flag to ignore CRC errors.
890      */
891     suffixp = strrchr(path, '.');
892     if (suffixp != NULL) {
893         if (g_ascii_strcasecmp(suffixp, ".caz") == 0)
894             ft->dont_check_crc = TRUE;
895     }
896 #endif
897
898     return ft;
899 }
900
901 void
902 file_set_random_access(FILE_T stream, gboolean random_flag _U_, GPtrArray *seek)
903 {
904     stream->fast_seek = seek;
905 }
906
907 gint64
908 file_seek(FILE_T file, gint64 offset, int whence, int *err)
909 {
910     struct fast_seek_point *here;
911     guint n;
912
913     if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) {
914         g_assert_not_reached();
915 /*
916  *err = EINVAL;
917  return -1;
918 */
919     }
920
921     /* Normalize offset to a SEEK_CUR specification */
922     if (whence == SEEK_END) {
923         /* Try skip until end-of-file */
924         if (gz_skip(file, G_MAXINT64) == -1) {
925             *err = file->err;
926             return -1;
927         }
928         if (offset == 0) {
929             /* We are done */
930             return file->pos;
931         }
932     } else if (whence == SEEK_SET)
933         offset -= file->pos;
934     else if (file->seek_pending)
935         offset += file->skip;
936     file->seek_pending = FALSE;
937
938     /*
939      * Are we seeking backwards and, if so, do we have data in the buffer?
940      */
941     if (offset < 0 && file->next) {
942         /*
943          * Yes.
944          *
945          * This is guaranteed to fit in an unsigned int.
946          * To squelch compiler warnings, we cast the
947          * result.
948          */
949         guint had = (unsigned)(file->next - file->out);
950
951         /*
952          * Do we have enough data before the current position in
953          * the buffer that we can seek backwards within the buffer?
954          */
955         if (-offset <= had) {
956             /*
957              * Yes.
958              *
959              * Offset is negative, so -offset is
960              * non-negative, and -offset is
961              * <= an unsigned and thus fits in an
962              * unsigned.  Get that value and
963              * adjust appropriately.
964              *
965              * (Casting offset to unsigned makes
966              * it positive, which is not what we
967              * would want, so we cast -offset
968              * instead.)
969              */
970             guint adjustment = (unsigned)(-offset);
971             file->have += adjustment;
972             file->next -= adjustment;
973             file->pos -= adjustment;
974             return file->pos;
975         }
976     }
977
978     /*
979      * No.  Do we have "fast seek" data for the location to which we
980      * will be seeking?
981      *
982      * XXX, profile
983      */
984     if ((here = fast_seek_find(file, file->pos + offset)) && (offset < 0 || offset > SPAN || here->compression == UNCOMPRESSED)) {
985         gint64 off, off2;
986
987         /*
988          * Yes.  Use that data to do the seek.
989          * Note that this will be true only if file_set_random_access()
990          * has been called on this file, which should never be the case
991          * for a pipe.
992          */
993 #ifdef HAVE_ZLIB
994         if (here->compression == ZLIB) {
995 #ifdef HAVE_INFLATEPRIME
996             off = here->in - (here->data.zlib.bits ? 1 : 0);
997 #else
998             off = here->in;
999 #endif
1000             off2 = here->out;
1001         } else if (here->compression == GZIP_AFTER_HEADER) {
1002             off = here->in;
1003             off2 = here->out;
1004         } else
1005 #endif
1006         {
1007             off2 = (file->pos + offset);
1008             off = here->in + (off2 - here->out);
1009         }
1010
1011         if (ws_lseek64(file->fd, off, SEEK_SET) == -1) {
1012             *err = errno;
1013             return -1;
1014         }
1015         fast_seek_reset(file);
1016
1017         file->raw_pos = off;
1018         file->have = 0;
1019         file->eof = FALSE;
1020         file->seek_pending = FALSE;
1021         file->err = 0;
1022         file->err_info = NULL;
1023         file->avail_in = 0;
1024
1025 #ifdef HAVE_ZLIB
1026         if (here->compression == ZLIB) {
1027             z_stream *strm = &file->strm;
1028
1029             inflateReset(strm);
1030             strm->adler = here->data.zlib.adler;
1031             strm->total_out = here->data.zlib.total_out;
1032 #ifdef HAVE_INFLATEPRIME
1033             if (here->data.zlib.bits) {
1034                 FILE_T state = file;
1035                 int ret = GZ_GETC();
1036
1037                 if (ret == -1) {
1038                     if (state->err == 0) {
1039                         /* EOF */
1040                         *err = WTAP_ERR_SHORT_READ;
1041                     } else
1042                         *err = state->err;
1043                     return -1;
1044                 }
1045                 (void)inflatePrime(strm, here->data.zlib.bits, ret >> (8 - here->data.zlib.bits));
1046             }
1047 #endif
1048             (void)inflateSetDictionary(strm, here->data.zlib.window, ZLIB_WINSIZE);
1049             file->compression = ZLIB;
1050         } else if (here->compression == GZIP_AFTER_HEADER) {
1051             z_stream *strm = &file->strm;
1052
1053             inflateReset(strm);
1054             strm->adler = crc32(0L, Z_NULL, 0);
1055             file->compression = ZLIB;
1056         } else
1057 #endif
1058             file->compression = here->compression;
1059
1060         offset = (file->pos + offset) - off2;
1061         file->pos = off2;
1062         /* g_print("OK! %ld\n", offset); */
1063
1064         if (offset) {
1065             file->seek_pending = TRUE;
1066             file->skip = offset;
1067         }
1068         return file->pos + offset;
1069     }
1070
1071     /*
1072      * Is this an uncompressed file, are we within the raw area,
1073      * are we either seeking backwards or seeking past the end
1074      * of the buffer, and are we set up for random access with
1075      * file_set_random_access()?
1076      *
1077      * Again, note that this will never be true on a pipe, as
1078      * file_set_random_access() should never be called if we're
1079      * reading from a pipe.
1080      */
1081     if (file->compression == UNCOMPRESSED && file->pos + offset >= file->raw
1082         && (offset < 0 || offset >= file->have)
1083         && (file->fast_seek))
1084     {
1085         /*
1086          * Yes.  Just seek there within the file.
1087          */
1088         if (ws_lseek64(file->fd, offset - file->have, SEEK_CUR) == -1) {
1089             *err = errno;
1090             return -1;
1091         }
1092         file->raw_pos += (offset - file->have);
1093         file->have = 0;
1094         file->eof = FALSE;
1095         file->seek_pending = FALSE;
1096         file->err = 0;
1097         file->err_info = NULL;
1098         file->avail_in = 0;
1099         file->pos += offset;
1100         return file->pos;
1101     }
1102
1103     /*
1104      * Are we seeking backwards?
1105      */
1106     if (offset < 0) {
1107         /*
1108          * Yes.
1109          *
1110          * Calculate the amount to skip forward after rewinding.
1111          */
1112         offset += file->pos;
1113         if (offset < 0) {                    /* before start of file! */
1114             *err = EINVAL;
1115             return -1;
1116         }
1117         /* rewind, then skip to offset */
1118
1119         /* back up and start over */
1120         if (ws_lseek64(file->fd, file->start, SEEK_SET) == -1) {
1121             *err = errno;
1122             return -1;
1123         }
1124         fast_seek_reset(file);
1125         file->raw_pos = file->start;
1126         gz_reset(file);
1127     }
1128
1129     /*
1130      * No, we're skipping forwards.
1131      *
1132      * Skip what's in output buffer (one less gzgetc() check).
1133      */
1134     n = (gint64)file->have > offset ? (unsigned)offset : file->have;
1135     file->have -= n;
1136     file->next += n;
1137     file->pos += n;
1138     offset -= n;
1139
1140     /* request skip (if not zero) */
1141     if (offset) {
1142         file->seek_pending = TRUE;
1143         file->skip = offset;
1144     }
1145     return file->pos + offset;
1146 }
1147
1148 /*
1149  * Skip forward the specified number of bytes in the file.
1150  * Currently implemented as a wrapper around file_seek(),
1151  * but if, for example, we ever add support for reading
1152  * sequentially from a pipe, this could instead just skip
1153  * forward by reading the bytes in question.
1154  */
1155 gboolean
1156 file_skip(FILE_T file, gint64 delta, int *err)
1157 {
1158     if (file_seek(file, delta, SEEK_CUR, err) == -1)
1159         return FALSE;
1160     return TRUE;
1161 }
1162
1163 gint64
1164 file_tell(FILE_T stream)
1165 {
1166     /* return position */
1167     return stream->pos + (stream->seek_pending ? stream->skip : 0);
1168 }
1169
1170 gint64
1171 file_tell_raw(FILE_T stream)
1172 {
1173     return stream->raw_pos;
1174 }
1175
1176 int
1177 file_fstat(FILE_T stream, ws_statb64 *statb, int *err)
1178 {
1179     if (ws_fstat64(stream->fd, statb) == -1) {
1180         if (err != NULL)
1181             *err = errno;
1182         return -1;
1183     }
1184     return 0;
1185 }
1186
1187 gboolean
1188 file_iscompressed(FILE_T stream)
1189 {
1190     return stream->is_compressed;
1191 }
1192
1193 int
1194 file_read(void *buf, unsigned int len, FILE_T file)
1195 {
1196     guint got, n;
1197
1198     /* if len is zero, avoid unnecessary operations */
1199     if (len == 0)
1200         return 0;
1201
1202     /* process a skip request */
1203     if (file->seek_pending) {
1204         file->seek_pending = FALSE;
1205         if (gz_skip(file, file->skip) == -1)
1206             return -1;
1207     }
1208
1209     /* get len bytes to buf, or less than len if at the end */
1210     got = 0;
1211     do {
1212         if (file->have) {
1213             /* We have stuff in the output buffer; copy
1214                what we have. */
1215             n = file->have > len ? len : file->have;
1216             memcpy(buf, file->next, n);
1217             file->next += n;
1218             file->have -= n;
1219         } else if (file->err) {
1220             /* We have nothing in the output buffer, and
1221                we have an error that may not have been
1222                reported yet; that means we can't generate
1223                any more data into the output buffer, so
1224                return an error indication. */
1225             return -1;
1226         } else if (file->eof && file->avail_in == 0) {
1227             /* We have nothing in the output buffer, and
1228                we're at the end of the input; just return
1229                with what we've gotten so far. */
1230             break;
1231         } else {
1232             /* We have nothing in the output buffer, and
1233                we can generate more data; get more output,
1234                looking for header if required, and
1235                keep looping to process the new stuff
1236                in the output buffer. */
1237             if (fill_out_buffer(file) == -1)
1238                 return -1;
1239             continue;       /* no progress yet -- go back to memcpy() above */
1240         }
1241         /* update progress */
1242         len -= n;
1243         buf = (char *)buf + n;
1244         got += n;
1245         file->pos += n;
1246     } while (len);
1247
1248     return (int)got;
1249 }
1250
1251 /*
1252  * XXX - this *peeks* at next byte, not a character.
1253  */
1254 int
1255 file_peekc(FILE_T file)
1256 {
1257     int ret = 0;
1258
1259     /* check that we're reading and that there's no error */
1260     if (file->err)
1261         return -1;
1262
1263     /* try output buffer (no need to check for skip request) */
1264     if (file->have) {
1265         return *(file->next);
1266     }
1267
1268     /* process a skip request */
1269     if (file->seek_pending) {
1270         file->seek_pending = FALSE;
1271         if (gz_skip(file, file->skip) == -1)
1272             return -1;
1273     }
1274     /* if we processed a skip request, there may be data in the buffer,
1275      * or an error could have occurred; likewise if we didn't do seek but
1276      * now call fill_out_buffer, the errors can occur.  So we do this while
1277      * loop to check before and after - this is basically the logic from
1278      * file_read() but only for peeking not consuming a byte
1279      */
1280     while (1) {
1281         if (file->have) {
1282             return *(file->next);
1283         }
1284         else if (file->err) {
1285             return -1;
1286         }
1287         else if (file->eof && file->avail_in == 0) {
1288             return -1;
1289         }
1290         else if (fill_out_buffer(file) == -1) {
1291             return -1;
1292         }
1293     }
1294     /* it's actually impossible to get here */
1295     return ret;
1296 }
1297
1298 /*
1299  * XXX - this gets a byte, not a character.
1300  */
1301 int
1302 file_getc(FILE_T file)
1303 {
1304     unsigned char buf[1];
1305     int ret;
1306
1307     /* check that we're reading and that there's no error */
1308     if (file->err)
1309         return -1;
1310
1311     /* try output buffer (no need to check for skip request) */
1312     if (file->have) {
1313         file->have--;
1314         file->pos++;
1315         return *(file->next)++;
1316     }
1317
1318     ret = file_read(buf, 1, file);
1319     return ret < 1 ? -1 : buf[0];
1320 }
1321
1322 char *
1323 file_gets(char *buf, int len, FILE_T file)
1324 {
1325     guint left, n;
1326     char *str;
1327     unsigned char *eol;
1328
1329     /* check parameters */
1330     if (buf == NULL || len < 1)
1331         return NULL;
1332
1333     /* check that there's no error */
1334     if (file->err)
1335         return NULL;
1336
1337     /* process a skip request */
1338     if (file->seek_pending) {
1339         file->seek_pending = FALSE;
1340         if (gz_skip(file, file->skip) == -1)
1341             return NULL;
1342     }
1343
1344     /* copy output bytes up to new line or len - 1, whichever comes first --
1345        append a terminating zero to the string (we don't check for a zero in
1346        the contents, let the user worry about that) */
1347     str = buf;
1348     left = (unsigned)len - 1;
1349     if (left) do {
1350             /* assure that something is in the output buffer */
1351             if (file->have == 0) {
1352                 /* We have nothing in the output buffer. */
1353                 if (file->err) {
1354                     /* We have an error that may not have
1355                        been reported yet; that means we
1356                        can't generate any more data into
1357                        the output buffer, so return an
1358                        error indication. */
1359                     return NULL;
1360                 }
1361                 if (fill_out_buffer(file) == -1)
1362                     return NULL;            /* error */
1363                 if (file->have == 0)  {     /* end of file */
1364                     if (buf == str)         /* got bupkus */
1365                         return NULL;
1366                     break;                  /* got something -- return it */
1367                 }
1368             }
1369
1370             /* look for end-of-line in current output buffer */
1371             n = file->have > left ? left : file->have;
1372             eol = (unsigned char *)memchr(file->next, '\n', n);
1373             if (eol != NULL)
1374                 n = (unsigned)(eol - file->next) + 1;
1375
1376             /* copy through end-of-line, or remainder if not found */
1377             memcpy(buf, file->next, n);
1378             file->have -= n;
1379             file->next += n;
1380             file->pos += n;
1381             left -= n;
1382             buf += n;
1383         } while (left && eol == NULL);
1384
1385     /* found end-of-line or out of space -- terminate string and return it */
1386     buf[0] = 0;
1387     return str;
1388 }
1389
1390 int
1391 file_eof(FILE_T file)
1392 {
1393     /* return end-of-file state */
1394     return (file->eof && file->avail_in == 0 && file->have == 0);
1395 }
1396
1397 /*
1398  * Routine to return a Wiretap error code (0 for no error, an errno
1399  * for a file error, or a WTAP_ERR_ code for other errors) for an
1400  * I/O stream.  Also returns an error string for some errors.
1401  */
1402 int
1403 file_error(FILE_T fh, gchar **err_info)
1404 {
1405     if (fh->err!=0 && err_info) {
1406         /* g_strdup() returns NULL for NULL argument */
1407         *err_info = g_strdup(fh->err_info);
1408     }
1409     return fh->err;
1410 }
1411
1412 void
1413 file_clearerr(FILE_T stream)
1414 {
1415     /* clear error and end-of-file */
1416     stream->err = 0;
1417     stream->err_info = NULL;
1418     stream->eof = FALSE;
1419 }
1420
1421 void
1422 file_fdclose(FILE_T file)
1423 {
1424     ws_close(file->fd);
1425     file->fd = -1;
1426 }
1427
1428 gboolean
1429 file_fdreopen(FILE_T file, const char *path)
1430 {
1431     int fd;
1432
1433     if ((fd = ws_open(path, O_RDONLY|O_BINARY, 0000)) == -1)
1434         return FALSE;
1435     file->fd = fd;
1436     return TRUE;
1437 }
1438
1439 void
1440 file_close(FILE_T file)
1441 {
1442     int fd = file->fd;
1443
1444     /* free memory and close file */
1445     if (file->size) {
1446 #ifdef HAVE_ZLIB
1447         inflateEnd(&(file->strm));
1448 #endif
1449         g_free(file->out);
1450         g_free(file->in);
1451     }
1452     g_free(file->fast_seek_cur);
1453     file->err = 0;
1454     file->err_info = NULL;
1455     g_free(file);
1456     /*
1457      * If fd is -1, somebody's done a file_closefd() on us, so
1458      * we don't need to close the FD itself, and shouldn't do
1459      * so.
1460      */
1461     if (fd != -1)
1462         ws_close(fd);
1463 }
1464
1465 #ifdef HAVE_ZLIB
1466 /* internal gzip file state data structure for writing */
1467 struct wtap_writer {
1468     int fd;                 /* file descriptor */
1469     gint64 pos;             /* current position in uncompressed data */
1470     guint size;          /* buffer size, zero if not allocated yet */
1471     guint want;          /* requested buffer size, default is GZBUFSIZE */
1472     unsigned char *in;      /* input buffer */
1473     unsigned char *out;     /* output buffer (double-sized when reading) */
1474     unsigned char *next;    /* next output data to deliver or write */
1475     int level;              /* compression level */
1476     int strategy;           /* compression strategy */
1477     int err;                /* error code */
1478     /* zlib deflate stream */
1479     z_stream strm;          /* stream structure in-place (not a pointer) */
1480 };
1481
1482 GZWFILE_T
1483 gzwfile_open(const char *path)
1484 {
1485     int fd;
1486     GZWFILE_T state;
1487     int save_errno;
1488
1489     fd = ws_open(path, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666);
1490     if (fd == -1)
1491         return NULL;
1492     state = gzwfile_fdopen(fd);
1493     if (state == NULL) {
1494         save_errno = errno;
1495         ws_close(fd);
1496         errno = save_errno;
1497     }
1498     return state;
1499 }
1500
1501 GZWFILE_T
1502 gzwfile_fdopen(int fd)
1503 {
1504     GZWFILE_T state;
1505
1506     /* allocate wtap_writer structure to return */
1507     state = (GZWFILE_T)g_try_malloc(sizeof *state);
1508     if (state == NULL)
1509         return NULL;
1510     state->fd = fd;
1511     state->size = 0;            /* no buffers allocated yet */
1512     state->want = GZBUFSIZE;    /* requested buffer size */
1513
1514     state->level = Z_DEFAULT_COMPRESSION;
1515     state->strategy = Z_DEFAULT_STRATEGY;
1516
1517     /* initialize stream */
1518     state->err = Z_OK;              /* clear error */
1519     state->pos = 0;                 /* no uncompressed data yet */
1520     state->strm.avail_in = 0;       /* no input data yet */
1521
1522     /* return stream */
1523     return state;
1524 }
1525
1526 /* Initialize state for writing a gzip file.  Mark initialization by setting
1527    state->size to non-zero.  Return -1, and set state->err, on failure;
1528    return 0 on success. */
1529 static int
1530 gz_init(GZWFILE_T state)
1531 {
1532     int ret;
1533     z_streamp strm = &(state->strm);
1534
1535     /* allocate input and output buffers */
1536     state->in = (unsigned char *)g_try_malloc(state->want);
1537     state->out = (unsigned char *)g_try_malloc(state->want);
1538     if (state->in == NULL || state->out == NULL) {
1539         g_free(state->out);
1540         g_free(state->in);
1541         state->err = ENOMEM;
1542         return -1;
1543     }
1544
1545     /* allocate deflate memory, set up for gzip compression */
1546     strm->zalloc = Z_NULL;
1547     strm->zfree = Z_NULL;
1548     strm->opaque = Z_NULL;
1549     ret = deflateInit2(strm, state->level, Z_DEFLATED,
1550                        15 + 16, 8, state->strategy);
1551     if (ret != Z_OK) {
1552         g_free(state->out);
1553         g_free(state->in);
1554         if (ret == Z_MEM_ERROR) {
1555             /* This means "not enough memory". */
1556             state->err = ENOMEM;
1557         } else {
1558             /* This "shouldn't happen". */
1559             state->err = WTAP_ERR_INTERNAL;
1560         }
1561         return -1;
1562     }
1563
1564     /* mark state as initialized */
1565     state->size = state->want;
1566
1567     /* initialize write buffer */
1568     strm->avail_out = state->size;
1569     strm->next_out = state->out;
1570     state->next = strm->next_out;
1571     return 0;
1572 }
1573
1574 /* Compress whatever is at avail_in and next_in and write to the output file.
1575    Return -1, and set state->err, if there is an error writing to the output
1576    file; return 0 on success.
1577    flush is assumed to be a valid deflate() flush value.  If flush is Z_FINISH,
1578    then the deflate() state is reset to start a new gzip stream. */
1579 static int
1580 gz_comp(GZWFILE_T state, int flush)
1581 {
1582     int ret;
1583     ssize_t got;
1584     ptrdiff_t have;
1585     z_streamp strm = &(state->strm);
1586
1587     /* allocate memory if this is the first time through */
1588     if (state->size == 0 && gz_init(state) == -1)
1589         return -1;
1590
1591     /* run deflate() on provided input until it produces no more output */
1592     ret = Z_OK;
1593     do {
1594         /* write out current buffer contents if full, or if flushing, but if
1595            doing Z_FINISH then don't write until we get to Z_STREAM_END */
1596         if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
1597                                      (flush != Z_FINISH || ret == Z_STREAM_END))) {
1598             have = strm->next_out - state->next;
1599             if (have) {
1600                 got = ws_write(state->fd, state->next, (unsigned int)have);
1601                 if (got < 0) {
1602                     state->err = errno;
1603                     return -1;
1604                 }
1605                 if ((ptrdiff_t)got != have) {
1606                     state->err = WTAP_ERR_SHORT_WRITE;
1607                     return -1;
1608                 }
1609             }
1610             if (strm->avail_out == 0) {
1611                 strm->avail_out = state->size;
1612                 strm->next_out = state->out;
1613             }
1614             state->next = strm->next_out;
1615         }
1616
1617         /* compress */
1618         have = strm->avail_out;
1619         ret = deflate(strm, flush);
1620         if (ret == Z_STREAM_ERROR) {
1621             /* This "shouldn't happen". */
1622             state->err = WTAP_ERR_INTERNAL;
1623             return -1;
1624         }
1625         have -= strm->avail_out;
1626     } while (have);
1627
1628     /* if that completed a deflate stream, allow another to start */
1629     if (flush == Z_FINISH)
1630         deflateReset(strm);
1631
1632     /* all done, no errors */
1633     return 0;
1634 }
1635
1636 /* Write out len bytes from buf.  Return 0, and set state->err, on
1637    failure or on an attempt to write 0 bytes (in which case state->err
1638    is Z_OK); return the number of bytes written on success. */
1639 unsigned
1640 gzwfile_write(GZWFILE_T state, const void *buf, guint len)
1641 {
1642     guint put = len;
1643     guint n;
1644     z_streamp strm;
1645
1646     strm = &(state->strm);
1647
1648     /* check that there's no error */
1649     if (state->err != Z_OK)
1650         return 0;
1651
1652     /* if len is zero, avoid unnecessary operations */
1653     if (len == 0)
1654         return 0;
1655
1656     /* allocate memory if this is the first time through */
1657     if (state->size == 0 && gz_init(state) == -1)
1658         return 0;
1659
1660     /* for small len, copy to input buffer, otherwise compress directly */
1661     if (len < state->size) {
1662         /* copy to input buffer, compress when full */
1663         do {
1664             if (strm->avail_in == 0)
1665                 strm->next_in = state->in;
1666             n = state->size - strm->avail_in;
1667             if (n > len)
1668                 n = len;
1669 #ifdef z_const
1670 DIAG_OFF(cast-qual)
1671             memcpy((Bytef *)strm->next_in + strm->avail_in, buf, n);
1672 DIAG_ON(cast-qual)
1673 #else
1674             memcpy(strm->next_in + strm->avail_in, buf, n);
1675 #endif
1676             strm->avail_in += n;
1677             state->pos += n;
1678             buf = (const char *)buf + n;
1679             len -= n;
1680             if (len && gz_comp(state, Z_NO_FLUSH) == -1)
1681                 return 0;
1682         } while (len);
1683     }
1684     else {
1685         /* consume whatever's left in the input buffer */
1686         if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
1687             return 0;
1688
1689         /* directly compress user buffer to file */
1690         strm->avail_in = len;
1691 #ifdef z_const
1692         strm->next_in = (z_const Bytef *)buf;
1693 #else
1694 DIAG_OFF(cast-qual)
1695         strm->next_in = (Bytef *)buf;
1696 DIAG_ON(cast-qual)
1697 #endif
1698         state->pos += len;
1699         if (gz_comp(state, Z_NO_FLUSH) == -1)
1700             return 0;
1701     }
1702
1703     /* input was all buffered or compressed (put will fit in int) */
1704     return (int)put;
1705 }
1706
1707 /* Flush out what we've written so far.  Returns -1, and sets state->err,
1708    on failure; returns 0 on success. */
1709 int
1710 gzwfile_flush(GZWFILE_T state)
1711 {
1712     /* check that there's no error */
1713     if (state->err != Z_OK)
1714         return -1;
1715
1716     /* compress remaining data with Z_SYNC_FLUSH */
1717     gz_comp(state, Z_SYNC_FLUSH);
1718     if (state->err != Z_OK)
1719         return -1;
1720     return 0;
1721 }
1722
1723 /* Flush out all data written, and close the file.  Returns a Wiretap
1724    error on failure; returns 0 on success.
1725
1726    If is_stdout is true, do all of that except for closing the file
1727    descriptor, as we don't want to close the standard output file
1728    descriptor out from under the program (even though, if the program
1729    is writing a capture file to the standard output, it shouldn't be
1730    doing anything *else* on the standard output). */
1731 int
1732 gzwfile_close(GZWFILE_T state, gboolean is_stdout)
1733 {
1734     int ret = 0;
1735
1736     /* flush, free memory, and close file */
1737     if (gz_comp(state, Z_FINISH) == -1 && ret == 0)
1738         ret = state->err;
1739     (void)deflateEnd(&(state->strm));
1740     g_free(state->out);
1741     g_free(state->in);
1742     state->err = Z_OK;
1743     if (!is_stdout) {
1744         if (ws_close(state->fd) == -1 && ret == 0)
1745             ret = errno;
1746     }
1747     g_free(state);
1748     return ret;
1749 }
1750
1751 int
1752 gzwfile_geterr(GZWFILE_T state)
1753 {
1754     return state->err;
1755 }
1756 #endif
1757
1758 /*
1759  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1760  *
1761  * Local variables:
1762  * c-basic-offset: 4
1763  * tab-width: 8
1764  * indent-tabs-mode: nil
1765  * End:
1766  *
1767  * vi: set shiftwidth=4 tabstop=8 expandtab:
1768  * :indentSize=4:tabSize=8:noTabs=true:
1769  */