Clean up comment alignment.
[metze/wireshark/wip.git] / wiretap / file_wrappers.c
1 /* file_wrappers.c
2  *
3  * $Id$
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7  *
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.
12  *
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.
17  *
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.
21  */
22
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
25  * under licence:
26  *
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.
30  *
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:
34  *
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.
42 */
43
44 #include "config.h"
45
46 #ifdef HAVE_UNISTD_H
47 #include <unistd.h>
48 #endif /* HAVE_UNISTD_H */
49
50 #include <errno.h>
51 #include <stdio.h>
52 #ifdef HAVE_FCNTL_H
53 #include <fcntl.h>
54 #endif /* HAVE_FCNTL_H */
55 #include <string.h>
56 #include "wtap-int.h"
57 #include "file_wrappers.h"
58 #include <wsutil/file_util.h>
59
60 #ifdef HAVE_LIBZ
61 #include <zlib.h>
62 #endif /* HAVE_LIBZ */
63
64 /*
65  * See RFC 1952 for a description of the gzip file format.
66  *
67  * Some other compressed file formats we might want to support:
68  *
69  *      XZ format: http://tukaani.org/xz/
70  *
71  *      Bzip2 format: http://bzip.org/
72  */
73
74 /*
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
78  * compression types.
79  */
80 static const char *compressed_file_extensions[] = {
81 #ifdef HAVE_LIBZ
82         "gz",
83 #endif
84         NULL
85 };
86
87 /*
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().
91  */
92 GSList *
93 wtap_get_compressed_file_extensions(void)
94 {
95         const char **extension;
96         GSList *extensions;
97
98         extensions = NULL;
99         for (extension = &compressed_file_extensions[0]; *extension != NULL;
100             extension++)
101                 extensions = g_slist_append(extensions, (gpointer)(*extension));
102         return extensions;
103 }
104
105 /* #define GZBUFSIZE 8192 */
106 #define GZBUFSIZE 4096
107
108 struct wtap_reader {
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 */
116
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 */
123         /* seek request */
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 */
129
130         guint avail_in;         /* number of bytes available at next_in */
131         unsigned char *next_in; /* next input byte */
132 #ifdef HAVE_LIBZ
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 */
136 #endif
137         /* fast seeking */
138         GPtrArray *fast_seek;
139         void *fast_seek_cur;
140 };
141
142 /* values for wtap_reader compression */
143 #define UNKNOWN         0       /* look for a gzip header */
144 #define UNCOMPRESSED    1       /* copy input directly */
145 #ifdef HAVE_LIBZ
146 #define ZLIB            2       /* decompress a zlib stream */
147 #define GZIP_AFTER_HEADER 3
148 #endif
149
150 static int      /* gz_load */
151 raw_read(FILE_T state, unsigned char *buf, unsigned int count, guint *have)
152 {
153         ssize_t ret;
154
155         *have = 0;
156         do {
157                 ret = read(state->fd, buf + *have, count - *have);
158                 if (ret <= 0)
159                         break;
160                 *have += (unsigned)ret;
161                 state->raw_pos += ret;
162         } while (*have < count);
163         if (ret < 0) {
164                 state->err = errno;
165                 state->err_info = NULL;
166                 return -1;
167         }
168         if (ret == 0)
169                 state->eof = 1;
170         return 0;
171 }
172
173 static int /* gz_avail */
174 fill_in_buffer(FILE_T state)
175 {
176         if (state->err)
177                 return -1;
178         if (state->eof == 0) {
179                 if (raw_read(state, state->in, state->size, &(state->avail_in)) == -1)
180                         return -1;
181                 state->next_in = state->in;
182         }
183         return 0;
184 }
185
186 #define ZLIB_WINSIZE 32768
187
188 struct fast_seek_point {
189         gint64 out;     /* corresponding offset in uncompressed data */
190         gint64 in;              /* offset in input file of first full byte */
191
192         int compression;
193         union {
194                 struct {
195 #ifdef HAVE_INFLATEPRIME
196                         int bits;               /* number of bits (1-7) from byte at in - 1, or 0 */
197 #endif
198                         unsigned char window[ZLIB_WINSIZE];     /* preceding 32K of uncompressed data */
199
200                         /* be gentle with Z_STREAM_END, 8 bytes more... Another solution would be to comment checks out */
201                         guint32 adler;
202                         guint32 total_out;
203                 } zlib;
204         } data;
205 };
206
207 struct zlib_cur_seek_point {
208         unsigned char window[ZLIB_WINSIZE];     /* preceding 32K of uncompressed data */
209         unsigned int pos;
210         unsigned int have;
211 };
212
213 #define SPAN G_GINT64_CONSTANT(1048576)
214 static struct fast_seek_point *
215 fast_seek_find(FILE_T file, gint64 pos)
216 {
217         struct fast_seek_point *smallest = NULL;
218         struct fast_seek_point *item;
219         guint low, i, max;
220
221         if (!file->fast_seek)
222                 return NULL;
223
224         for (low = 0, max = file->fast_seek->len; low < max; ) {
225                 i = (low + max) / 2;
226                 item = (struct fast_seek_point *)file->fast_seek->pdata[i];
227
228                 if (pos < item->out)
229                         max = i;
230                 else if (pos > item->out) {
231                         smallest = item;
232                         low = i + 1;
233                 } else {
234                         return item;
235                 }
236         }
237         return smallest;
238 }
239
240 static void
241 fast_seek_header(FILE_T file, gint64 in_pos, gint64 out_pos, int compression)
242 {
243         struct fast_seek_point *item = NULL;
244
245         if (file->fast_seek->len != 0)
246                 item = (struct fast_seek_point *)file->fast_seek->pdata[file->fast_seek->len - 1];
247
248         if (!item || item->out < out_pos) {
249                 struct fast_seek_point *val = g_new(struct fast_seek_point,1);
250                 val->in = in_pos;
251                 val->out = out_pos;
252                 val->compression = compression;
253
254                 g_ptr_array_add(file->fast_seek, val);
255         }
256 }
257
258 static void
259 fast_seek_reset(FILE_T state _U_)
260 {
261 #ifdef HAVE_LIBZ
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;
264
265                 cur->have = 0;
266         }
267 #endif
268 }
269
270 #ifdef HAVE_LIBZ
271
272 /* Get next byte from input, or -1 if end or error.
273  *
274  * Note:
275  *
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
278  *      an error;
279  *
280  *      2) GZ_GETC() returns -1 on an EOF;
281  *
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)++)))
287
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. */
290 static int
291 gz_next1(FILE_T state, guint8 *ret)
292 {
293         int ch;
294
295         ch = GZ_GETC();
296         if (ch == -1) {
297                 if (state->err == 0) {
298                         /* EOF */
299                         state->err = WTAP_ERR_SHORT_READ;
300                         state->err_info = NULL;
301                 }
302                 return -1;
303         }
304         *ret = ch;
305         return 0;
306 }
307
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
310    modified. */
311 static int
312 gz_next2(FILE_T state, guint16 *ret)
313 {
314         guint16 val;
315         int ch;
316
317         val = GZ_GETC();
318         ch = GZ_GETC();
319         if (ch == -1) {
320                 if (state->err == 0) {
321                         /* EOF */
322                         state->err = WTAP_ERR_SHORT_READ;
323                         state->err_info = NULL;
324                 }
325                 return -1;
326         }
327         val += (guint16)ch << 8;
328         *ret = val;
329         return 0;
330 }
331
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
334    modified. */
335 static int
336 gz_next4(FILE_T state, guint32 *ret)
337 {
338         guint32 val;
339         int ch;
340
341         val = GZ_GETC();
342         val += (unsigned)GZ_GETC() << 8;
343         val += (guint32)GZ_GETC() << 16;
344         ch = GZ_GETC();
345         if (ch == -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         val += (guint32)ch << 24;
354         *ret = val;
355         return 0;
356 }
357
358 /* Skip the specified number of bytes and return 0 on success.  Otherwise -1
359    is returned. */
360 static int
361 gz_skipn(FILE_T state, size_t n)
362 {
363         while (n != 0) {
364                 if (GZ_GETC() == -1) {
365                         if (state->err == 0) {
366                                 /* EOF */
367                                 state->err = WTAP_ERR_SHORT_READ;
368                                 state->err_info = NULL;
369                         }
370                         return -1;
371                 }
372                 n--;
373         }
374         return 0;
375 }
376
377 /* Skip a null-terminated string and return 0 on success.  Otherwise -1
378    is returned. */
379 static int
380 gz_skipzstr(FILE_T state)
381 {
382         int ch;
383
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)
387                 ;
388         if (ch == -1) {
389                 if (state->err == 0) {
390                         /* EOF */
391                         state->err = WTAP_ERR_SHORT_READ;
392                         state->err_info = NULL;
393                 }
394                 return -1;
395         }
396         return 0;
397 }
398
399 static void
400 zlib_fast_seek_add(FILE_T file, struct zlib_cur_seek_point *point, int bits, gint64 in_pos, gint64 out_pos)
401 {
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];
404
405 #ifndef HAVE_INFLATEPRIME
406         if (bits)
407                 return;
408 #endif
409
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
413          */
414         if (item->out + SPAN < out_pos) {
415                 struct fast_seek_point *val = g_new(struct fast_seek_point,1);
416                 val->in = in_pos;
417                 val->out = out_pos;
418                 val->compression = ZLIB;
419 #ifdef HAVE_INFLATEPRIME
420                 val->data.zlib.bits = bits;
421 #endif
422                 if (point->pos != 0) {
423                         unsigned int left = ZLIB_WINSIZE - point->pos;
424
425                         memcpy(val->data.zlib.window, point->window + point->pos, left);
426                         memcpy(val->data.zlib.window + left, point->window, point->pos);
427                 } else
428                         memcpy(val->data.zlib.window, point->window, ZLIB_WINSIZE);
429
430                 /*
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.
440                  *
441                  * The same applies to strm.total_out.
442                  */
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);
446         }
447 }
448
449 static void /* gz_decomp */
450 zlib_read(FILE_T state, unsigned char *buf, unsigned int count)
451 {
452         int ret = 0;    /* XXX */
453         guint32 crc, len;
454         z_streamp strm = &(state->strm);
455
456         unsigned char *buf2 = buf;
457         unsigned int count2 = count;
458
459         strm->avail_out = count;
460         strm->next_out = buf;
461
462         /* fill output buffer up to end of deflate stream or error */
463         do {
464                 /* get more input for inflate() */
465                 if (state->avail_in == 0 && fill_in_buffer(state) == -1)
466                         break;
467                 if (state->avail_in == 0) {
468                         /* EOF */
469                         state->err = WTAP_ERR_SHORT_READ;
470                         state->err_info = NULL;
471                         break;
472                 }
473
474                 strm->avail_in = state->avail_in;
475                 strm->next_in = state->next_in;
476                 /* decompress and handle errors */
477 #ifdef Z_BLOCK
478                 ret = inflate(strm, Z_BLOCK);
479 #else
480                 ret = inflate(strm, Z_NO_FLUSH);
481 #endif
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;
487                         break;
488                 }
489                 if (ret == Z_NEED_DICT) {
490                         state->err = WTAP_ERR_DECOMPRESS;
491                         state->err_info = "preset dictionary needed";
492                         break;
493                 }
494                 if (ret == Z_MEM_ERROR) {
495                         /* This means "not enough memory". */
496                         state->err = ENOMEM;
497                         state->err_info = NULL;
498                         break;
499                 }
500                 if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
501                         state->err = WTAP_ERR_DECOMPRESS;
502                         state->err_info = strm->msg;
503                         break;
504                 }
505                 /*
506                  * XXX - Z_BUF_ERROR?
507                  */
508
509                 strm->adler = crc32(strm->adler, buf2, count2 - strm->avail_out);
510 #ifdef Z_BLOCK
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;
514
515                         if (ready < ZLIB_WINSIZE) {
516                                 guint left = ZLIB_WINSIZE - cur->pos;
517
518                                 if (ready >= left) {
519                                         memcpy(cur->window + cur->pos, buf2, left);
520                                         if (ready != left)
521                                                 memcpy(cur->window, buf2 + left, ready - left);
522
523                                         cur->pos = ready - left;
524                                         cur->have += ready;
525                                 } else {
526                                         memcpy(cur->window + cur->pos, buf2, ready);
527                                         cur->pos += ready;
528                                         cur->have += ready;
529                                 }
530
531                                 if (cur->have >= ZLIB_WINSIZE)
532                                         cur->have = ZLIB_WINSIZE;
533
534                         } else {
535                                 memcpy(cur->window, buf2 + (ready - ZLIB_WINSIZE), ZLIB_WINSIZE);
536                                 cur->pos = 0;
537                                 cur->have = ZLIB_WINSIZE;
538                         }
539
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));
542                 }
543 #endif
544                 buf2 = (buf2 + count2 - strm->avail_out);
545                 count2 = strm->avail_out;
546
547         } while (strm->avail_out && ret != Z_STREAM_END);
548
549         /* update available output and crc check value */
550         state->next = buf;
551         state->have = count - strm->avail_out;
552
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";
567                         }
568                 }
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;
572         }
573 }
574 #endif
575
576 static int
577 gz_head(FILE_T state)
578 {
579         /* get some data in the input buffer */
580         if (state->avail_in == 0) {
581                 if (fill_in_buffer(state) == -1)
582                         return -1;
583                 if (state->avail_in == 0)
584                         return 0;
585         }
586
587         /* look for the gzip magic header bytes 31 and 139 */
588 #ifdef HAVE_LIBZ
589         if (state->next_in[0] == 31) {
590                 state->avail_in--;
591                 state->next_in++;
592                 if (state->avail_in == 0 && fill_in_buffer(state) == -1)
593                         return -1;
594                 if (state->avail_in && state->next_in[0] == 139) {
595                         guint8 cm;
596                         guint8 flags;
597                         guint16 len;
598                         guint16 hcrc;
599
600                         /* we have a gzip header, woo hoo! */
601                         state->avail_in--;
602                         state->next_in++;
603
604                         /* read rest of header */
605
606                         /* compression method (CM) */
607                         if (gz_next1(state, &cm) == -1)
608                                 return -1;
609                         if (cm != 8) {
610                                 state->err = WTAP_ERR_DECOMPRESS;
611                                 state->err_info = "unknown compression method";
612                                 return -1;
613                         }
614
615                         /* flags (FLG) */
616                         if (gz_next1(state, &flags) == -1)
617                                 return -1;
618                         if (flags & 0xe0) {     /* reserved flag bits */
619                                 state->err = WTAP_ERR_DECOMPRESS;
620                                 state->err_info = "reserved flag bits set";
621                                 return -1;
622                         }
623
624                         /* modification time (MTIME) */
625                         if (gz_skipn(state, 4) == -1)
626                                 return -1;
627
628                         /* extra flags (XFL) */
629                         if (gz_skipn(state, 1) == -1)
630                                 return -1;
631
632                         /* operating system (OS) */
633                         if (gz_skipn(state, 1) == -1)
634                                 return -1;
635
636                         if (flags & 4) {
637                                 /* extra field - get XLEN */
638                                 if (gz_next2(state, &len) == -1)
639                                         return -1;
640
641                                 /* skip the extra field */
642                                 if (gz_skipn(state, len) == -1)
643                                         return -1;
644                         }
645                         if (flags & 8) {
646                                 /* file name */
647                                 if (gz_skipzstr(state) == -1)
648                                         return -1;
649                         }
650                         if (flags & 16) {
651                                 /* comment */
652                                 if (gz_skipzstr(state) == -1)
653                                         return -1;
654                         }
655                         if (flags & 2) {
656                                 /* header crc */
657                                 if (gz_next2(state, &hcrc) == -1)
658                                         return -1;
659                                 /* XXX - check the CRC? */
660                         }
661
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;
667 #ifdef Z_BLOCK
668                         if (state->fast_seek) {
669                                 struct zlib_cur_seek_point *cur = g_new(struct zlib_cur_seek_point,1);
670
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);
675                         }
676 #endif
677                         return 0;
678                 }
679                 else {
680                         /* not a gzip file -- save first byte (31) and fall to raw i/o */
681                         state->out[0] = 31;
682                         state->have = 1;
683                 }
684         }
685 #endif
686 #ifdef HAVE_LIBXZ
687         /* { 0xFD, '7', 'z', 'X', 'Z', 0x00 } */
688         /* FD 37 7A 58 5A 00 */
689 #endif
690         if (state->fast_seek)
691                 fast_seek_header(state, state->raw_pos - state->avail_in - state->have, state->pos, UNCOMPRESSED);
692
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;
701                 state->avail_in = 0;
702         }
703         state->compression = UNCOMPRESSED;
704         return 0;
705 }
706
707 static int /* gz_make */
708 fill_out_buffer(FILE_T state)
709 {
710         if (state->compression == UNKNOWN) {           /* look for gzip header */
711                 if (gz_head(state) == -1)
712                         return -1;
713                 if (state->have)                /* got some data from gz_head() */
714                         return 0;
715         }
716         if (state->compression == UNCOMPRESSED) {           /* straight copy */
717                 if (raw_read(state, state->out, state->size /* << 1 */, &(state->have)) == -1)
718                         return -1;
719                 state->next = state->out;
720         }
721 #ifdef HAVE_LIBZ
722         else if (state->compression == ZLIB) {      /* decompress */
723                 zlib_read(state, state->out, state->size << 1);
724         }
725 #endif
726         return 0;
727 }
728
729 static int
730 gz_skip(FILE_T state, gint64 len)
731 {
732         guint n;
733
734         /* skip over len bytes or reach end-of-file, whichever comes first */
735         while (len)
736                 if (state->have) {
737                         /* We have stuff in the output buffer; skip over
738                            it. */
739                         n = (gint64)state->have > len ? (unsigned)len : state->have;
740                         state->have -= n;
741                         state->next += n;
742                         state->pos += n;
743                         len -= n;
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. */
750                         return -1;
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. */
754                         break;
755                 } else {
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)
760                                 return -1;
761                 }
762         return 0;
763 }
764
765 static void
766 gz_reset(FILE_T state)
767 {
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 */
771
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 */
777 }
778
779 FILE_T
780 file_fdopen(int fd)
781 {
782 #ifdef _STATBUF_ST_BLKSIZE      /* XXX, _STATBUF_ST_BLKSIZE portable? */
783         struct stat st;
784 #endif
785         int want = GZBUFSIZE;
786         FILE_T state;
787
788         if (fd == -1)
789                 return NULL;
790
791         /* allocate FILE_T structure to return */
792         state = (FILE_T)g_try_malloc(sizeof *state);
793         if (state == NULL)
794                 return NULL;
795
796         state->fast_seek_cur = NULL;
797         state->fast_seek = NULL;
798
799         /* open the file with the appropriate mode (or just use fd) */
800         state->fd = fd;
801
802         /* we don't yet know whether it's compressed */
803         state->is_compressed = FALSE;
804
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;
809
810         /* initialize stream */
811         gz_reset(state);
812
813 #ifdef _STATBUF_ST_BLKSIZE
814         if (fstat(fd, &st) >= 0) {
815                 want = st.st_blksize;
816                 /* XXX, verify result? */
817         }
818 #endif
819
820         /* allocate buffers */
821         state->in = (unsigned char *)g_try_malloc(want);
822         state->out = (unsigned char *)g_try_malloc(want << 1);
823         state->size = want;
824         if (state->in == NULL || state->out == NULL) {
825                 g_free(state->out);
826                 g_free(state->in);
827                 g_free(state);
828                 errno = ENOMEM;
829                 return NULL;
830         }
831
832 #ifdef HAVE_LIBZ
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 */
840                 g_free(state->out);
841                 g_free(state->in);
842                 g_free(state);
843                 errno = ENOMEM;
844                 return NULL;
845         }
846
847         /* for now, assume we should check the crc */
848         state->dont_check_crc = 0;
849 #endif
850         /* return stream */
851         return state;
852 }
853
854 FILE_T
855 file_open(const char *path)
856 {
857         int fd;
858         FILE_T ft;
859 #ifdef HAVE_LIBZ
860         const char *suffixp;
861 #endif
862
863         /* open file and do correct filename conversions.
864
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)
873                 return NULL;
874
875         /* open file handle */
876         ft = file_fdopen(fd);
877         if (ft == NULL) {
878                 ws_close(fd);
879                 return NULL;
880         }
881
882 #ifdef HAVE_LIBZ
883         /*
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.
888          *
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?
893          *
894          * For now, we just set a flag to ignore CRC errors.
895          */
896         suffixp = strrchr(path, '.');
897         if (suffixp != NULL) {
898                 if (g_ascii_strcasecmp(suffixp, ".caz") == 0)
899                         ft->dont_check_crc = 1;
900         }
901 #endif
902
903         return ft;
904 }
905
906 void
907 file_set_random_access(FILE_T stream, gboolean random_flag _U_, GPtrArray *seek)
908 {
909         stream->fast_seek = seek;
910 }
911
912 gint64
913 file_seek(FILE_T file, gint64 offset, int whence, int *err)
914 {
915         struct fast_seek_point *here;
916         guint n;
917
918         /* can only seek from start or relative to current position */
919         if (whence != SEEK_SET && whence != SEEK_CUR) {
920                 g_assert_not_reached();
921 /*
922                 *err = EINVAL;
923                 return -1;
924  */
925         }
926
927         /* normalize offset to a SEEK_CUR specification */
928         if (whence == SEEK_SET)
929                 offset -= file->pos;
930         else if (file->seek)
931                 offset += file->skip;
932         file->seek = 0;
933
934         if (offset < 0 && file->next) {
935                 /*
936                  * This is guaranteed to fit in an unsigned int.
937                  * To squelch compiler warnings, we cast the
938                  * result.
939                  */
940                 guint had = (unsigned)(file->next - file->out);
941                 if (-offset <= had) {
942                         /*
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.
948                          *
949                          * (Casting offset to unsigned makes
950                          * it positive, which is not what we
951                          * would want, so we cast -offset
952                          * instead.)
953                          */
954                         guint adjustment = (unsigned)(-offset);
955                         file->have += adjustment;
956                         file->next -= adjustment;
957                         file->pos -= adjustment;
958                         return file->pos;
959                 }
960         }
961
962         /* XXX, profile */
963         if ((here = fast_seek_find(file, file->pos + offset)) && (offset < 0 || offset > SPAN || here->compression == UNCOMPRESSED)) {
964                 gint64 off, off2;
965
966 #ifdef HAVE_LIBZ
967                 if (here->compression == ZLIB) {
968 #ifdef HAVE_INFLATEPRIME
969                         off = here->in - (here->data.zlib.bits ? 1 : 0);
970 #else
971                         off = here->in;
972 #endif
973                         off2 = here->out;
974                 } else if (here->compression == GZIP_AFTER_HEADER) {
975                         off = here->in;
976                         off2 = here->out;
977                 } else
978 #endif
979                 {
980                         off2 = (file->pos + offset);
981                         off = here->in + (off2 - here->out);
982                 }
983
984                 if (ws_lseek64(file->fd, off, SEEK_SET) == -1) {
985                         *err = errno;
986                         return -1;
987                 }
988                 fast_seek_reset(file);
989
990                 file->raw_pos = off;
991                 file->have = 0;
992                 file->eof = 0;
993                 file->seek = 0;
994                 file->err = 0;
995                 file->err_info = NULL;
996                 file->avail_in = 0;
997
998 #ifdef HAVE_LIBZ
999                 if (here->compression == ZLIB) {
1000                         z_stream *strm = &file->strm;
1001
1002                         inflateReset(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();
1009
1010                                 if (ret == -1) {
1011                                         if (state->err == 0) {
1012                                                 /* EOF */
1013                                                 *err = WTAP_ERR_SHORT_READ;
1014                                         } else
1015                                                 *err = state->err;
1016                                         return -1;
1017                                 }
1018                                 (void)inflatePrime(strm, here->data.zlib.bits, ret >> (8 - here->data.zlib.bits));
1019                         }
1020 #endif
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;
1025
1026                         inflateReset(strm);
1027                         strm->adler = crc32(0L, Z_NULL, 0);
1028                         file->compression = ZLIB;
1029                 } else
1030 #endif
1031                         file->compression = here->compression;
1032
1033                 offset = (file->pos + offset) - off2;
1034                 file->pos = off2;
1035                 /* g_print("OK! %ld\n", offset); */
1036
1037                 if (offset) {
1038                         file->seek = 1;
1039                         file->skip = offset;
1040                 }
1041                 return file->pos + offset;
1042         }
1043
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 */)
1047         {
1048                 if (ws_lseek64(file->fd, offset - file->have, SEEK_CUR) == -1) {
1049                         *err = errno;
1050                         return -1;
1051                 }
1052                 file->raw_pos += (offset - file->have);
1053                 file->have = 0;
1054                 file->eof = 0;
1055                 file->seek = 0;
1056                 file->err = 0;
1057                 file->err_info = NULL;
1058                 file->avail_in = 0;
1059                 file->pos += offset;
1060                 return file->pos;
1061         }
1062
1063         /* calculate skip amount, rewinding if needed for back seek when reading */
1064         if (offset < 0) {
1065                 offset += file->pos;
1066                 if (offset < 0) {                    /* before start of file! */
1067                         *err = EINVAL;
1068                         return -1;
1069                 }
1070                 /* rewind, then skip to offset */
1071
1072                 /* back up and start over */
1073                 if (ws_lseek64(file->fd, file->start, SEEK_SET) == -1) {
1074                         *err = errno;
1075                         return -1;
1076                 }
1077                 fast_seek_reset(file);
1078                 file->raw_pos = file->start;
1079                 gz_reset(file);
1080         }
1081
1082         /* skip what's in output buffer (one less gzgetc() check) */
1083         n = (gint64)file->have > offset ? (unsigned)offset : file->have;
1084         file->have -= n;
1085         file->next += n;
1086         file->pos += n;
1087         offset -= n;
1088
1089         /* request skip (if not zero) */
1090         if (offset) {
1091                 file->seek = 1;
1092                 file->skip = offset;
1093         }
1094         return file->pos + offset;
1095 }
1096
1097 /*
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.
1103  */
1104 gint64
1105 file_skip(FILE_T file, gint64 delta, int *err)
1106 {
1107         return file_seek(file, delta, SEEK_CUR, err);
1108 }
1109
1110 gint64
1111 file_tell(FILE_T stream)
1112 {
1113         /* return position */
1114         return stream->pos + (stream->seek ? stream->skip : 0);
1115 }
1116
1117 gint64
1118 file_tell_raw(FILE_T stream)
1119 {
1120         return stream->raw_pos;
1121 }
1122
1123 int
1124 file_fstat(FILE_T stream, ws_statb64 *statb, int *err)
1125 {
1126         if (ws_fstat64(stream->fd, statb) == -1) {
1127                 if (err != NULL)
1128                         *err = errno;
1129                 return -1;
1130         }
1131         return 0;
1132 }
1133
1134 gboolean
1135 file_iscompressed(FILE_T stream)
1136 {
1137         return stream->is_compressed;
1138 }
1139
1140 int
1141 file_read(void *buf, unsigned int len, FILE_T file)
1142 {
1143         guint got, n;
1144
1145         /* if len is zero, avoid unnecessary operations */
1146         if (len == 0)
1147                 return 0;
1148
1149         /* process a skip request */
1150         if (file->seek) {
1151                 file->seek = 0;
1152                 if (gz_skip(file, file->skip) == -1)
1153                         return -1;
1154         }
1155
1156         /* get len bytes to buf, or less than len if at the end */
1157         got = 0;
1158         do {
1159                 if (file->have) {
1160                         /* We have stuff in the output buffer; copy
1161                            what we have. */
1162                         n = file->have > len ? len : file->have;
1163                         memcpy(buf, file->next, n);
1164                         file->next += n;
1165                         file->have -= 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. */
1172                         return -1;
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. */
1177                         break;
1178                 } else {
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)
1185                                 return -1;
1186                         continue;       /* no progress yet -- go back to memcpy() above */
1187                 }
1188                 /* update progress */
1189                 len -= n;
1190                 buf = (char *)buf + n;
1191                 got += n;
1192                 file->pos += n;
1193         } while (len);
1194
1195         return (int)got;
1196 }
1197
1198 int
1199 file_getc(FILE_T file)
1200 {
1201         unsigned char buf[1];
1202         int ret;
1203
1204         /* check that we're reading and that there's no error */
1205         if (file->err)
1206                 return -1;
1207
1208         /* try output buffer (no need to check for skip request) */
1209         if (file->have) {
1210                 file->have--;
1211                 file->pos++;
1212                 return *(file->next)++;
1213         }
1214
1215         ret = file_read(buf, 1, file);
1216         return ret < 1 ? -1 : buf[0];
1217 }
1218
1219 char *
1220 file_gets(char *buf, int len, FILE_T file)
1221 {
1222         guint left, n;
1223         char *str;
1224         unsigned char *eol;
1225
1226         /* check parameters */
1227         if (buf == NULL || len < 1)
1228                 return NULL;
1229
1230         /* check that there's no error */
1231         if (file->err)
1232                 return NULL;
1233
1234         /* process a skip request */
1235         if (file->seek) {
1236                 file->seek = 0;
1237                 if (gz_skip(file, file->skip) == -1)
1238                         return NULL;
1239         }
1240
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) */
1244         str = buf;
1245         left = (unsigned)len - 1;
1246         if (left) do {
1247                 /* assure that something is in the output buffer */
1248                 if (file->have == 0) {
1249                         /* We have nothing in the output buffer. */
1250                         if (file->err) {
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. */
1256                                 return NULL;
1257                         }
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 */
1262                                         return NULL;
1263                                 break;                  /* got something -- return it */
1264                         }
1265                 }
1266
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);
1270                 if (eol != NULL)
1271                         n = (unsigned)(eol - file->next) + 1;
1272
1273                 /* copy through end-of-line, or remainder if not found */
1274                 memcpy(buf, file->next, n);
1275                 file->have -= n;
1276                 file->next += n;
1277                 file->pos += n;
1278                 left -= n;
1279                 buf += n;
1280         } while (left && eol == NULL);
1281
1282         /* found end-of-line or out of space -- terminate string and return it */
1283         buf[0] = 0;
1284         return str;
1285 }
1286
1287 int
1288 file_eof(FILE_T file)
1289 {
1290         /* return end-of-file state */
1291         return (file->eof && file->avail_in == 0 && file->have == 0);
1292 }
1293
1294 /*
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.
1298  */
1299 int
1300 file_error(FILE_T fh, gchar **err_info)
1301 {
1302         if (fh->err != 0) {
1303                 *err_info = (fh->err_info == NULL) ? NULL : g_strdup(fh->err_info);
1304                 return fh->err;
1305         }
1306         return 0;
1307 }
1308
1309 void
1310 file_clearerr(FILE_T stream)
1311 {
1312         /* clear error and end-of-file */
1313         stream->err = 0;
1314         stream->err_info = NULL;
1315         stream->eof = 0;
1316 }
1317
1318 void
1319 file_fdclose(FILE_T file)
1320 {
1321         ws_close(file->fd);
1322         file->fd = -1;
1323 }
1324
1325 gboolean
1326 file_fdreopen(FILE_T file, const char *path)
1327 {
1328         int fd;
1329
1330         if ((fd = ws_open(path, O_RDONLY|O_BINARY, 0000)) == -1)
1331                 return FALSE;
1332         file->fd = fd;
1333         return TRUE;
1334 }
1335
1336 void
1337 file_close(FILE_T file)
1338 {
1339         int fd = file->fd;
1340
1341         /* free memory and close file */
1342         if (file->size) {
1343 #ifdef HAVE_LIBZ
1344                 inflateEnd(&(file->strm));
1345 #endif
1346                 g_free(file->out);
1347                 g_free(file->in);
1348         }
1349         g_free(file->fast_seek_cur);
1350         file->err = 0;
1351         file->err_info = NULL;
1352         g_free(file);
1353         /*
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
1356          * so.
1357          */
1358         if (fd != -1)
1359                 ws_close(fd);
1360 }
1361
1362 #ifdef HAVE_LIBZ
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) */
1377 };
1378
1379 GZWFILE_T
1380 gzwfile_open(const char *path)
1381 {
1382     int fd;
1383     GZWFILE_T state;
1384     int save_errno;
1385
1386     fd = ws_open(path, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0666);
1387     if (fd == -1)
1388         return NULL;
1389     state = gzwfile_fdopen(fd);
1390     if (state == NULL) {
1391         save_errno = errno;
1392         close(fd);
1393         errno = save_errno;
1394     }
1395     return state;
1396 }
1397
1398 GZWFILE_T
1399 gzwfile_fdopen(int fd)
1400 {
1401     GZWFILE_T state;
1402
1403     /* allocate wtap_writer structure to return */
1404     state = (GZWFILE_T)g_try_malloc(sizeof *state);
1405     if (state == NULL)
1406         return NULL;
1407     state->fd = fd;
1408     state->size = 0;            /* no buffers allocated yet */
1409     state->want = GZBUFSIZE;    /* requested buffer size */
1410
1411     state->level = Z_DEFAULT_COMPRESSION;
1412     state->strategy = Z_DEFAULT_STRATEGY;
1413
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 */
1418
1419     /* return stream */
1420     return state;
1421 }
1422
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. */
1426 static int
1427 gz_init(GZWFILE_T state)
1428 {
1429     int ret;
1430     z_streamp strm = &(state->strm);
1431
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) {
1436         g_free(state->out);
1437         g_free(state->in);
1438         state->err = ENOMEM;
1439         return -1;
1440     }
1441
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);
1448     if (ret != Z_OK) {
1449         g_free(state->out);
1450         g_free(state->in);
1451         if (ret == Z_MEM_ERROR) {
1452                 /* This means "not enough memory". */
1453                 state->err = ENOMEM;
1454         } else {
1455                 /* This "shouldn't happen". */
1456                 state->err = WTAP_ERR_INTERNAL;
1457         }
1458         return -1;
1459     }
1460
1461     /* mark state as initialized */
1462     state->size = state->want;
1463
1464     /* initialize write buffer */
1465     strm->avail_out = state->size;
1466     strm->next_out = state->out;
1467     state->next = strm->next_out;
1468     return 0;
1469 }
1470
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. */
1476 static int
1477 gz_comp(GZWFILE_T state, int flush)
1478 {
1479     int ret;
1480     ssize_t got;
1481     ptrdiff_t have;
1482     z_streamp strm = &(state->strm);
1483
1484     /* allocate memory if this is the first time through */
1485     if (state->size == 0 && gz_init(state) == -1)
1486         return -1;
1487
1488     /* run deflate() on provided input until it produces no more output */
1489     ret = Z_OK;
1490     do {
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;
1496             if (have) {
1497                 got = write(state->fd, state->next, (unsigned int)have);
1498                 if (got < 0) {
1499                     state->err = errno;
1500                     return -1;
1501                 }
1502                 if ((ptrdiff_t)got != have) {
1503                     state->err = WTAP_ERR_SHORT_WRITE;
1504                     return -1;
1505                 }
1506             }
1507             if (strm->avail_out == 0) {
1508                 strm->avail_out = state->size;
1509                 strm->next_out = state->out;
1510             }
1511             state->next = strm->next_out;
1512         }
1513
1514         /* compress */
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;
1520             return -1;
1521         }
1522         have -= strm->avail_out;
1523     } while (have);
1524
1525     /* if that completed a deflate stream, allow another to start */
1526     if (flush == Z_FINISH)
1527         deflateReset(strm);
1528
1529     /* all done, no errors */
1530     return 0;
1531 }
1532
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. */
1536 unsigned
1537 gzwfile_write(GZWFILE_T state, const void *buf, guint len)
1538 {
1539     guint put = len;
1540     guint n;
1541     z_streamp strm;
1542
1543     strm = &(state->strm);
1544
1545     /* check that there's no error */
1546     if (state->err != Z_OK)
1547         return 0;
1548
1549     /* if len is zero, avoid unnecessary operations */
1550     if (len == 0)
1551         return 0;
1552
1553     /* allocate memory if this is the first time through */
1554     if (state->size == 0 && gz_init(state) == -1)
1555         return 0;
1556
1557     /* for small len, copy to input buffer, otherwise compress directly */
1558     if (len < state->size) {
1559         /* copy to input buffer, compress when full */
1560         do {
1561             if (strm->avail_in == 0)
1562                 strm->next_in = state->in;
1563             n = state->size - strm->avail_in;
1564             if (n > len)
1565                 n = len;
1566             memcpy(strm->next_in + strm->avail_in, buf, n);
1567             strm->avail_in += n;
1568             state->pos += n;
1569             buf = (char *)buf + n;
1570             len -= n;
1571             if (len && gz_comp(state, Z_NO_FLUSH) == -1)
1572                 return 0;
1573         } while (len);
1574     }
1575     else {
1576         /* consume whatever's left in the input buffer */
1577         if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
1578             return 0;
1579
1580         /* directly compress user buffer to file */
1581         strm->avail_in = len;
1582         strm->next_in = (voidp)buf;
1583         state->pos += len;
1584         if (gz_comp(state, Z_NO_FLUSH) == -1)
1585             return 0;
1586     }
1587
1588     /* input was all buffered or compressed (put will fit in int) */
1589     return (int)put;
1590 }
1591
1592 /* Flush out what we've written so far.  Returns -1, and sets state->err,
1593    on failure; returns 0 on success. */
1594 int
1595 gzwfile_flush(GZWFILE_T state)
1596 {
1597     /* check that there's no error */
1598     if (state->err != Z_OK)
1599         return -1;
1600
1601     /* compress remaining data with Z_SYNC_FLUSH */
1602     gz_comp(state, Z_SYNC_FLUSH);
1603     if (state->err != Z_OK)
1604         return -1;
1605     return 0;
1606 }
1607
1608 /* Flush out all data written, and close the file.  Returns a Wiretap
1609    error on failure; returns 0 on success. */
1610 int
1611 gzwfile_close(GZWFILE_T state)
1612 {
1613     int ret = 0;
1614
1615     /* flush, free memory, and close file */
1616     if (gz_comp(state, Z_FINISH) == -1 && ret == 0)
1617         ret = state->err;
1618     (void)deflateEnd(&(state->strm));
1619     g_free(state->out);
1620     g_free(state->in);
1621     state->err = Z_OK;
1622     if (close(state->fd) == -1 && ret == 0)
1623         ret = errno;
1624     g_free(state);
1625     return ret;
1626 }
1627
1628 int
1629 gzwfile_geterr(GZWFILE_T state)
1630 {
1631     return state->err;
1632 }
1633 #endif