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"
50 #include "ascendtext.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"
85 #include "jpeg_jfif.h"
88 /* The open_file_* routines should return:
92 * 1 if the file they're reading is one of the types it handles;
94 * 0 if the file they're reading isn't the type they're checking for.
96 * If the routine handles this type of file, it should set the "file_type"
97 * field in the "struct wtap" to the type of the file.
99 * Put the trace files that are merely saved telnet-sessions last, since it's
100 * possible that you could have captured someone a router telnet-session
101 * using another tool. So, a libpcap trace of an toshiba "snoop" session
102 * should be discovered as a libpcap file, not a toshiba file.
106 static wtap_open_routine_t open_routines_base[] = {
107 /* Files that have magic bytes in fixed locations. These
108 * are easy to identify.
121 network_instruments_open,
125 catapult_dct2000_open,
129 packetlogger_open, /* This type does not have a magic number, but its
130 * files are sometimes grabbed by mpeg_open. */
136 /* Files that don't have magic bytes at a fixed location,
137 * but that instead require a heuristic of some sort to
138 * identify them. This includes the ASCII trace files that
139 * would be, for example, saved copies of a Telnet session
143 /* I put NetScreen *before* erf, because there were some
144 * false positives with my test-files (Sake Blok, July 2007)
164 #define N_FILE_TYPES (sizeof open_routines_base / sizeof open_routines_base[0])
166 static wtap_open_routine_t* open_routines = NULL;
168 static GArray* open_routines_arr = NULL;
171 /* initialize the open routines array if it has not being initialized yet */
172 static void init_open_routines(void) {
174 if (open_routines_arr) return;
176 open_routines_arr = g_array_new(FALSE,TRUE,sizeof(wtap_open_routine_t));
178 g_array_append_vals(open_routines_arr,open_routines_base,N_FILE_TYPES);
180 open_routines = (wtap_open_routine_t*)open_routines_arr->data;
183 void wtap_register_open_routine(wtap_open_routine_t open_routine, gboolean has_magic) {
184 init_open_routines();
187 g_array_prepend_val(open_routines_arr,open_routine);
189 g_array_append_val(open_routines_arr,open_routine);
191 open_routines = (wtap_open_routine_t*)open_routines_arr->data;
195 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
196 * define them either.)
198 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
201 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
204 #define S_IFIFO _S_IFIFO
207 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
210 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
213 /* Opens a file and prepares a wtap struct.
214 If "do_random" is TRUE, it opens the file twice; the second open
215 allows the application to do random-access I/O without moving
216 the seek offset for sequential I/O, which is used by Wireshark
217 so that it can do sequential I/O to a capture file that's being
218 written to as new packets arrive independently of random I/O done
219 to display protocol trees for packets when they're selected. */
220 wtap* wtap_open_offline(const char *filename, int *err, char **err_info,
226 gboolean use_stdin = FALSE;
228 /* open standard input if filename is '-' */
229 if (strcmp(filename, "-") == 0)
232 /* First, make sure the file is valid */
234 if (fstat(0, &statb) < 0) {
239 if (ws_stat(filename, &statb) < 0) {
244 if (S_ISFIFO(statb.st_mode)) {
246 * Opens of FIFOs are allowed only when not opening
249 * XXX - currently, we do seeking when trying to find
250 * out the file type, so we don't actually support
251 * opening FIFOs. However, we may eventually
252 * do buffering that allows us to do at least some
253 * file type determination even on pipes, so we
254 * allow FIFO opens and let things fail later when
258 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
261 } else if (S_ISDIR(statb.st_mode)) {
263 * Return different errors for "this is a directory"
264 * and "this is some random special file type", so
265 * the user can get a potentially more helpful error.
269 } else if (! S_ISREG(statb.st_mode)) {
270 *err = WTAP_ERR_NOT_REGULAR_FILE;
275 * We need two independent descriptors for random access, so
276 * they have different file positions. If we're opening the
277 * standard input, we can only dup it to get additional
278 * descriptors, so we can't have two independent descriptors,
279 * and thus can't do random access.
281 if (use_stdin && do_random) {
282 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
287 wth = (wtap *)g_malloc(sizeof(wtap));
294 errno = WTAP_ERR_CANT_OPEN;
297 * We dup FD 0, so that we don't have to worry about
298 * an fclose or gzclose of wth->fh closing the standard
299 * input of the process.
303 _setmode(wth->fd, O_BINARY);
306 wth->fd = ws_open(filename, O_RDONLY|O_BINARY, 0000 /* no creation so don't matter */);
312 if (!(wth->fh = filed_open(wth->fd, "rb"))) {
320 if (!(wth->random_fh = file_open(filename, "rb"))) {
327 wth->random_fh = NULL;
330 wth->file_encap = WTAP_ENCAP_UNKNOWN;
331 wth->data_offset = 0;
332 wth->subtype_sequential_close = NULL;
333 wth->subtype_close = NULL;
334 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
337 init_open_routines();
339 /* Try all file types */
340 for (i = 0; i < open_routines_arr->len; i++) {
341 /* Seek back to the beginning of the file; the open routine
342 for the previous file type may have left the file
343 position somewhere other than the beginning, and the
344 open routine for this file type will probably want
345 to start reading at the beginning.
347 Initialize the data offset while we're at it. */
348 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
349 /* I/O error - give up */
350 if (wth->random_fh != NULL)
351 file_close(wth->random_fh);
356 wth->data_offset = 0;
358 switch ((*open_routines[i])(wth, err, err_info)) {
361 /* I/O error - give up */
362 if (wth->random_fh != NULL)
363 file_close(wth->random_fh);
369 /* No I/O error, but not that type of file */
373 /* We found the file type */
378 /* Well, it's not one of the types of file we know about. */
379 if (wth->random_fh != NULL)
380 file_close(wth->random_fh);
383 *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
387 wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
388 buffer_init(wth->frame_buffer, 1500);
392 /* Table of the file types we know about. */
393 static const struct file_type_info dump_open_table_base[] = {
394 /* WTAP_FILE_UNKNOWN (only used internally for initialization) */
395 { NULL, NULL, NULL, NULL, FALSE,
398 /* WTAP_FILE_WTAP (only used internally while capturing) */
399 { NULL, NULL, NULL, NULL, FALSE,
403 { "Wireshark/tcpdump/... - libpcap", "libpcap", "*.pcap;*.cap", ".pcap", TRUE,
404 libpcap_dump_can_write_encap, libpcap_dump_open },
406 /* WTAP_FILE_PCAP_NSEC */
407 { "Wireshark - nanosecond libpcap", "nseclibpcap", "*.pcap;*.cap", ".pcap", TRUE,
408 libpcap_dump_can_write_encap, libpcap_dump_open },
410 /* WTAP_FILE_PCAP_AIX */
411 { "AIX tcpdump - libpcap", "aixlibpcap", "*.pcap;*.cap", ".pcap", TRUE,
414 /* WTAP_FILE_PCAP_SS991029 */
415 { "Modified tcpdump - libpcap", "modlibpcap", "*.pcap;*.cap", ".pcap", TRUE,
416 libpcap_dump_can_write_encap, libpcap_dump_open },
418 /* WTAP_FILE_PCAP_NOKIA */
419 { "Nokia tcpdump - libpcap ", "nokialibpcap", "*.pcap;*.cap", ".pcap", TRUE,
420 libpcap_dump_can_write_encap, libpcap_dump_open },
422 /* WTAP_FILE_PCAP_SS990417 */
423 { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "*.pcap;*.cap", ".pcap", TRUE,
424 libpcap_dump_can_write_encap, libpcap_dump_open },
426 /* WTAP_FILE_PCAP_SS990915 */
427 { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "*.pcap;*.cap", ".pcap", TRUE,
428 libpcap_dump_can_write_encap, libpcap_dump_open },
430 /* WTAP_FILE_5VIEWS */
431 { "Accellent 5Views capture", "5views", "*.5vw", ".5vw", FALSE,
432 _5views_dump_can_write_encap, _5views_dump_open },
434 /* WTAP_FILE_IPTRACE_1_0 */
435 { "AIX iptrace 1.0", "iptrace_1", "*.*", NULL, FALSE,
438 /* WTAP_FILE_IPTRACE_2_0 */
439 { "AIX iptrace 2.0", "iptrace_2", "*.*", NULL, FALSE,
443 { "ASN.1 Basic Encoding Rules", "ber", "*.*", NULL, FALSE,
446 /* WTAP_FILE_HCIDUMP */
447 { "Bluetooth HCI dump", "hcidump", "*.*", NULL, FALSE,
450 /* WTAP_FILE_CATAPULT_DCT2000 */
451 { "Catapult DCT2000 trace (.out format)", "dct2000", "*.out", ".out", FALSE,
452 catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open },
454 /* WTAP_FILE_NETXRAY_OLD */
455 { "Cinco Networks NetXRay 1.x", "netxray1", "*.cap", ".cap", FALSE,
458 /* WTAP_FILE_NETXRAY_1_0 */
459 { "Cinco Networks NetXRay 2.0 or later", "netxray2", "*.cap", ".cap", FALSE,
462 /* WTAP_FILE_COSINE */
463 { "CoSine IPSX L2 capture", "cosine", "*.*", NULL, FALSE,
466 /* WTAP_FILE_CSIDS */
467 { "CSIDS IPLog", "csids", "*.*", NULL, FALSE,
470 /* WTAP_FILE_DBS_ETHERWATCH */
471 { "DBS Etherwatch (VMS)", "etherwatch", "*.*", NULL, FALSE,
475 { "Endace ERF capture", "erf", "*.erf", ".erf", FALSE,
478 /* WTAP_FILE_EYESDN */
479 { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "*.*", NULL, FALSE,
482 /* WTAP_FILE_NETTL */
483 { "HP-UX nettl trace", "nettl", "*.TRC0;*.TRC1", ".TRC0", FALSE,
484 nettl_dump_can_write_encap, nettl_dump_open },
486 /* WTAP_FILE_ISERIES */
487 { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "*.*", NULL, FALSE,
490 /* WTAP_FILE_ISERIES_UNICODE */
491 { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "*.*", NULL, FALSE,
494 /* WTAP_FILE_I4BTRACE */
495 { "I4B ISDN trace", "i4btrace", "*.*", NULL, FALSE,
498 /* WTAP_FILE_ASCEND */
499 { "Lucent/Ascend access server trace", "ascend", "*.*", NULL, FALSE,
502 /* WTAP_FILE_NETMON_1_x */
503 { "Microsoft NetMon 1.x", "netmon1", "*.cap", ".cap", FALSE,
504 netmon_dump_can_write_encap, netmon_dump_open },
506 /* WTAP_FILE_NETMON_2_x */
507 { "Microsoft NetMon 2.x", "netmon2", "*.cap", ".cap", FALSE,
508 netmon_dump_can_write_encap, netmon_dump_open },
510 /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
511 { "NA Sniffer (DOS)", "ngsniffer", "*.cap;*.enc;*.trc;*.fdc;*.syc", ".cap", FALSE,
512 ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
514 /* WTAP_FILE_NGSNIFFER_COMPRESSED */
515 { "NA Sniffer (DOS), compressed", "ngsniffer_comp", "*.caz", ".caz", FALSE,
518 /* WTAP_FILE_NETXRAY_1_1 */
519 { "NA Sniffer (Windows) 1.1", "ngwsniffer_1_1", "*.cap", ".cap", FALSE,
520 netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 },
522 /* WTAP_FILE_NETXRAY_2_00x */
523 { "NA Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "*.cap", ".cap", FALSE,
524 netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 },
526 /* WTAP_FILE_NETWORK_INSTRUMENTS_V9 */
527 { "Network Instruments Observer (V9)", "niobserverv9", "*.bfr", ".bfr", FALSE,
528 network_instruments_dump_can_write_encap, network_instruments_dump_open },
530 /* WTAP_FILE_LANALYZER */
531 { "Novell LANalyzer","lanalyzer", "*.tr1", ".tr1", FALSE,
532 lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
534 /* WTAP_FILE_PPPDUMP */
535 { "pppd log (pppdump format)", "pppd", "*.*", NULL, FALSE,
538 /* WTAP_FILE_RADCOM */
539 { "RADCOM WAN/LAN analyzer", "radcom", "*.*", NULL, FALSE,
542 /* WTAP_FILE_SNOOP */
543 { "Sun snoop", "snoop", "*.snoop;*.cap", ".snoop", FALSE,
544 snoop_dump_can_write_encap, snoop_dump_open },
546 /* WTAP_FILE_SHOMITI */
547 { "Shomiti/Finisar Surveyor", "shomiti", "*.cap", ".cap", FALSE,
551 { "TCPIPtrace (VMS)", "tcpiptrace", "*.*", NULL, FALSE,
555 { "Tektronix K12xx 32-bit .rf5 format", "rf5", "*.rf5", ".rf5", TRUE,
556 k12_dump_can_write_encap, k12_dump_open },
558 /* WTAP_FILE_TOSHIBA */
559 { "Toshiba Compact ISDN Router snoop", "toshiba", "*.*", NULL, FALSE,
562 /* WTAP_FILE_VISUAL_NETWORKS */
563 { "Visual Networks traffic capture", "visual", "*.*", NULL, FALSE,
564 visual_dump_can_write_encap, visual_dump_open },
566 /* WTAP_FILE_ETHERPEEK_V56 */
567 { "WildPackets Ether/TokenPeek (V5 & V6)", "peek56", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
570 /* WTAP_FILE_ETHERPEEK_V7 */
571 { "WildPackets Ether/Token/AiroPeek (V7)", "peek7", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
574 /* WTAP_FILE_ETHERPEEK_V9 */
575 { "WildPackets Ether/AiroPeek (V9)", "peek9", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
579 { "MPEG", "mpeg", "*.mpeg;*.mpg;*.mp3", ".mpeg", FALSE,
582 /* WTAP_FILE_K12TEXT */
583 { "K12 text file", "k12text", "*.txt", ".txt", TRUE,
584 k12text_dump_can_write_encap, k12text_dump_open },
586 /* WTAP_FILE_NETSCREEN */
587 { "NetScreen snoop text file", "netscreen", "*.*", NULL, FALSE,
590 /* WTAP_FILE_COMMVIEW */
591 { "TamoSoft CommView", "commview", "*.ncf", ".ncf", TRUE,
592 commview_dump_can_write_encap, commview_dump_open },
594 /* WTAP_FILE_PCAPNG */
595 { "Wireshark - pcapng (experimental)", "pcapng", "*.pcapng", NULL, FALSE,
596 pcapng_dump_can_write_encap, pcapng_dump_open },
598 /* WTAP_FILE_BTSNOOP */
599 { "Symbian OS btsnoop", "btsnoop", "*.log", ".log", FALSE,
600 btsnoop_dump_can_write_encap, btsnoop_dump_open_h4 },
602 /* WTAP_FILE_X2E_XORAYA */
603 { NULL, NULL, NULL, NULL, FALSE, NULL, NULL },
606 { "Transport-Neutral Encapsulation Format", "tnef", "*.*", NULL, FALSE, NULL, NULL },
608 /* WTAP_FILE_DCT3TRACE */
609 { "Gammu DCT3 trace", "dct3trace", "*.xml", NULL, FALSE, NULL, NULL },
611 /* WTAP_FILE_PACKETLOGGER */
612 { "PacketLogger", "pklg", "*.pklg", NULL, FALSE, NULL, NULL },
614 /* WTAP_FILE_DAINTREE_SNA */
615 { "Daintree SNA", "dsna", "*.dcf", NULL, FALSE, NULL, NULL },
617 /* WTAP_FILE_NETSCALER_1_0 */
618 { "NetScaler Trace (Version 1.0)", "nstrace10", "*.*", "*.*", FALSE,
619 nstrace_10_dump_can_write_encap, nstrace_dump_open },
621 /* WTAP_FILE_NETSCALER_2_0 */
622 { "NetScaler Trace (Version 2.0)", "nstrace20", "*.cap", "*.cap", FALSE,
623 nstrace_20_dump_can_write_encap, nstrace_dump_open },
625 /* WTAP_FILE_JPEG_JFIF */
626 { "JPEG/JFIF", "jpeg", "*.jpg;*.jpeg;*.jfif", ".jpg", FALSE, NULL, NULL },
630 gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info);
632 static GArray* dump_open_table_arr = NULL;
633 static const struct file_type_info* dump_open_table = dump_open_table_base;
635 /* initialize the open routines array if it has not being initialized yet */
636 static void init_file_types(void) {
638 if (dump_open_table_arr) return;
640 dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_info));
642 g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types);
644 dump_open_table = (const struct file_type_info*)dump_open_table_arr->data;
647 int wtap_register_file_type(const struct file_type_info* fi) {
650 g_array_append_val(dump_open_table_arr,*fi);
652 dump_open_table = (const struct file_type_info*)dump_open_table_arr->data;
654 return wtap_num_file_types++;
657 int wtap_get_num_file_types(void)
659 return wtap_num_file_types;
662 /* Name that should be somewhat descriptive. */
663 const char *wtap_file_type_string(int filetype)
665 if (filetype < 0 || filetype >= wtap_num_file_types) {
666 g_error("Unknown capture file type %d", filetype);
669 return dump_open_table[filetype].name;
672 /* Name to use in, say, a command-line flag specifying the type. */
673 const char *wtap_file_type_short_string(int filetype)
675 if (filetype < 0 || filetype >= wtap_num_file_types)
678 return dump_open_table[filetype].short_name;
681 /* Translate a short name to a capture file type. */
682 int wtap_short_string_to_file_type(const char *short_name)
686 for (filetype = 0; filetype < wtap_num_file_types; filetype++) {
687 if (dump_open_table[filetype].short_name != NULL &&
688 strcmp(short_name, dump_open_table[filetype].short_name) == 0)
691 return -1; /* no such file type, or we can't write it */
694 /* file extensions to use. */
695 const char *wtap_file_extensions_string(int filetype)
697 if (filetype < 0 || filetype >= wtap_num_file_types)
700 return dump_open_table[filetype].file_extensions;
703 /* default file extension to use. */
704 const char *wtap_file_extension_default_string(int filetype)
706 if (filetype < 0 || filetype >= wtap_num_file_types)
709 return dump_open_table[filetype].file_extension_default;
712 gboolean wtap_dump_can_open(int filetype)
714 if (filetype < 0 || filetype >= wtap_num_file_types
715 || dump_open_table[filetype].dump_open == NULL)
721 gboolean wtap_dump_can_write_encap(int filetype, int encap)
723 if (filetype < 0 || filetype >= wtap_num_file_types
724 || dump_open_table[filetype].can_write_encap == NULL)
727 if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
734 gboolean wtap_dump_can_compress(int filetype)
736 if (filetype < 0 || filetype >= wtap_num_file_types
737 || dump_open_table[filetype].can_compress == FALSE)
743 gboolean wtap_dump_can_compress(int filetype _U_)
750 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
751 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
752 gboolean compressed, int *err);
753 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err);
755 static FILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
756 static FILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
757 static int wtap_dump_file_close(wtap_dumper *wdh);
759 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
760 int snaplen, gboolean compressed, int *err)
765 /* Check whether we can open a capture file with that file type
766 and that encapsulation. */
767 if (!wtap_dump_open_check(filetype, encap, compressed, err))
770 /* Allocate a data structure for the output stream. */
771 wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
773 return NULL; /* couldn't allocate it */
775 /* "-" means stdout */
776 if (strcmp(filename, "-") == 0) {
779 return NULL; /* compress won't work on stdout */
782 setmode(fileno(stdout), O_BINARY);
786 /* In case "fopen()" fails but doesn't set "errno", set "errno"
787 to a generic "the open failed" error. */
788 errno = WTAP_ERR_CANT_OPEN;
789 fh = wtap_dump_file_open(wdh, filename);
793 return NULL; /* can't create file */
798 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
799 /* Get rid of the file we created; we couldn't finish
801 if (wdh->fh != stdout) {
802 wtap_dump_file_close(wdh);
811 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
812 gboolean compressed, int *err)
817 /* Check whether we can open a capture file with that file type
818 and that encapsulation. */
819 if (!wtap_dump_open_check(filetype, encap, compressed, err))
822 /* Allocate a data structure for the output stream. */
823 wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
825 return NULL; /* couldn't allocate it */
829 setmode(fileno(stdout), O_BINARY);
833 /* In case "fopen()" fails but doesn't set "errno", set "errno"
834 to a generic "the open failed" error. */
835 errno = WTAP_ERR_CANT_OPEN;
836 fh = wtap_dump_file_fdopen(wdh, fd);
840 return NULL; /* can't create standard I/O stream */
844 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
845 wtap_dump_file_close(wdh);
852 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err)
854 if (!wtap_dump_can_open(filetype)) {
855 /* Invalid type, or type we don't know how to write. */
856 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
860 /* OK, we know how to write that type; can we write the specified
861 encapsulation type? */
862 *err = (*dump_open_table[filetype].can_write_encap)(encap);
866 /* if compression is wanted, do we support this for this filetype? */
867 if(compressed && !wtap_dump_can_compress(filetype)) {
868 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
872 *err = (*dump_open_table[filetype].can_write_encap)(encap);
877 /* All systems go! */
881 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
882 gboolean compressed, int *err)
886 wdh = (wtap_dumper *)g_malloc(sizeof (wtap_dumper));
892 wdh->file_type = filetype;
893 wdh->snaplen = snaplen;
895 wdh->compressed = compressed;
896 wdh->bytes_dumped = 0;
898 wdh->subtype_write = NULL;
899 wdh->subtype_close = NULL;
903 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err)
908 /* Can we do a seek on the file descriptor?
909 If not, note that fact. */
913 fd = fileno(wdh->fh);
914 if (lseek(fd, 1, SEEK_CUR) == -1)
918 lseek(fd, 0, SEEK_SET);
923 /* Now try to open the file for writing. */
924 if (!(*dump_open_table[filetype].dump_open)(wdh, cant_seek, err)) {
928 return TRUE; /* success! */
931 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
932 const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err)
934 return (wdh->subtype_write)(wdh, phdr, pseudo_header, pd, err);
937 void wtap_dump_flush(wtap_dumper *wdh)
940 if(wdh->compressed) {
941 gzflush(wdh->fh, Z_SYNC_FLUSH); /* XXX - is Z_SYNC_FLUSH the right one? */
949 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
953 if (wdh->subtype_close != NULL) {
954 /* There's a close routine for this dump stream. */
955 if (!(wdh->subtype_close)(wdh, err))
958 errno = WTAP_ERR_CANT_CLOSE;
959 /* Don't close stdout */
960 if (wdh->fh != stdout) {
961 if (wtap_dump_file_close(wdh) == EOF) {
963 /* The per-format close function succeeded,
964 but the fclose didn't. Save the reason
965 why, if our caller asked for it. */
972 /* as we don't close stdout, at least try to flush it */
973 wtap_dump_flush(wdh);
975 if (wdh->priv != NULL)
981 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
983 return wdh->bytes_dumped;
986 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
988 wdh->bytes_dumped = bytes_dumped;
992 /* internally open a file for writing (compressed or not) */
994 static FILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
996 if(wdh->compressed) {
997 return gzopen(filename, "wb");
999 return ws_fopen(filename, "wb");
1003 static FILE_T wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
1005 return ws_fopen(filename, "wb");
1009 /* internally open a file for writing (compressed or not) */
1011 static FILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
1013 if(wdh->compressed) {
1014 return gzdopen(fd, "wb");
1016 return fdopen(fd, "wb");
1020 static FILE_T wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
1022 return fdopen(fd, "wb");
1026 /* internally writing raw bytes (compressed or not) */
1027 size_t wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize)
1030 if(wdh->compressed) {
1031 return gzwrite(wdh->fh, buf, (unsigned) bufsize);
1035 return fwrite(buf, 1, bufsize, wdh->fh);
1039 gboolean wtap_dump_file_write_all(wtap_dumper *wdh, const void *buf, unsigned bufsize, int *err)
1043 nwritten = wtap_dump_file_write(wdh, buf, bufsize);
1044 if (nwritten != bufsize) {
1045 if (nwritten == 0 && wtap_dump_file_ferror(wdh))
1046 *err = wtap_dump_file_ferror(wdh);
1048 *err = WTAP_ERR_SHORT_WRITE;
1054 /* internally close a file for writing (compressed or not) */
1055 static int wtap_dump_file_close(wtap_dumper *wdh)
1058 if(wdh->compressed) {
1059 return gzclose(wdh->fh);
1063 return fclose(wdh->fh);
1067 int wtap_dump_file_ferror(wtap_dumper *wdh)
1072 if(wdh->compressed) {
1073 gzerror(wdh->fh, &errnum);
1075 if(errnum == Z_ERRNO) {
1078 /* XXX - what to do with this zlib specific number? */
1084 return ferror(wdh->fh);