6 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41 #include "file_util.h"
44 #include "file_wrappers.h"
46 #include "lanalyzer.h"
47 #include "airopeek9.h"
48 #include "ngsniffer.h"
63 #include "etherpeek.h"
65 #include "dbs-etherwatch.h"
71 #include "network_instruments.h"
74 #include "catapult_dct2000.h"
79 /* The open_file_* routines should return:
83 * 1 if the file they're reading is one of the types it handles;
85 * 0 if the file they're reading isn't the type they're checking for.
87 * If the routine handles this type of file, it should set the "file_type"
88 * field in the "struct wtap" to the type of the file.
90 * Put the trace files that are merely saved telnet-sessions last, since it's
91 * possible that you could have captured someone a router telnet-session
92 * using another tool. So, a libpcap trace of an toshiba "snoop" session
93 * should be discovered as a libpcap file, not a toshiba file.
97 static wtap_open_routine_t open_routines_base[] = {
98 /* Files that have magic bytes in fixed locations. These
99 * are easy to identify.
112 network_instruments_open,
116 catapult_dct2000_open,
119 /* Files that don't have magic bytes at a fixed location,
120 * but that instead require a heuristic of some sort to
121 * identify them. This includes the ASCII trace files that
122 * would be, for example, saved copies of a Telnet session
140 #define N_FILE_TYPES (sizeof open_routines_base / sizeof open_routines_base[0])
142 static wtap_open_routine_t* open_routines = NULL;
144 static GArray* open_routines_arr = NULL;
147 /* initialize the open routines array if it has not being initialized yet */
148 static void init_open_routines(void) {
150 if (open_routines_arr) return;
152 open_routines_arr = g_array_new(FALSE,TRUE,sizeof(wtap_open_routine_t));
154 g_array_append_vals(open_routines_arr,open_routines_base,N_FILE_TYPES);
156 open_routines = (void*)open_routines_arr->data;
159 void wtap_register_open_routine(wtap_open_routine_t open_routine, gboolean has_magic) {
160 init_open_routines();
163 g_array_prepend_val(open_routines_arr,open_routine);
165 g_array_append_val(open_routines_arr,open_routine);
167 open_routines = (void*)open_routines_arr->data;
168 wtap_num_file_types++;
172 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
173 * define them either.)
175 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
178 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
181 #define S_IFIFO _S_IFIFO
184 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
187 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
190 /* Opens a file and prepares a wtap struct.
191 If "do_random" is TRUE, it opens the file twice; the second open
192 allows the application to do random-access I/O without moving
193 the seek offset for sequential I/O, which is used by Wireshark
194 so that it can do sequential I/O to a capture file that's being
195 written to as new packets arrive independently of random I/O done
196 to display protocol trees for packets when they're selected. */
197 wtap* wtap_open_offline(const char *filename, int *err, char **err_info,
203 gboolean use_stdin = FALSE;
205 /* open standard input if filename is '-' */
206 if (strcmp(filename, "-") == 0)
209 /* First, make sure the file is valid */
211 if (fstat(0, &statb) < 0) {
216 if (eth_stat(filename, &statb) < 0) {
221 if (S_ISFIFO(statb.st_mode)) {
223 * Opens of FIFOs are allowed only when not opening
226 * XXX - currently, we do seeking when trying to find
227 * out the file type, so we don't actually support
228 * opening FIFOs. However, we may eventually
229 * do buffering that allows us to do at least some
230 * file type determination even on pipes, so we
231 * allow FIFO opens and let things fail later when
235 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
238 } else if (S_ISDIR(statb.st_mode)) {
240 * Return different errors for "this is a directory"
241 * and "this is some random special file type", so
242 * the user can get a potentially more helpful error.
246 } else if (! S_ISREG(statb.st_mode)) {
247 *err = WTAP_ERR_NOT_REGULAR_FILE;
252 * We need two independent descriptors for random access, so
253 * they have different file positions. If we're opening the
254 * standard input, we can only dup it to get additional
255 * descriptors, so we can't have two independent descriptors,
256 * and thus can't do random access.
258 if (use_stdin && do_random) {
259 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
264 wth = g_malloc(sizeof(wtap));
271 errno = WTAP_ERR_CANT_OPEN;
274 * We dup FD 0, so that we don't have to worry about
275 * an fclose or gzclose of wth->fh closing the standard
276 * input of the process.
278 wth->fd = eth_dup(0);
280 _setmode(wth->fd, O_BINARY);
283 wth->fd = eth_open(filename, O_RDONLY|O_BINARY, 0000 /* no creation so don't matter */);
289 if (!(wth->fh = filed_open(wth->fd, "rb"))) {
297 if (!(wth->random_fh = file_open(filename, "rb"))) {
304 wth->random_fh = NULL;
307 wth->file_encap = WTAP_ENCAP_UNKNOWN;
308 wth->data_offset = 0;
309 wth->subtype_sequential_close = NULL;
310 wth->subtype_close = NULL;
311 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
313 init_open_routines();
315 /* Try all file types */
316 for (i = 0; i < open_routines_arr->len; i++) {
317 /* Seek back to the beginning of the file; the open routine
318 for the previous file type may have left the file
319 position somewhere other than the beginning, and the
320 open routine for this file type will probably want
321 to start reading at the beginning.
323 Initialize the data offset while we're at it. */
324 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
325 /* I/O error - give up */
326 if (wth->random_fh != NULL)
327 file_close(wth->random_fh);
332 wth->data_offset = 0;
334 switch ((*open_routines[i])(wth, err, err_info)) {
337 /* I/O error - give up */
338 if (wth->random_fh != NULL)
339 file_close(wth->random_fh);
345 /* No I/O error, but not that type of file */
349 /* We found the file type */
354 /* Well, it's not one of the types of file we know about. */
355 if (wth->random_fh != NULL)
356 file_close(wth->random_fh);
359 *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
363 wth->frame_buffer = g_malloc(sizeof(struct Buffer));
364 buffer_init(wth->frame_buffer, 1500);
368 /* Table of the file types we know about. */
369 static const struct file_type_info dump_open_table[] = {
370 /* WTAP_FILE_UNKNOWN (only used internally for initialization) */
371 { NULL, NULL, NULL, NULL, FALSE,
374 /* WTAP_FILE_WTAP (only used internally while capturing) */
375 { NULL, NULL, NULL, NULL, FALSE,
379 { "Wireshark/tcpdump/... - libpcap", "libpcap", "*.pcap;*.cap", ".pcap", TRUE,
380 libpcap_dump_can_write_encap, libpcap_dump_open },
382 /* WTAP_FILE_PCAP_NSEC */
383 { "Wireshark - nanosecond libpcap", "nseclibpcap", "*.pcap;*.cap", ".pcap", TRUE,
384 libpcap_dump_can_write_encap, libpcap_dump_open },
386 /* WTAP_FILE_PCAP_AIX */
387 { "AIX tcpdump - libpcap", "aixlibpcap", "*.pcap;*.cap", ".pcap", TRUE,
390 /* WTAP_FILE_PCAP_SS991029 */
391 { "Modified tcpdump - libpcap", "modlibpcap", "*.pcap;*.cap", ".pcap", TRUE,
392 libpcap_dump_can_write_encap, libpcap_dump_open },
394 /* WTAP_FILE_PCAP_NOKIA */
395 { "Nokia tcpdump - libpcap ", "nokialibpcap", "*.pcap;*.cap", ".pcap", TRUE,
396 libpcap_dump_can_write_encap, libpcap_dump_open },
398 /* WTAP_FILE_PCAP_SS990417 */
399 { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "*.pcap;*.cap", ".pcap", TRUE,
400 libpcap_dump_can_write_encap, libpcap_dump_open },
402 /* WTAP_FILE_PCAP_SS990915 */
403 { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "*.pcap;*.cap", ".pcap", TRUE,
404 libpcap_dump_can_write_encap, libpcap_dump_open },
406 /* WTAP_FILE_5VIEWS */
407 { "Accellent 5Views capture", "5views", "*.5vw", ".5vw", FALSE,
408 _5views_dump_can_write_encap, _5views_dump_open },
410 /* WTAP_FILE_IPTRACE_1_0 */
411 { "AIX iptrace 1.0", "iptrace_1", "*.*", NULL, FALSE,
414 /* WTAP_FILE_IPTRACE_2_0 */
415 { "AIX iptrace 2.0", "iptrace_2", "*.*", NULL, FALSE,
419 { "ASN.1 Basic Encoding Rules", "ber", "*.*", NULL, FALSE,
422 /* WTAP_FILE_HCIDUMP */
423 { "Bluetooth HCI dump", "hcidump", "*.*", NULL, FALSE,
426 /* WTAP_FILE_CATAPULT_DCT2000 */
427 { "Catapult DCT2000 trace (.out format)", "dct2000", "*.out", ".out", FALSE,
428 catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open },
430 /* WTAP_FILE_NETXRAY_OLD */
431 { "Cinco Networks NetXRay 1.x", "netxray1", "*.cap", ".cap", FALSE,
434 /* WTAP_FILE_NETXRAY_1_0 */
435 { "Cinco Networks NetXRay 2.0 or later", "netxray2", "*.cap", ".cap", FALSE,
438 /* WTAP_FILE_COSINE */
439 { "CoSine IPSX L2 capture", "cosine", "*.*", NULL, FALSE,
442 /* WTAP_FILE_CSIDS */
443 { "CSIDS IPLog", "csids", "*.*", NULL, FALSE,
446 /* WTAP_FILE_DBS_ETHERWATCH */
447 { "DBS Etherwatch (VMS)", "etherwatch", "*.*", NULL, FALSE,
451 { "Endace DAG capture", "erf", "*.erf", ".erf", FALSE,
454 /* WTAP_FILE_EYESDN */
455 { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "*.*", NULL, FALSE,
458 /* WTAP_FILE_NETTL */
459 { "HP-UX nettl trace", "nettl", "*.TRC0;*.TRC1", ".TRC0", FALSE,
460 nettl_dump_can_write_encap, nettl_dump_open },
462 /* WTAP_FILE_ISERIES */
463 { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "*.*", NULL, FALSE,
466 /* WTAP_FILE_ISERIES_UNICODE */
467 { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "*.*", NULL, FALSE,
470 /* WTAP_FILE_I4BTRACE */
471 { "I4B ISDN trace", "i4btrace", "*.*", NULL, FALSE,
474 /* WTAP_FILE_ASCEND */
475 { "Lucent/Ascend access server trace", "ascend", "*.*", NULL, FALSE,
478 /* WTAP_FILE_NETMON_1_x */
479 { "Microsoft NetMon 1.x", "netmon1", "*.cap", ".cap", FALSE,
480 netmon_dump_can_write_encap, netmon_dump_open },
482 /* WTAP_FILE_NETMON_2_x */
483 { "Microsoft NetMon 2.x", "netmon2", "*.cap", ".cap", FALSE,
484 netmon_dump_can_write_encap, netmon_dump_open },
486 /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
487 { "NA Sniffer (DOS)", "ngsniffer", "*.cap;*.enc;*.trc;*.fdc;*.syc", ".cap", FALSE,
488 ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
490 /* WTAP_FILE_NGSNIFFER_COMPRESSED */
491 { "NA Sniffer (DOS), compressed", "ngsniffer_comp", "*.caz", ".caz", FALSE,
494 /* WTAP_FILE_NETXRAY_1_1 */
495 { "NA Sniffer (Windows) 1.1", "ngwsniffer_1_1", "*.cap", ".cap", FALSE,
496 netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 },
498 /* WTAP_FILE_NETXRAY_2_00x */
499 { "NA Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "*.cap", ".cap", FALSE,
500 netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 },
502 /* WTAP_FILE_NETWORK_INSTRUMENTS_V9 */
503 { "Network Instruments Observer (V9)", "niobserverv9", "*.bfr", ".bfr", FALSE,
504 network_instruments_dump_can_write_encap, network_instruments_dump_open },
506 /* WTAP_FILE_LANALYZER */
507 { "Novell LANalyzer","lanalyzer", "*.tr1", ".tr1", FALSE,
508 lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
510 /* WTAP_FILE_PPPDUMP */
511 { "pppd log (pppdump format)", "pppd", "*.*", NULL, FALSE,
514 /* WTAP_FILE_RADCOM */
515 { "RADCOM WAN/LAN analyzer", "radcom", "*.*", NULL, FALSE,
518 /* WTAP_FILE_SNOOP */
519 { "Sun snoop", "snoop", "*.snoop;*.cap", ".snoop", FALSE,
520 snoop_dump_can_write_encap, snoop_dump_open },
522 /* WTAP_FILE_SHOMITI */
523 { "Shomiti/Finisar Surveyor", "shomiti", "*.cap", ".cap", FALSE,
527 { "TCPIPtrace (VMS)", "tcpiptrace", "*.*", NULL, FALSE,
531 { "Tektronix K12xx 32-bit .rf5 format", "rf5", "*.rf5", ".rf5", TRUE,
532 k12_dump_can_write_encap, k12_dump_open },
534 /* WTAP_FILE_TOSHIBA */
535 { "Toshiba Compact ISDN Router snoop", "toshiba", "*.*", NULL, FALSE,
538 /* WTAP_FILE_VISUAL_NETWORKS */
539 { "Visual Networks traffic capture", "visual", "*.*", NULL, FALSE,
540 visual_dump_can_write_encap, visual_dump_open },
542 /* WTAP_FILE_ETHERPEEK_V56 */
543 { "Wildpacket Ether/TokenPeek (V5 & V6)", "peek56", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
546 /* WTAP_FILE_ETHERPEEK_V7 */
547 { "Wildpacket Ether/Token/AiroPeek (V7)", "peek7", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
550 /* WTAP_FILE_ETHERPEEK_V9 */
551 { "Wildpacket Ether/AiroPeek (V9)", "peek9", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
555 { "MPEG", "mpeg", "*.mpeg;*.mpg;*.mp3", ".mpeg", FALSE,
558 /* WTAP_FILE_K12TEXT */
559 { "K12 text file", "k12text", "*.txt", ".txt", TRUE,
560 k12text_dump_can_write_encap, k12text_dump_open },
563 gint wtap_num_file_types = sizeof(dump_open_table) / sizeof(struct file_type_info);
565 /* Name that should be somewhat descriptive. */
566 const char *wtap_file_type_string(int filetype)
568 if (filetype < 0 || filetype >= WTAP_NUM_FILE_TYPES) {
569 g_error("Unknown capture file type %d", filetype);
572 return dump_open_table[filetype].name;
575 /* Name to use in, say, a command-line flag specifying the type. */
576 const char *wtap_file_type_short_string(int filetype)
578 if (filetype < 0 || filetype >= WTAP_NUM_FILE_TYPES)
581 return dump_open_table[filetype].short_name;
584 /* Translate a short name to a capture file type. */
585 int wtap_short_string_to_file_type(const char *short_name)
589 for (filetype = 0; filetype < WTAP_NUM_FILE_TYPES; filetype++) {
590 if (dump_open_table[filetype].short_name != NULL &&
591 strcmp(short_name, dump_open_table[filetype].short_name) == 0)
594 return -1; /* no such file type, or we can't write it */
597 /* file extensions to use. */
598 const char *wtap_file_extensions_string(int filetype)
600 if (filetype < 0 || filetype >= WTAP_NUM_FILE_TYPES)
603 return dump_open_table[filetype].file_extensions;
606 /* default file extension to use. */
607 const char *wtap_file_extension_default_string(int filetype)
609 if (filetype < 0 || filetype >= WTAP_NUM_FILE_TYPES)
612 return dump_open_table[filetype].file_extension_default;
615 gboolean wtap_dump_can_open(int filetype)
617 if (filetype < 0 || filetype >= WTAP_NUM_FILE_TYPES
618 || dump_open_table[filetype].dump_open == NULL)
624 gboolean wtap_dump_can_write_encap(int filetype, int encap)
626 if (filetype < 0 || filetype >= WTAP_NUM_FILE_TYPES
627 || dump_open_table[filetype].can_write_encap == NULL)
630 if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
636 gboolean wtap_dump_can_compress(int filetype)
639 if (filetype < 0 || filetype >= WTAP_NUM_FILE_TYPES
640 || dump_open_table[filetype].can_compress == FALSE)
650 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
651 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
652 gboolean compressed, int *err);
653 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err);
655 static FILE *wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
656 static FILE *wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
657 static int wtap_dump_file_close(wtap_dumper *wdh);
659 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
660 int snaplen, gboolean compressed, int *err)
665 /* Check whether we can open a capture file with that file type
666 and that encapsulation. */
667 if (!wtap_dump_open_check(filetype, encap, compressed, err))
670 /* Allocate a data structure for the output stream. */
671 wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
673 return NULL; /* couldn't allocate it */
675 /* "-" means stdout */
676 if (strcmp(filename, "-") == 0) {
679 return NULL; /* compress won't work on stdout */
682 setmode(fileno(stdout), O_BINARY);
686 /* In case "fopen()" fails but doesn't set "errno", set "errno"
687 to a generic "the open failed" error. */
688 errno = WTAP_ERR_CANT_OPEN;
689 fh = wtap_dump_file_open(wdh, filename);
693 return NULL; /* can't create file */
698 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
699 /* Get rid of the file we created; we couldn't finish
701 if (wdh->fh != stdout) {
702 wtap_dump_file_close(wdh);
703 eth_unlink(filename);
711 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
712 gboolean compressed, int *err)
717 /* Check whether we can open a capture file with that file type
718 and that encapsulation. */
719 if (!wtap_dump_open_check(filetype, encap, compressed, err))
722 /* Allocate a data structure for the output stream. */
723 wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
725 return NULL; /* couldn't allocate it */
729 setmode(fileno(stdout), O_BINARY);
733 /* In case "fopen()" fails but doesn't set "errno", set "errno"
734 to a generic "the open failed" error. */
735 errno = WTAP_ERR_CANT_OPEN;
736 fh = wtap_dump_file_fdopen(wdh, fd);
740 return NULL; /* can't create standard I/O stream */
744 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
745 wtap_dump_file_close(wdh);
752 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err)
754 if (!wtap_dump_can_open(filetype)) {
755 /* Invalid type, or type we don't know how to write. */
756 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
760 /* OK, we know how to write that type; can we write the specified
761 encapsulation type? */
762 *err = (*dump_open_table[filetype].can_write_encap)(encap);
766 /* if compression is wanted, do we support this for this filetype? */
767 if(compressed && !wtap_dump_can_compress(filetype)) {
768 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
772 *err = (*dump_open_table[filetype].can_write_encap)(encap);
777 /* All systems go! */
781 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
782 gboolean compressed, int *err)
786 wdh = g_malloc(sizeof (wtap_dumper));
792 wdh->file_type = filetype;
793 wdh->snaplen = snaplen;
795 wdh->compressed = compressed;
796 wdh->bytes_dumped = 0;
797 wdh->dump.opaque = NULL;
798 wdh->subtype_write = NULL;
799 wdh->subtype_close = NULL;
803 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err)
808 /* Can we do a seek on the file descriptor?
809 If not, note that fact. */
813 fd = fileno(wdh->fh);
814 if (lseek(fd, 1, SEEK_CUR) == -1)
818 lseek(fd, 0, SEEK_SET);
823 /* Now try to open the file for writing. */
824 if (!(*dump_open_table[filetype].dump_open)(wdh, cant_seek, err)) {
828 return TRUE; /* success! */
831 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
832 const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err)
834 return (wdh->subtype_write)(wdh, phdr, pseudo_header, pd, err);
837 void wtap_dump_flush(wtap_dumper *wdh)
840 if(wdh->compressed) {
841 gzflush(wdh->fh, Z_SYNC_FLUSH); /* XXX - is Z_SYNC_FLUSH the right one? */
849 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
853 if (wdh->subtype_close != NULL) {
854 /* There's a close routine for this dump stream. */
855 if (!(wdh->subtype_close)(wdh, err))
858 errno = WTAP_ERR_CANT_CLOSE;
859 /* Don't close stdout */
860 if (wdh->fh != stdout) {
861 if (wtap_dump_file_close(wdh) == EOF) {
863 /* The per-format close function succeeded,
864 but the fclose didn't. Save the reason
865 why, if our caller asked for it. */
872 /* as we don't close stdout, at least try to flush it */
873 wtap_dump_flush(wdh);
875 if (wdh->dump.opaque != NULL)
876 g_free(wdh->dump.opaque);
881 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
883 return wdh->bytes_dumped;
886 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
888 wdh->bytes_dumped = bytes_dumped;
892 /* internally open a file for writing (compressed or not) */
893 static FILE *wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
896 if(wdh->compressed) {
897 return gzopen(filename, "wb");
901 return eth_fopen(filename, "wb");
905 /* internally open a file for writing (compressed or not) */
906 static FILE *wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
909 if(wdh->compressed) {
910 return gzdopen(fd, "wb");
914 return fdopen(fd, "wb");
918 /* internally writing raw bytes (compressed or not) */
919 size_t wtap_dump_file_write(wtap_dumper *wdh, const void *buf, unsigned bufsize)
922 if(wdh->compressed) {
923 return gzwrite(wdh->fh, buf, bufsize);
927 return fwrite(buf, 1, bufsize, wdh->fh);
931 /* internally close a file for writing (compressed or not) */
932 static int wtap_dump_file_close(wtap_dumper *wdh)
935 if(wdh->compressed) {
936 return gzclose(wdh->fh);
940 return fclose(wdh->fh);
944 int wtap_dump_file_ferror(wtap_dumper *wdh)
949 if(wdh->compressed) {
950 gzerror(wdh->fh, &errnum);
952 if(errnum == Z_ERRNO) {
955 /* XXX - what to do with this zlib specific number? */
961 return ferror(wdh->fh);