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 <wsutil/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"
76 #include "netscreen.h"
81 #include "dct3trace.h"
82 #include "packetlogger.h"
83 #include "daintree-sna.h"
84 #include "netscaler.h"
87 /* The open_file_* routines should return:
91 * 1 if the file they're reading is one of the types it handles;
93 * 0 if the file they're reading isn't the type they're checking for.
95 * If the routine handles this type of file, it should set the "file_type"
96 * field in the "struct wtap" to the type of the file.
98 * Put the trace files that are merely saved telnet-sessions last, since it's
99 * possible that you could have captured someone a router telnet-session
100 * using another tool. So, a libpcap trace of an toshiba "snoop" session
101 * should be discovered as a libpcap file, not a toshiba file.
105 static wtap_open_routine_t open_routines_base[] = {
106 /* Files that have magic bytes in fixed locations. These
107 * are easy to identify.
120 network_instruments_open,
124 catapult_dct2000_open,
128 packetlogger_open, /* This type does not have a magic number, but its
129 * files are sometimes grabbed by mpeg_open. */
134 /* Files that don't have magic bytes at a fixed location,
135 * but that instead require a heuristic of some sort to
136 * identify them. This includes the ASCII trace files that
137 * would be, for example, saved copies of a Telnet session
141 /* I put NetScreen *before* erf, because there were some
142 * false positives with my test-files (Sake Blok, July 2007)
162 #define N_FILE_TYPES (sizeof open_routines_base / sizeof open_routines_base[0])
164 static wtap_open_routine_t* open_routines = NULL;
166 static GArray* open_routines_arr = NULL;
169 /* initialize the open routines array if it has not being initialized yet */
170 static void init_open_routines(void) {
172 if (open_routines_arr) return;
174 open_routines_arr = g_array_new(FALSE,TRUE,sizeof(wtap_open_routine_t));
176 g_array_append_vals(open_routines_arr,open_routines_base,N_FILE_TYPES);
178 open_routines = (void*)open_routines_arr->data;
181 void wtap_register_open_routine(wtap_open_routine_t open_routine, gboolean has_magic) {
182 init_open_routines();
185 g_array_prepend_val(open_routines_arr,open_routine);
187 g_array_append_val(open_routines_arr,open_routine);
189 open_routines = (void*)open_routines_arr->data;
193 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
194 * define them either.)
196 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
199 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
202 #define S_IFIFO _S_IFIFO
205 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
208 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
211 /* Opens a file and prepares a wtap struct.
212 If "do_random" is TRUE, it opens the file twice; the second open
213 allows the application to do random-access I/O without moving
214 the seek offset for sequential I/O, which is used by Wireshark
215 so that it can do sequential I/O to a capture file that's being
216 written to as new packets arrive independently of random I/O done
217 to display protocol trees for packets when they're selected. */
218 wtap* wtap_open_offline(const char *filename, int *err, char **err_info,
224 gboolean use_stdin = FALSE;
226 /* open standard input if filename is '-' */
227 if (strcmp(filename, "-") == 0)
230 /* First, make sure the file is valid */
232 if (fstat(0, &statb) < 0) {
237 if (ws_stat(filename, &statb) < 0) {
242 if (S_ISFIFO(statb.st_mode)) {
244 * Opens of FIFOs are allowed only when not opening
247 * XXX - currently, we do seeking when trying to find
248 * out the file type, so we don't actually support
249 * opening FIFOs. However, we may eventually
250 * do buffering that allows us to do at least some
251 * file type determination even on pipes, so we
252 * allow FIFO opens and let things fail later when
256 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
259 } else if (S_ISDIR(statb.st_mode)) {
261 * Return different errors for "this is a directory"
262 * and "this is some random special file type", so
263 * the user can get a potentially more helpful error.
267 } else if (! S_ISREG(statb.st_mode)) {
268 *err = WTAP_ERR_NOT_REGULAR_FILE;
273 * We need two independent descriptors for random access, so
274 * they have different file positions. If we're opening the
275 * standard input, we can only dup it to get additional
276 * descriptors, so we can't have two independent descriptors,
277 * and thus can't do random access.
279 if (use_stdin && do_random) {
280 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
285 wth = g_malloc(sizeof(wtap));
292 errno = WTAP_ERR_CANT_OPEN;
295 * We dup FD 0, so that we don't have to worry about
296 * an fclose or gzclose of wth->fh closing the standard
297 * input of the process.
301 _setmode(wth->fd, O_BINARY);
304 wth->fd = ws_open(filename, O_RDONLY|O_BINARY, 0000 /* no creation so don't matter */);
310 if (!(wth->fh = filed_open(wth->fd, "rb"))) {
318 if (!(wth->random_fh = file_open(filename, "rb"))) {
325 wth->random_fh = NULL;
328 wth->file_encap = WTAP_ENCAP_UNKNOWN;
329 wth->data_offset = 0;
330 wth->subtype_sequential_close = NULL;
331 wth->subtype_close = NULL;
332 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
334 init_open_routines();
336 /* Try all file types */
337 for (i = 0; i < open_routines_arr->len; i++) {
338 /* Seek back to the beginning of the file; the open routine
339 for the previous file type may have left the file
340 position somewhere other than the beginning, and the
341 open routine for this file type will probably want
342 to start reading at the beginning.
344 Initialize the data offset while we're at it. */
345 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
346 /* I/O error - give up */
347 if (wth->random_fh != NULL)
348 file_close(wth->random_fh);
353 wth->data_offset = 0;
355 switch ((*open_routines[i])(wth, err, err_info)) {
358 /* I/O error - give up */
359 if (wth->random_fh != NULL)
360 file_close(wth->random_fh);
366 /* No I/O error, but not that type of file */
370 /* We found the file type */
375 /* Well, it's not one of the types of file we know about. */
376 if (wth->random_fh != NULL)
377 file_close(wth->random_fh);
380 *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
384 wth->frame_buffer = g_malloc(sizeof(struct Buffer));
385 buffer_init(wth->frame_buffer, 1500);
389 /* Table of the file types we know about. */
390 static const struct file_type_info dump_open_table_base[] = {
391 /* WTAP_FILE_UNKNOWN (only used internally for initialization) */
392 { NULL, NULL, NULL, NULL, FALSE,
395 /* WTAP_FILE_WTAP (only used internally while capturing) */
396 { NULL, NULL, NULL, NULL, FALSE,
400 { "Wireshark/tcpdump/... - libpcap", "libpcap", "*.pcap;*.cap", ".pcap", TRUE,
401 libpcap_dump_can_write_encap, libpcap_dump_open },
403 /* WTAP_FILE_PCAP_NSEC */
404 { "Wireshark - nanosecond libpcap", "nseclibpcap", "*.pcap;*.cap", ".pcap", TRUE,
405 libpcap_dump_can_write_encap, libpcap_dump_open },
407 /* WTAP_FILE_PCAP_AIX */
408 { "AIX tcpdump - libpcap", "aixlibpcap", "*.pcap;*.cap", ".pcap", TRUE,
411 /* WTAP_FILE_PCAP_SS991029 */
412 { "Modified tcpdump - libpcap", "modlibpcap", "*.pcap;*.cap", ".pcap", TRUE,
413 libpcap_dump_can_write_encap, libpcap_dump_open },
415 /* WTAP_FILE_PCAP_NOKIA */
416 { "Nokia tcpdump - libpcap ", "nokialibpcap", "*.pcap;*.cap", ".pcap", TRUE,
417 libpcap_dump_can_write_encap, libpcap_dump_open },
419 /* WTAP_FILE_PCAP_SS990417 */
420 { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "*.pcap;*.cap", ".pcap", TRUE,
421 libpcap_dump_can_write_encap, libpcap_dump_open },
423 /* WTAP_FILE_PCAP_SS990915 */
424 { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "*.pcap;*.cap", ".pcap", TRUE,
425 libpcap_dump_can_write_encap, libpcap_dump_open },
427 /* WTAP_FILE_5VIEWS */
428 { "Accellent 5Views capture", "5views", "*.5vw", ".5vw", FALSE,
429 _5views_dump_can_write_encap, _5views_dump_open },
431 /* WTAP_FILE_IPTRACE_1_0 */
432 { "AIX iptrace 1.0", "iptrace_1", "*.*", NULL, FALSE,
435 /* WTAP_FILE_IPTRACE_2_0 */
436 { "AIX iptrace 2.0", "iptrace_2", "*.*", NULL, FALSE,
440 { "ASN.1 Basic Encoding Rules", "ber", "*.*", NULL, FALSE,
443 /* WTAP_FILE_HCIDUMP */
444 { "Bluetooth HCI dump", "hcidump", "*.*", NULL, FALSE,
447 /* WTAP_FILE_CATAPULT_DCT2000 */
448 { "Catapult DCT2000 trace (.out format)", "dct2000", "*.out", ".out", FALSE,
449 catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open },
451 /* WTAP_FILE_NETXRAY_OLD */
452 { "Cinco Networks NetXRay 1.x", "netxray1", "*.cap", ".cap", FALSE,
455 /* WTAP_FILE_NETXRAY_1_0 */
456 { "Cinco Networks NetXRay 2.0 or later", "netxray2", "*.cap", ".cap", FALSE,
459 /* WTAP_FILE_COSINE */
460 { "CoSine IPSX L2 capture", "cosine", "*.*", NULL, FALSE,
463 /* WTAP_FILE_CSIDS */
464 { "CSIDS IPLog", "csids", "*.*", NULL, FALSE,
467 /* WTAP_FILE_DBS_ETHERWATCH */
468 { "DBS Etherwatch (VMS)", "etherwatch", "*.*", NULL, FALSE,
472 { "Endace ERF capture", "erf", "*.erf", ".erf", FALSE,
475 /* WTAP_FILE_EYESDN */
476 { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "*.*", NULL, FALSE,
479 /* WTAP_FILE_NETTL */
480 { "HP-UX nettl trace", "nettl", "*.TRC0;*.TRC1", ".TRC0", FALSE,
481 nettl_dump_can_write_encap, nettl_dump_open },
483 /* WTAP_FILE_ISERIES */
484 { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "*.*", NULL, FALSE,
487 /* WTAP_FILE_ISERIES_UNICODE */
488 { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "*.*", NULL, FALSE,
491 /* WTAP_FILE_I4BTRACE */
492 { "I4B ISDN trace", "i4btrace", "*.*", NULL, FALSE,
495 /* WTAP_FILE_ASCEND */
496 { "Lucent/Ascend access server trace", "ascend", "*.*", NULL, FALSE,
499 /* WTAP_FILE_NETMON_1_x */
500 { "Microsoft NetMon 1.x", "netmon1", "*.cap", ".cap", FALSE,
501 netmon_dump_can_write_encap, netmon_dump_open },
503 /* WTAP_FILE_NETMON_2_x */
504 { "Microsoft NetMon 2.x", "netmon2", "*.cap", ".cap", FALSE,
505 netmon_dump_can_write_encap, netmon_dump_open },
507 /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
508 { "NA Sniffer (DOS)", "ngsniffer", "*.cap;*.enc;*.trc;*.fdc;*.syc", ".cap", FALSE,
509 ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
511 /* WTAP_FILE_NGSNIFFER_COMPRESSED */
512 { "NA Sniffer (DOS), compressed", "ngsniffer_comp", "*.caz", ".caz", FALSE,
515 /* WTAP_FILE_NETXRAY_1_1 */
516 { "NA Sniffer (Windows) 1.1", "ngwsniffer_1_1", "*.cap", ".cap", FALSE,
517 netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 },
519 /* WTAP_FILE_NETXRAY_2_00x */
520 { "NA Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "*.cap", ".cap", FALSE,
521 netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 },
523 /* WTAP_FILE_NETWORK_INSTRUMENTS_V9 */
524 { "Network Instruments Observer (V9)", "niobserverv9", "*.bfr", ".bfr", FALSE,
525 network_instruments_dump_can_write_encap, network_instruments_dump_open },
527 /* WTAP_FILE_LANALYZER */
528 { "Novell LANalyzer","lanalyzer", "*.tr1", ".tr1", FALSE,
529 lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
531 /* WTAP_FILE_PPPDUMP */
532 { "pppd log (pppdump format)", "pppd", "*.*", NULL, FALSE,
535 /* WTAP_FILE_RADCOM */
536 { "RADCOM WAN/LAN analyzer", "radcom", "*.*", NULL, FALSE,
539 /* WTAP_FILE_SNOOP */
540 { "Sun snoop", "snoop", "*.snoop;*.cap", ".snoop", FALSE,
541 snoop_dump_can_write_encap, snoop_dump_open },
543 /* WTAP_FILE_SHOMITI */
544 { "Shomiti/Finisar Surveyor", "shomiti", "*.cap", ".cap", FALSE,
548 { "TCPIPtrace (VMS)", "tcpiptrace", "*.*", NULL, FALSE,
552 { "Tektronix K12xx 32-bit .rf5 format", "rf5", "*.rf5", ".rf5", TRUE,
553 k12_dump_can_write_encap, k12_dump_open },
555 /* WTAP_FILE_TOSHIBA */
556 { "Toshiba Compact ISDN Router snoop", "toshiba", "*.*", NULL, FALSE,
559 /* WTAP_FILE_VISUAL_NETWORKS */
560 { "Visual Networks traffic capture", "visual", "*.*", NULL, FALSE,
561 visual_dump_can_write_encap, visual_dump_open },
563 /* WTAP_FILE_ETHERPEEK_V56 */
564 { "Wildpacket Ether/TokenPeek (V5 & V6)", "peek56", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
567 /* WTAP_FILE_ETHERPEEK_V7 */
568 { "Wildpacket Ether/Token/AiroPeek (V7)", "peek7", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
571 /* WTAP_FILE_ETHERPEEK_V9 */
572 { "Wildpacket Ether/AiroPeek (V9)", "peek9", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
576 { "MPEG", "mpeg", "*.mpeg;*.mpg;*.mp3", ".mpeg", FALSE,
579 /* WTAP_FILE_K12TEXT */
580 { "K12 text file", "k12text", "*.txt", ".txt", TRUE,
581 k12text_dump_can_write_encap, k12text_dump_open },
583 /* WTAP_FILE_NETSCREEN */
584 { "NetScreen snoop text file", "netscreen", "*.*", NULL, FALSE,
587 /* WTAP_FILE_COMMVIEW */
588 { "TamoSoft CommView", "commview", "*.ncf", ".ncf", TRUE,
589 commview_dump_can_write_encap, commview_dump_open },
591 /* WTAP_FILE_PCAPNG */
592 { "Wireshark - pcapng (experimental)", "pcapng", "*.pcapng", NULL, FALSE,
593 pcapng_dump_can_write_encap, pcapng_dump_open },
595 /* WTAP_FILE_BTSNOOP */
596 { "Symbian OS btsnoop", "btsnoop", "*.log", ".log", FALSE,
597 btsnoop_dump_can_write_encap, btsnoop_dump_open_h4 },
599 /* WTAP_FILE_X2E_XORAYA */
600 { NULL, NULL, NULL, NULL, FALSE, NULL, NULL },
603 { "Transport-Neutral Encapsulation Format", "tnef", "*.*", NULL, FALSE, NULL, NULL },
605 /* WTAP_FILE_DCT3TRACE */
606 { "Gammu DCT3 trace", "dct3trace", "*.xml", NULL, FALSE, NULL, NULL },
608 /* WTAP_FILE_PACKETLOGGER */
609 { "PacketLogger", "pklg", "*.pklg", NULL, FALSE, NULL, NULL },
611 /* WTAP_FILE_DAINTREE_SNA */
612 { "Daintree SNA", "dsna", "*.dcf", NULL, FALSE, NULL, NULL },
614 /* WTAP_FILE_NETSCALER_1_0 */
615 { "NetScaler Trace (Version 1.0)", "nstrace10", "*.*", "*.*", FALSE,
616 nstrace_10_dump_can_write_encap, nstrace_dump_open },
618 /* WTAP_FILE_NETSCALER_2_0 */
619 { "NetScaler Trace (Version 2.0)", "nstrace20", "*.cap", "*.cap", FALSE,
620 nstrace_20_dump_can_write_encap, nstrace_dump_open },
624 gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info);
626 static GArray* dump_open_table_arr = NULL;
627 static const struct file_type_info* dump_open_table = dump_open_table_base;
629 /* initialize the open routines array if it has not being initialized yet */
630 static void init_file_types(void) {
632 if (dump_open_table_arr) return;
634 dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_info));
636 g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types);
638 dump_open_table = (void*)dump_open_table_arr->data;
641 int wtap_register_file_type(const struct file_type_info* fi) {
644 g_array_append_val(dump_open_table_arr,*fi);
646 dump_open_table = (void*)dump_open_table_arr->data;
648 return wtap_num_file_types++;
651 int wtap_get_num_file_types(void)
653 return wtap_num_file_types;
656 /* Name that should be somewhat descriptive. */
657 const char *wtap_file_type_string(int filetype)
659 if (filetype < 0 || filetype >= wtap_num_file_types) {
660 g_error("Unknown capture file type %d", filetype);
663 return dump_open_table[filetype].name;
666 /* Name to use in, say, a command-line flag specifying the type. */
667 const char *wtap_file_type_short_string(int filetype)
669 if (filetype < 0 || filetype >= wtap_num_file_types)
672 return dump_open_table[filetype].short_name;
675 /* Translate a short name to a capture file type. */
676 int wtap_short_string_to_file_type(const char *short_name)
680 for (filetype = 0; filetype < wtap_num_file_types; filetype++) {
681 if (dump_open_table[filetype].short_name != NULL &&
682 strcmp(short_name, dump_open_table[filetype].short_name) == 0)
685 return -1; /* no such file type, or we can't write it */
688 /* file extensions to use. */
689 const char *wtap_file_extensions_string(int filetype)
691 if (filetype < 0 || filetype >= wtap_num_file_types)
694 return dump_open_table[filetype].file_extensions;
697 /* default file extension to use. */
698 const char *wtap_file_extension_default_string(int filetype)
700 if (filetype < 0 || filetype >= wtap_num_file_types)
703 return dump_open_table[filetype].file_extension_default;
706 gboolean wtap_dump_can_open(int filetype)
708 if (filetype < 0 || filetype >= wtap_num_file_types
709 || dump_open_table[filetype].dump_open == NULL)
715 gboolean wtap_dump_can_write_encap(int filetype, int encap)
717 if (filetype < 0 || filetype >= wtap_num_file_types
718 || dump_open_table[filetype].can_write_encap == NULL)
721 if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
728 gboolean wtap_dump_can_compress(int filetype)
730 if (filetype < 0 || filetype >= wtap_num_file_types
731 || dump_open_table[filetype].can_compress == FALSE)
737 gboolean wtap_dump_can_compress(int filetype _U_)
744 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
745 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
746 gboolean compressed, int *err);
747 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err);
749 static FILE *wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
750 static FILE *wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
751 static int wtap_dump_file_close(wtap_dumper *wdh);
753 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
754 int snaplen, gboolean compressed, int *err)
759 /* Check whether we can open a capture file with that file type
760 and that encapsulation. */
761 if (!wtap_dump_open_check(filetype, encap, compressed, err))
764 /* Allocate a data structure for the output stream. */
765 wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
767 return NULL; /* couldn't allocate it */
769 /* "-" means stdout */
770 if (strcmp(filename, "-") == 0) {
773 return NULL; /* compress won't work on stdout */
776 setmode(fileno(stdout), O_BINARY);
780 /* In case "fopen()" fails but doesn't set "errno", set "errno"
781 to a generic "the open failed" error. */
782 errno = WTAP_ERR_CANT_OPEN;
783 fh = wtap_dump_file_open(wdh, filename);
787 return NULL; /* can't create file */
792 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
793 /* Get rid of the file we created; we couldn't finish
795 if (wdh->fh != stdout) {
796 wtap_dump_file_close(wdh);
805 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
806 gboolean compressed, int *err)
811 /* Check whether we can open a capture file with that file type
812 and that encapsulation. */
813 if (!wtap_dump_open_check(filetype, encap, compressed, err))
816 /* Allocate a data structure for the output stream. */
817 wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
819 return NULL; /* couldn't allocate it */
823 setmode(fileno(stdout), O_BINARY);
827 /* In case "fopen()" fails but doesn't set "errno", set "errno"
828 to a generic "the open failed" error. */
829 errno = WTAP_ERR_CANT_OPEN;
830 fh = wtap_dump_file_fdopen(wdh, fd);
834 return NULL; /* can't create standard I/O stream */
838 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
839 wtap_dump_file_close(wdh);
846 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err)
848 if (!wtap_dump_can_open(filetype)) {
849 /* Invalid type, or type we don't know how to write. */
850 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
854 /* OK, we know how to write that type; can we write the specified
855 encapsulation type? */
856 *err = (*dump_open_table[filetype].can_write_encap)(encap);
860 /* if compression is wanted, do we support this for this filetype? */
861 if(compressed && !wtap_dump_can_compress(filetype)) {
862 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
866 *err = (*dump_open_table[filetype].can_write_encap)(encap);
871 /* All systems go! */
875 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
876 gboolean compressed, int *err)
880 wdh = g_malloc(sizeof (wtap_dumper));
886 wdh->file_type = filetype;
887 wdh->snaplen = snaplen;
889 wdh->compressed = compressed;
890 wdh->bytes_dumped = 0;
891 wdh->dump.opaque = NULL;
892 wdh->subtype_write = NULL;
893 wdh->subtype_close = NULL;
897 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err)
902 /* Can we do a seek on the file descriptor?
903 If not, note that fact. */
907 fd = fileno(wdh->fh);
908 if (lseek(fd, 1, SEEK_CUR) == -1)
912 lseek(fd, 0, SEEK_SET);
917 /* Now try to open the file for writing. */
918 if (!(*dump_open_table[filetype].dump_open)(wdh, cant_seek, err)) {
922 return TRUE; /* success! */
925 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
926 const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err)
928 return (wdh->subtype_write)(wdh, phdr, pseudo_header, pd, err);
931 void wtap_dump_flush(wtap_dumper *wdh)
934 if(wdh->compressed) {
935 gzflush(wdh->fh, Z_SYNC_FLUSH); /* XXX - is Z_SYNC_FLUSH the right one? */
943 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
947 if (wdh->subtype_close != NULL) {
948 /* There's a close routine for this dump stream. */
949 if (!(wdh->subtype_close)(wdh, err))
952 errno = WTAP_ERR_CANT_CLOSE;
953 /* Don't close stdout */
954 if (wdh->fh != stdout) {
955 if (wtap_dump_file_close(wdh) == EOF) {
957 /* The per-format close function succeeded,
958 but the fclose didn't. Save the reason
959 why, if our caller asked for it. */
966 /* as we don't close stdout, at least try to flush it */
967 wtap_dump_flush(wdh);
969 if (wdh->dump.opaque != NULL)
970 g_free(wdh->dump.opaque);
975 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
977 return wdh->bytes_dumped;
980 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
982 wdh->bytes_dumped = bytes_dumped;
986 /* internally open a file for writing (compressed or not) */
988 static FILE *wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
990 if(wdh->compressed) {
991 return gzopen(filename, "wb");
993 return ws_fopen(filename, "wb");
997 static FILE *wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
999 return ws_fopen(filename, "wb");
1003 /* internally open a file for writing (compressed or not) */
1005 static FILE *wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
1007 if(wdh->compressed) {
1008 return gzdopen(fd, "wb");
1010 return fdopen(fd, "wb");
1014 static FILE *wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
1016 return fdopen(fd, "wb");
1020 /* internally writing raw bytes (compressed or not) */
1021 size_t wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize)
1024 if(wdh->compressed) {
1025 return gzwrite(wdh->fh, buf, (unsigned) bufsize);
1029 return fwrite(buf, 1, bufsize, wdh->fh);
1033 gboolean wtap_dump_file_write_all(wtap_dumper *wdh, const void *buf, unsigned bufsize, int *err)
1037 nwritten = wtap_dump_file_write(wdh, buf, bufsize);
1038 if (nwritten != bufsize) {
1039 if (nwritten == 0 && wtap_dump_file_ferror(wdh))
1040 *err = wtap_dump_file_ferror(wdh);
1042 *err = WTAP_ERR_SHORT_WRITE;
1048 /* internally close a file for writing (compressed or not) */
1049 static int wtap_dump_file_close(wtap_dumper *wdh)
1052 if(wdh->compressed) {
1053 return gzclose(wdh->fh);
1057 return fclose(wdh->fh);
1061 int wtap_dump_file_ferror(wtap_dumper *wdh)
1066 if(wdh->compressed) {
1067 gzerror(wdh->fh, &errnum);
1069 if(errnum == Z_ERRNO) {
1072 /* XXX - what to do with this zlib specific number? */
1078 return ferror(wdh->fh);