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"
84 /* The open_file_* routines should return:
88 * 1 if the file they're reading is one of the types it handles;
90 * 0 if the file they're reading isn't the type they're checking for.
92 * If the routine handles this type of file, it should set the "file_type"
93 * field in the "struct wtap" to the type of the file.
95 * Put the trace files that are merely saved telnet-sessions last, since it's
96 * possible that you could have captured someone a router telnet-session
97 * using another tool. So, a libpcap trace of an toshiba "snoop" session
98 * should be discovered as a libpcap file, not a toshiba file.
102 static wtap_open_routine_t open_routines_base[] = {
103 /* Files that have magic bytes in fixed locations. These
104 * are easy to identify.
117 network_instruments_open,
121 catapult_dct2000_open,
128 /* Files that don't have magic bytes at a fixed location,
129 * but that instead require a heuristic of some sort to
130 * identify them. This includes the ASCII trace files that
131 * would be, for example, saved copies of a Telnet session
135 /* I put NetScreen *before* erf, because there were some
136 * false positives with my test-files (Sake Blok, July 2007)
155 #define N_FILE_TYPES (sizeof open_routines_base / sizeof open_routines_base[0])
157 static wtap_open_routine_t* open_routines = NULL;
159 static GArray* open_routines_arr = NULL;
162 /* initialize the open routines array if it has not being initialized yet */
163 static void init_open_routines(void) {
165 if (open_routines_arr) return;
167 open_routines_arr = g_array_new(FALSE,TRUE,sizeof(wtap_open_routine_t));
169 g_array_append_vals(open_routines_arr,open_routines_base,N_FILE_TYPES);
171 open_routines = (void*)open_routines_arr->data;
174 void wtap_register_open_routine(wtap_open_routine_t open_routine, gboolean has_magic) {
175 init_open_routines();
178 g_array_prepend_val(open_routines_arr,open_routine);
180 g_array_append_val(open_routines_arr,open_routine);
182 open_routines = (void*)open_routines_arr->data;
186 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
187 * define them either.)
189 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
192 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
195 #define S_IFIFO _S_IFIFO
198 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
201 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
204 /* Opens a file and prepares a wtap struct.
205 If "do_random" is TRUE, it opens the file twice; the second open
206 allows the application to do random-access I/O without moving
207 the seek offset for sequential I/O, which is used by Wireshark
208 so that it can do sequential I/O to a capture file that's being
209 written to as new packets arrive independently of random I/O done
210 to display protocol trees for packets when they're selected. */
211 wtap* wtap_open_offline(const char *filename, int *err, char **err_info,
217 gboolean use_stdin = FALSE;
219 /* open standard input if filename is '-' */
220 if (strcmp(filename, "-") == 0)
223 /* First, make sure the file is valid */
225 if (fstat(0, &statb) < 0) {
230 if (ws_stat(filename, &statb) < 0) {
235 if (S_ISFIFO(statb.st_mode)) {
237 * Opens of FIFOs are allowed only when not opening
240 * XXX - currently, we do seeking when trying to find
241 * out the file type, so we don't actually support
242 * opening FIFOs. However, we may eventually
243 * do buffering that allows us to do at least some
244 * file type determination even on pipes, so we
245 * allow FIFO opens and let things fail later when
249 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
252 } else if (S_ISDIR(statb.st_mode)) {
254 * Return different errors for "this is a directory"
255 * and "this is some random special file type", so
256 * the user can get a potentially more helpful error.
260 } else if (! S_ISREG(statb.st_mode)) {
261 *err = WTAP_ERR_NOT_REGULAR_FILE;
266 * We need two independent descriptors for random access, so
267 * they have different file positions. If we're opening the
268 * standard input, we can only dup it to get additional
269 * descriptors, so we can't have two independent descriptors,
270 * and thus can't do random access.
272 if (use_stdin && do_random) {
273 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
278 wth = g_malloc(sizeof(wtap));
285 errno = WTAP_ERR_CANT_OPEN;
288 * We dup FD 0, so that we don't have to worry about
289 * an fclose or gzclose of wth->fh closing the standard
290 * input of the process.
294 _setmode(wth->fd, O_BINARY);
297 wth->fd = ws_open(filename, O_RDONLY|O_BINARY, 0000 /* no creation so don't matter */);
303 if (!(wth->fh = filed_open(wth->fd, "rb"))) {
311 if (!(wth->random_fh = file_open(filename, "rb"))) {
318 wth->random_fh = NULL;
321 wth->file_encap = WTAP_ENCAP_UNKNOWN;
322 wth->data_offset = 0;
323 wth->subtype_sequential_close = NULL;
324 wth->subtype_close = NULL;
325 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
327 init_open_routines();
329 /* Try all file types */
330 for (i = 0; i < open_routines_arr->len; i++) {
331 /* Seek back to the beginning of the file; the open routine
332 for the previous file type may have left the file
333 position somewhere other than the beginning, and the
334 open routine for this file type will probably want
335 to start reading at the beginning.
337 Initialize the data offset while we're at it. */
338 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
339 /* I/O error - give up */
340 if (wth->random_fh != NULL)
341 file_close(wth->random_fh);
346 wth->data_offset = 0;
348 switch ((*open_routines[i])(wth, err, err_info)) {
351 /* I/O error - give up */
352 if (wth->random_fh != NULL)
353 file_close(wth->random_fh);
359 /* No I/O error, but not that type of file */
363 /* We found the file type */
368 /* Well, it's not one of the types of file we know about. */
369 if (wth->random_fh != NULL)
370 file_close(wth->random_fh);
373 *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
377 wth->frame_buffer = g_malloc(sizeof(struct Buffer));
378 buffer_init(wth->frame_buffer, 1500);
382 /* Table of the file types we know about. */
383 static const struct file_type_info dump_open_table_base[] = {
384 /* WTAP_FILE_UNKNOWN (only used internally for initialization) */
385 { NULL, NULL, NULL, NULL, FALSE,
388 /* WTAP_FILE_WTAP (only used internally while capturing) */
389 { NULL, NULL, NULL, NULL, FALSE,
393 { "Wireshark/tcpdump/... - libpcap", "libpcap", "*.pcap;*.cap", ".pcap", TRUE,
394 libpcap_dump_can_write_encap, libpcap_dump_open },
396 /* WTAP_FILE_PCAP_NSEC */
397 { "Wireshark - nanosecond libpcap", "nseclibpcap", "*.pcap;*.cap", ".pcap", TRUE,
398 libpcap_dump_can_write_encap, libpcap_dump_open },
400 /* WTAP_FILE_PCAP_AIX */
401 { "AIX tcpdump - libpcap", "aixlibpcap", "*.pcap;*.cap", ".pcap", TRUE,
404 /* WTAP_FILE_PCAP_SS991029 */
405 { "Modified tcpdump - libpcap", "modlibpcap", "*.pcap;*.cap", ".pcap", TRUE,
406 libpcap_dump_can_write_encap, libpcap_dump_open },
408 /* WTAP_FILE_PCAP_NOKIA */
409 { "Nokia tcpdump - libpcap ", "nokialibpcap", "*.pcap;*.cap", ".pcap", TRUE,
410 libpcap_dump_can_write_encap, libpcap_dump_open },
412 /* WTAP_FILE_PCAP_SS990417 */
413 { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "*.pcap;*.cap", ".pcap", TRUE,
414 libpcap_dump_can_write_encap, libpcap_dump_open },
416 /* WTAP_FILE_PCAP_SS990915 */
417 { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "*.pcap;*.cap", ".pcap", TRUE,
418 libpcap_dump_can_write_encap, libpcap_dump_open },
420 /* WTAP_FILE_5VIEWS */
421 { "Accellent 5Views capture", "5views", "*.5vw", ".5vw", FALSE,
422 _5views_dump_can_write_encap, _5views_dump_open },
424 /* WTAP_FILE_IPTRACE_1_0 */
425 { "AIX iptrace 1.0", "iptrace_1", "*.*", NULL, FALSE,
428 /* WTAP_FILE_IPTRACE_2_0 */
429 { "AIX iptrace 2.0", "iptrace_2", "*.*", NULL, FALSE,
433 { "ASN.1 Basic Encoding Rules", "ber", "*.*", NULL, FALSE,
436 /* WTAP_FILE_HCIDUMP */
437 { "Bluetooth HCI dump", "hcidump", "*.*", NULL, FALSE,
440 /* WTAP_FILE_CATAPULT_DCT2000 */
441 { "Catapult DCT2000 trace (.out format)", "dct2000", "*.out", ".out", FALSE,
442 catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open },
444 /* WTAP_FILE_NETXRAY_OLD */
445 { "Cinco Networks NetXRay 1.x", "netxray1", "*.cap", ".cap", FALSE,
448 /* WTAP_FILE_NETXRAY_1_0 */
449 { "Cinco Networks NetXRay 2.0 or later", "netxray2", "*.cap", ".cap", FALSE,
452 /* WTAP_FILE_COSINE */
453 { "CoSine IPSX L2 capture", "cosine", "*.*", NULL, FALSE,
456 /* WTAP_FILE_CSIDS */
457 { "CSIDS IPLog", "csids", "*.*", NULL, FALSE,
460 /* WTAP_FILE_DBS_ETHERWATCH */
461 { "DBS Etherwatch (VMS)", "etherwatch", "*.*", NULL, FALSE,
465 { "Endace ERF capture", "erf", "*.erf", ".erf", FALSE,
468 /* WTAP_FILE_EYESDN */
469 { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "*.*", NULL, FALSE,
472 /* WTAP_FILE_NETTL */
473 { "HP-UX nettl trace", "nettl", "*.TRC0;*.TRC1", ".TRC0", FALSE,
474 nettl_dump_can_write_encap, nettl_dump_open },
476 /* WTAP_FILE_ISERIES */
477 { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "*.*", NULL, FALSE,
480 /* WTAP_FILE_ISERIES_UNICODE */
481 { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "*.*", NULL, FALSE,
484 /* WTAP_FILE_I4BTRACE */
485 { "I4B ISDN trace", "i4btrace", "*.*", NULL, FALSE,
488 /* WTAP_FILE_ASCEND */
489 { "Lucent/Ascend access server trace", "ascend", "*.*", NULL, FALSE,
492 /* WTAP_FILE_NETMON_1_x */
493 { "Microsoft NetMon 1.x", "netmon1", "*.cap", ".cap", FALSE,
494 netmon_dump_can_write_encap, netmon_dump_open },
496 /* WTAP_FILE_NETMON_2_x */
497 { "Microsoft NetMon 2.x", "netmon2", "*.cap", ".cap", FALSE,
498 netmon_dump_can_write_encap, netmon_dump_open },
500 /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
501 { "NA Sniffer (DOS)", "ngsniffer", "*.cap;*.enc;*.trc;*.fdc;*.syc", ".cap", FALSE,
502 ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
504 /* WTAP_FILE_NGSNIFFER_COMPRESSED */
505 { "NA Sniffer (DOS), compressed", "ngsniffer_comp", "*.caz", ".caz", FALSE,
508 /* WTAP_FILE_NETXRAY_1_1 */
509 { "NA Sniffer (Windows) 1.1", "ngwsniffer_1_1", "*.cap", ".cap", FALSE,
510 netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 },
512 /* WTAP_FILE_NETXRAY_2_00x */
513 { "NA Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "*.cap", ".cap", FALSE,
514 netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 },
516 /* WTAP_FILE_NETWORK_INSTRUMENTS_V9 */
517 { "Network Instruments Observer (V9)", "niobserverv9", "*.bfr", ".bfr", FALSE,
518 network_instruments_dump_can_write_encap, network_instruments_dump_open },
520 /* WTAP_FILE_LANALYZER */
521 { "Novell LANalyzer","lanalyzer", "*.tr1", ".tr1", FALSE,
522 lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
524 /* WTAP_FILE_PPPDUMP */
525 { "pppd log (pppdump format)", "pppd", "*.*", NULL, FALSE,
528 /* WTAP_FILE_RADCOM */
529 { "RADCOM WAN/LAN analyzer", "radcom", "*.*", NULL, FALSE,
532 /* WTAP_FILE_SNOOP */
533 { "Sun snoop", "snoop", "*.snoop;*.cap", ".snoop", FALSE,
534 snoop_dump_can_write_encap, snoop_dump_open },
536 /* WTAP_FILE_SHOMITI */
537 { "Shomiti/Finisar Surveyor", "shomiti", "*.cap", ".cap", FALSE,
541 { "TCPIPtrace (VMS)", "tcpiptrace", "*.*", NULL, FALSE,
545 { "Tektronix K12xx 32-bit .rf5 format", "rf5", "*.rf5", ".rf5", TRUE,
546 k12_dump_can_write_encap, k12_dump_open },
548 /* WTAP_FILE_TOSHIBA */
549 { "Toshiba Compact ISDN Router snoop", "toshiba", "*.*", NULL, FALSE,
552 /* WTAP_FILE_VISUAL_NETWORKS */
553 { "Visual Networks traffic capture", "visual", "*.*", NULL, FALSE,
554 visual_dump_can_write_encap, visual_dump_open },
556 /* WTAP_FILE_ETHERPEEK_V56 */
557 { "Wildpacket Ether/TokenPeek (V5 & V6)", "peek56", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
560 /* WTAP_FILE_ETHERPEEK_V7 */
561 { "Wildpacket Ether/Token/AiroPeek (V7)", "peek7", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
564 /* WTAP_FILE_ETHERPEEK_V9 */
565 { "Wildpacket Ether/AiroPeek (V9)", "peek9", "*.tpc;*.apc;*.pkt;*.wpz", ".pkt", FALSE,
569 { "MPEG", "mpeg", "*.mpeg;*.mpg;*.mp3", ".mpeg", FALSE,
572 /* WTAP_FILE_K12TEXT */
573 { "K12 text file", "k12text", "*.txt", ".txt", TRUE,
574 k12text_dump_can_write_encap, k12text_dump_open },
576 /* WTAP_FILE_NETSCREEN */
577 { "NetScreen snoop text file", "netscreen", "*.*", NULL, FALSE,
580 /* WTAP_FILE_COMMVIEW */
581 { "TamoSoft CommView", "commview", "*.ncf", ".ncf", TRUE,
582 commview_dump_can_write_encap, commview_dump_open },
584 /* WTAP_FILE_PCAPNG */
585 { "Wireshark - pcapng (experimental)", "pcapng", "*.pcapng", NULL, FALSE,
586 pcapng_dump_can_write_encap, pcapng_dump_open },
588 /* WTAP_FILE_BTSNOOP */
589 { "Symbian OS btsnoop", "btsnoop", "*.log", NULL, FALSE, NULL, NULL },
591 /* WTAP_FILE_X2E_XORAYA */
592 { NULL, NULL, NULL, NULL, FALSE, NULL, NULL },
595 { "Transport-Neutral Encapsulation Format", "tnef", "*.*", NULL, FALSE, NULL, NULL },
597 /* WTAP_FILE_DCT3TRACE */
598 { "Gammu DCT3 trace", "dct3trace", "*.xml", NULL, FALSE, NULL, NULL }
601 gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info);
603 static GArray* dump_open_table_arr = NULL;
604 static const struct file_type_info* dump_open_table = dump_open_table_base;
606 /* initialize the open routines array if it has not being initialized yet */
607 static void init_file_types(void) {
609 if (dump_open_table_arr) return;
611 dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_info));
613 g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types);
615 dump_open_table = (void*)dump_open_table_arr->data;
618 int wtap_register_file_type(const struct file_type_info* fi) {
621 g_array_append_val(dump_open_table_arr,*fi);
623 dump_open_table = (void*)dump_open_table_arr->data;
625 return wtap_num_file_types++;
628 int wtap_get_num_file_types(void)
630 return wtap_num_file_types;
633 /* Name that should be somewhat descriptive. */
634 const char *wtap_file_type_string(int filetype)
636 if (filetype < 0 || filetype >= wtap_num_file_types) {
637 g_error("Unknown capture file type %d", filetype);
640 return dump_open_table[filetype].name;
643 /* Name to use in, say, a command-line flag specifying the type. */
644 const char *wtap_file_type_short_string(int filetype)
646 if (filetype < 0 || filetype >= wtap_num_file_types)
649 return dump_open_table[filetype].short_name;
652 /* Translate a short name to a capture file type. */
653 int wtap_short_string_to_file_type(const char *short_name)
657 for (filetype = 0; filetype < wtap_num_file_types; filetype++) {
658 if (dump_open_table[filetype].short_name != NULL &&
659 strcmp(short_name, dump_open_table[filetype].short_name) == 0)
662 return -1; /* no such file type, or we can't write it */
665 /* file extensions to use. */
666 const char *wtap_file_extensions_string(int filetype)
668 if (filetype < 0 || filetype >= wtap_num_file_types)
671 return dump_open_table[filetype].file_extensions;
674 /* default file extension to use. */
675 const char *wtap_file_extension_default_string(int filetype)
677 if (filetype < 0 || filetype >= wtap_num_file_types)
680 return dump_open_table[filetype].file_extension_default;
683 gboolean wtap_dump_can_open(int filetype)
685 if (filetype < 0 || filetype >= wtap_num_file_types
686 || dump_open_table[filetype].dump_open == NULL)
692 gboolean wtap_dump_can_write_encap(int filetype, int encap)
694 if (filetype < 0 || filetype >= wtap_num_file_types
695 || dump_open_table[filetype].can_write_encap == NULL)
698 if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
705 gboolean wtap_dump_can_compress(int filetype)
707 if (filetype < 0 || filetype >= wtap_num_file_types
708 || dump_open_table[filetype].can_compress == FALSE)
714 gboolean wtap_dump_can_compress(int filetype _U_)
721 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
722 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
723 gboolean compressed, int *err);
724 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err);
726 static FILE *wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
727 static FILE *wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
728 static int wtap_dump_file_close(wtap_dumper *wdh);
730 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
731 int snaplen, gboolean compressed, int *err)
736 /* Check whether we can open a capture file with that file type
737 and that encapsulation. */
738 if (!wtap_dump_open_check(filetype, encap, compressed, err))
741 /* Allocate a data structure for the output stream. */
742 wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
744 return NULL; /* couldn't allocate it */
746 /* "-" means stdout */
747 if (strcmp(filename, "-") == 0) {
750 return NULL; /* compress won't work on stdout */
753 setmode(fileno(stdout), O_BINARY);
757 /* In case "fopen()" fails but doesn't set "errno", set "errno"
758 to a generic "the open failed" error. */
759 errno = WTAP_ERR_CANT_OPEN;
760 fh = wtap_dump_file_open(wdh, filename);
764 return NULL; /* can't create file */
769 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
770 /* Get rid of the file we created; we couldn't finish
772 if (wdh->fh != stdout) {
773 wtap_dump_file_close(wdh);
782 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
783 gboolean compressed, int *err)
788 /* Check whether we can open a capture file with that file type
789 and that encapsulation. */
790 if (!wtap_dump_open_check(filetype, encap, compressed, err))
793 /* Allocate a data structure for the output stream. */
794 wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
796 return NULL; /* couldn't allocate it */
800 setmode(fileno(stdout), O_BINARY);
804 /* In case "fopen()" fails but doesn't set "errno", set "errno"
805 to a generic "the open failed" error. */
806 errno = WTAP_ERR_CANT_OPEN;
807 fh = wtap_dump_file_fdopen(wdh, fd);
811 return NULL; /* can't create standard I/O stream */
815 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
816 wtap_dump_file_close(wdh);
823 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err)
825 if (!wtap_dump_can_open(filetype)) {
826 /* Invalid type, or type we don't know how to write. */
827 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
831 /* OK, we know how to write that type; can we write the specified
832 encapsulation type? */
833 *err = (*dump_open_table[filetype].can_write_encap)(encap);
837 /* if compression is wanted, do we support this for this filetype? */
838 if(compressed && !wtap_dump_can_compress(filetype)) {
839 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
843 *err = (*dump_open_table[filetype].can_write_encap)(encap);
848 /* All systems go! */
852 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
853 gboolean compressed, int *err)
857 wdh = g_malloc(sizeof (wtap_dumper));
863 wdh->file_type = filetype;
864 wdh->snaplen = snaplen;
866 wdh->compressed = compressed;
867 wdh->bytes_dumped = 0;
868 wdh->dump.opaque = NULL;
869 wdh->subtype_write = NULL;
870 wdh->subtype_close = NULL;
874 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err)
879 /* Can we do a seek on the file descriptor?
880 If not, note that fact. */
884 fd = fileno(wdh->fh);
885 if (lseek(fd, 1, SEEK_CUR) == -1)
889 lseek(fd, 0, SEEK_SET);
894 /* Now try to open the file for writing. */
895 if (!(*dump_open_table[filetype].dump_open)(wdh, cant_seek, err)) {
899 return TRUE; /* success! */
902 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
903 const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err)
905 return (wdh->subtype_write)(wdh, phdr, pseudo_header, pd, err);
908 void wtap_dump_flush(wtap_dumper *wdh)
911 if(wdh->compressed) {
912 gzflush(wdh->fh, Z_SYNC_FLUSH); /* XXX - is Z_SYNC_FLUSH the right one? */
920 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
924 if (wdh->subtype_close != NULL) {
925 /* There's a close routine for this dump stream. */
926 if (!(wdh->subtype_close)(wdh, err))
929 errno = WTAP_ERR_CANT_CLOSE;
930 /* Don't close stdout */
931 if (wdh->fh != stdout) {
932 if (wtap_dump_file_close(wdh) == EOF) {
934 /* The per-format close function succeeded,
935 but the fclose didn't. Save the reason
936 why, if our caller asked for it. */
943 /* as we don't close stdout, at least try to flush it */
944 wtap_dump_flush(wdh);
946 if (wdh->dump.opaque != NULL)
947 g_free(wdh->dump.opaque);
952 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
954 return wdh->bytes_dumped;
957 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
959 wdh->bytes_dumped = bytes_dumped;
963 /* internally open a file for writing (compressed or not) */
965 static FILE *wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
967 if(wdh->compressed) {
968 return gzopen(filename, "wb");
970 return ws_fopen(filename, "wb");
974 static FILE *wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
976 return ws_fopen(filename, "wb");
980 /* internally open a file for writing (compressed or not) */
982 static FILE *wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
984 if(wdh->compressed) {
985 return gzdopen(fd, "wb");
987 return fdopen(fd, "wb");
991 static FILE *wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
993 return fdopen(fd, "wb");
997 /* internally writing raw bytes (compressed or not) */
998 size_t wtap_dump_file_write(wtap_dumper *wdh, const void *buf, unsigned bufsize)
1001 if(wdh->compressed) {
1002 return gzwrite(wdh->fh, buf, bufsize);
1006 return fwrite(buf, 1, bufsize, wdh->fh);
1010 /* internally close a file for writing (compressed or not) */
1011 static int wtap_dump_file_close(wtap_dumper *wdh)
1014 if(wdh->compressed) {
1015 return gzclose(wdh->fh);
1019 return fclose(wdh->fh);
1023 int wtap_dump_file_ferror(wtap_dumper *wdh)
1028 if(wdh->compressed) {
1029 gzerror(wdh->fh, &errnum);
1031 if(errnum == Z_ERRNO) {
1034 /* XXX - what to do with this zlib specific number? */
1040 return ferror(wdh->fh);