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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
39 #include <wsutil/file_util.h>
42 #include "file_wrappers.h"
44 #include "lanalyzer.h"
45 #include "ngsniffer.h"
47 #include "ascendtext.h"
60 #include "peekclassic.h"
61 #include "peektagged.h"
63 #include "dbs-etherwatch.h"
69 #include "network_instruments.h"
72 #include "catapult_dct2000.h"
75 #include "netscreen.h"
81 #include "dct3trace.h"
82 #include "packetlogger.h"
83 #include "daintree-sna.h"
84 #include "netscaler.h"
85 #include "mime_file.h"
89 #include "stanag4607.h"
90 #include "pcap-encap.h"
93 * Add an extension, and all compressed versions thereof, to a GSList
96 static GSList *add_extensions(GSList *extensions, const gchar *extension,
97 GSList *compressed_file_extensions)
99 GSList *compressed_file_extension;
102 * Add the specified extension.
104 extensions = g_slist_append(extensions, g_strdup(extension));
107 * Now add the extensions for compressed-file versions of
110 for (compressed_file_extension = compressed_file_extensions;
111 compressed_file_extension != NULL;
112 compressed_file_extension = g_slist_next(compressed_file_extension)) {
113 extensions = g_slist_append(extensions,
114 g_strdup_printf("%s.%s", extension,
115 (gchar *)compressed_file_extension->data));
122 * File types that can be identified by file extensions.
124 static const struct file_extension_info file_type_extensions_base[] = {
125 { "Wireshark/tcpdump/... - pcap", "pcap;cap;dmp" },
126 { "Wireshark/... - pcapng", "pcapng;ntar" },
127 { "Network Monitor, Surveyor, NetScaler", "cap" },
128 { "InfoVista 5View capture", "5vw" },
129 { "Sniffer (DOS)", "cap;enc;trc;fdc;syc" },
130 { "NetXRay, Sniffer (Windows)", "cap;caz" },
131 { "Endace ERF capture", "erf" },
132 { "EyeSDN USB S0/E1 ISDN trace format", "trc" },
133 { "HP-UX nettl trace", "trc0;trc1" },
134 { "Network Instruments Observer", "bfr" },
135 { "Novell LANalyzer", "tr1" },
136 { "Tektronix K12xx 32-bit .rf5 format", "rf5" },
137 { "WildPackets *Peek", "pkt;tpc;apc;wpz" },
138 { "Catapult DCT2000 trace (.out format)", "out" },
139 { "MPEG files", "mpg;mp3" },
140 { "CommView", "ncf" },
141 { "Symbian OS btsnoop", "log" },
142 { "Transport-Neutral Encapsulation Format", "tnef" },
143 { "XML files (including Gammu DCT3 traces)", "xml" },
144 { "OS X PacketLogger", "pklg" },
145 { "Daintree SNA", "dcf" },
146 { "JPEG/JFIF files", "jpg;jpeg;jfif" },
147 { "IPFIX File Format", "pfx;ipfix" },
148 { "Aethra .aps file", "aps" },
149 { "MPEG2 transport stream", "mp2t;ts;mpg" },
150 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr" },
151 { "CAM Inspector file", "camins" },
154 #define N_FILE_TYPE_EXTENSIONS (sizeof file_type_extensions_base / sizeof file_type_extensions_base[0])
156 static const struct file_extension_info* file_type_extensions = NULL;
158 static GArray* file_type_extensions_arr = NULL;
160 /* initialize the extensions array if it has not been initialized yet */
161 static void init_file_type_extensions(void) {
163 if (file_type_extensions_arr) return;
165 file_type_extensions_arr = g_array_new(FALSE,TRUE,sizeof(struct file_extension_info));
167 g_array_append_vals(file_type_extensions_arr,file_type_extensions_base,N_FILE_TYPE_EXTENSIONS);
169 file_type_extensions = (struct file_extension_info*)(void *)file_type_extensions_arr->data;
172 void wtap_register_file_type_extension(const struct file_extension_info *ei) {
173 init_file_type_extensions();
175 g_array_append_val(file_type_extensions_arr,*ei);
177 file_type_extensions = (const struct file_extension_info*)(void *)file_type_extensions_arr->data;
180 /* Return a list of all extensions that are used by all file types,
181 including compressed extensions, e.g. not just "pcap" but also
182 "pcap.gz" if we can read gzipped files.
184 All strings in the list are allocated with g_malloc() and must be freed
186 GSList *wtap_get_all_file_extensions_list(void)
188 GSList *compressed_file_extensions;
191 gchar **extensions_set, **extensionp, *extension;
193 init_file_type_extensions();
195 extensions = NULL; /* empty list, to start with */
198 * Get the list of compressed-file extensions.
200 compressed_file_extensions = wtap_get_compressed_file_extensions();
202 for (i = 0; i < file_type_extensions_arr->len; i++) {
204 * Split the extension-list string into a set of extensions.
206 extensions_set = g_strsplit(file_type_extensions[i].extensions,
210 * Add each of those extensions to the list.
212 for (extensionp = extensions_set; *extensionp != NULL;
214 extension = *extensionp;
217 * Add the extension, and all compressed variants
220 extensions = add_extensions(extensions, extension,
221 compressed_file_extensions);
224 g_strfreev(extensions_set);
227 g_slist_free(compressed_file_extensions);
231 /* The open_file_* routines should return:
233 * -1 on an I/O error;
235 * 1 if the file they're reading is one of the types it handles;
237 * 0 if the file they're reading isn't the type they're checking for.
239 * If the routine handles this type of file, it should set the "file_type"
240 * field in the "struct wtap" to the type of the file.
242 * Note that the routine does not have to free the private data pointer on
243 * error. The caller takes care of that by calling wtap_close on error.
244 * (See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8518)
246 * However, the caller does have to free the private data pointer when
247 * returning 0, since the next file type will be called and will likely
248 * just overwrite the pointer.
250 * Put the trace files that are merely saved telnet-sessions last, since it's
251 * possible that you could have captured someone a router telnet-session
252 * using another tool. So, a libpcap trace of an toshiba "snoop" session
253 * should be discovered as a libpcap file, not a toshiba file.
257 static wtap_open_routine_t open_routines_base[] = {
258 /* Files that have magic bytes in fixed locations. These
259 * are easy to identify.
273 network_instruments_open,
277 catapult_dct2000_open,
278 ber_open, /* XXX - this is really a heuristic */
282 packetlogger_open, /* This type does not have a magic number, but its
283 * files are sometimes grabbed by mpeg_open. */
290 /* Files that don't have magic bytes at a fixed location,
291 * but that instead require a heuristic of some sort to
292 * identify them. This includes the ASCII trace files that
293 * would be, for example, saved copies of a Telnet session
297 /* I put NetScreen *before* erf, because there were some
298 * false positives with my test-files (Sake Blok, July 2007)
300 * I put VWR *after* ERF, because there were some cases where
301 * ERF files were misidentified as vwr files (Stephen
302 * Donnelly, August 2013; see bug 9054)
325 #define N_FILE_TYPES (sizeof open_routines_base / sizeof open_routines_base[0])
327 static wtap_open_routine_t* open_routines = NULL;
329 static GArray* open_routines_arr = NULL;
332 /* initialize the open routines array if it has not been initialized yet */
333 static void init_open_routines(void) {
335 if (open_routines_arr) return;
337 open_routines_arr = g_array_new(FALSE,TRUE,sizeof(wtap_open_routine_t));
339 g_array_append_vals(open_routines_arr,open_routines_base,N_FILE_TYPES);
341 open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
344 void wtap_register_open_routine(wtap_open_routine_t open_routine, gboolean has_magic) {
345 init_open_routines();
348 g_array_prepend_val(open_routines_arr,open_routine);
350 g_array_append_val(open_routines_arr,open_routine);
352 open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
356 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
357 * define them either.)
359 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
362 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
365 #define S_IFIFO _S_IFIFO
368 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
371 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
374 /* Opens a file and prepares a wtap struct.
375 If "do_random" is TRUE, it opens the file twice; the second open
376 allows the application to do random-access I/O without moving
377 the seek offset for sequential I/O, which is used by Wireshark
378 so that it can do sequential I/O to a capture file that's being
379 written to as new packets arrive independently of random I/O done
380 to display protocol trees for packets when they're selected. */
381 wtap* wtap_open_offline(const char *filename, int *err, char **err_info,
388 gboolean use_stdin = FALSE;
390 /* open standard input if filename is '-' */
391 if (strcmp(filename, "-") == 0)
394 /* First, make sure the file is valid */
396 if (ws_fstat64(0, &statb) < 0) {
401 if (ws_stat64(filename, &statb) < 0) {
406 if (S_ISFIFO(statb.st_mode)) {
408 * Opens of FIFOs are allowed only when not opening
411 * XXX - currently, we do seeking when trying to find
412 * out the file type, so we don't actually support
413 * opening FIFOs. However, we may eventually
414 * do buffering that allows us to do at least some
415 * file type determination even on pipes, so we
416 * allow FIFO opens and let things fail later when
420 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
423 } else if (S_ISDIR(statb.st_mode)) {
425 * Return different errors for "this is a directory"
426 * and "this is some random special file type", so
427 * the user can get a potentially more helpful error.
431 } else if (! S_ISREG(statb.st_mode)) {
432 *err = WTAP_ERR_NOT_REGULAR_FILE;
437 * We need two independent descriptors for random access, so
438 * they have different file positions. If we're opening the
439 * standard input, we can only dup it to get additional
440 * descriptors, so we can't have two independent descriptors,
441 * and thus can't do random access.
443 if (use_stdin && do_random) {
444 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
449 wth = (wtap *)g_malloc0(sizeof(wtap));
452 errno = WTAP_ERR_CANT_OPEN;
455 * We dup FD 0, so that we don't have to worry about
456 * a file_close of wth->fh closing the standard
457 * input of the process.
466 if (_setmode(fd, O_BINARY) == -1) {
467 /* "Shouldn't happen" */
473 if (!(wth->fh = file_fdopen(fd))) {
480 if (!(wth->fh = file_open(filename))) {
488 if (!(wth->random_fh = file_open(filename))) {
495 wth->random_fh = NULL;
498 wth->file_encap = WTAP_ENCAP_UNKNOWN;
499 wth->subtype_sequential_close = NULL;
500 wth->subtype_close = NULL;
501 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
504 init_open_routines();
505 if (wth->random_fh) {
506 wth->fast_seek = g_ptr_array_new();
508 file_set_random_access(wth->fh, FALSE, wth->fast_seek);
509 file_set_random_access(wth->random_fh, TRUE, wth->fast_seek);
512 /* Try all file types */
513 for (i = 0; i < open_routines_arr->len; i++) {
514 /* Seek back to the beginning of the file; the open routine
515 for the previous file type may have left the file
516 position somewhere other than the beginning, and the
517 open routine for this file type will probably want
518 to start reading at the beginning.
520 Initialize the data offset while we're at it. */
521 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
522 /* I/O error - give up */
527 switch ((*open_routines[i])(wth, err, err_info)) {
530 /* I/O error - give up */
535 /* No I/O error, but not that type of file */
539 /* We found the file type */
544 /* Well, it's not one of the types of file we know about. */
546 *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
550 wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
551 buffer_init(wth->frame_buffer, 1500);
553 if(wth->file_type == WTAP_FILE_PCAP){
555 wtapng_if_descr_t descr;
557 descr.wtap_encap = wth->file_encap;
558 descr.time_units_per_second = 1000000; /* default microsecond resolution */
559 descr.link_type = wtap_wtap_encap_to_pcap_encap(wth->file_encap);
560 descr.snap_len = wth->snapshot_length;
561 descr.opt_comment = NULL;
562 descr.if_name = NULL;
563 descr.if_description = NULL;
565 descr.if_tsresol = 6;
566 descr.if_filter_str= NULL;
567 descr.bpf_filter_len= 0;
568 descr.if_filter_bpf_bytes= NULL;
570 descr.if_fcslen = -1;
571 descr.num_stat_entries = 0; /* Number of ISB:s */
572 descr.interface_statistics = NULL;
573 wth->number_of_interfaces= 1;
574 wth->interface_data= g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
575 g_array_append_val(wth->interface_data, descr);
582 * Given the pathname of the file we just closed with wtap_fdclose(), attempt
583 * to reopen that file and assign the new file descriptor(s) to the sequential
584 * stream and, if do_random is TRUE, to the random stream. Used on Windows
585 * after the rename of a file we had open was done or if the rename of a
586 * file on top of a file we had open failed.
588 * This is only required by Wireshark, not TShark, and, at the point that
589 * Wireshark is doing this, the sequential stream is closed, and the
590 * random stream is open, so this refuses to open pipes, and only
591 * reopens the random stream.
594 wtap_fdreopen(wtap *wth, const char *filename, int *err)
599 * We need two independent descriptors for random access, so
600 * they have different file positions. If we're opening the
601 * standard input, we can only dup it to get additional
602 * descriptors, so we can't have two independent descriptors,
603 * and thus can't do random access.
605 if (strcmp(filename, "-") == 0) {
606 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
610 /* First, make sure the file is valid */
611 if (ws_stat64(filename, &statb) < 0) {
615 if (S_ISFIFO(statb.st_mode)) {
617 * Opens of FIFOs are not allowed; see above.
619 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
621 } else if (S_ISDIR(statb.st_mode)) {
623 * Return different errors for "this is a directory"
624 * and "this is some random special file type", so
625 * the user can get a potentially more helpful error.
629 } else if (! S_ISREG(statb.st_mode)) {
630 *err = WTAP_ERR_NOT_REGULAR_FILE;
635 errno = WTAP_ERR_CANT_OPEN;
636 if (!file_fdreopen(wth->random_fh, filename)) {
643 /* Table of the file types we know about.
644 Entries must be sorted by WTAP_FILE_xxx values in ascending order */
645 static const struct file_type_info dump_open_table_base[] = {
646 /* WTAP_FILE_UNKNOWN (only used internally for initialization) */
647 { NULL, NULL, NULL, NULL,
652 /* Gianluca Varenni suggests that we add "deprecated" to the description. */
653 { "Wireshark/tcpdump/... - pcap", "pcap", "pcap", "cap;dmp",
655 libpcap_dump_can_write_encap, libpcap_dump_open },
657 /* WTAP_FILE_PCAPNG */
658 { "Wireshark/... - pcapng", "pcapng", "pcapng", "ntar",
659 FALSE, TRUE, WTAP_COMMENT_PER_SECTION|WTAP_COMMENT_PER_INTERFACE|WTAP_COMMENT_PER_PACKET,
660 pcapng_dump_can_write_encap, pcapng_dump_open },
662 /* WTAP_FILE_PCAP_NSEC */
663 { "Wireshark - nanosecond libpcap", "nseclibpcap", "pcap", "cap;dmp",
665 libpcap_dump_can_write_encap, libpcap_dump_open },
667 /* WTAP_FILE_PCAP_AIX */
668 { "AIX tcpdump - libpcap", "aixlibpcap", "pcap", "cap;dmp",
672 /* WTAP_FILE_PCAP_SS991029 */
673 { "Modified tcpdump - libpcap", "modlibpcap", "pcap", "cap;dmp",
675 libpcap_dump_can_write_encap, libpcap_dump_open },
677 /* WTAP_FILE_PCAP_NOKIA */
678 { "Nokia tcpdump - libpcap ", "nokialibpcap", "pcap", "cap;dmp",
680 libpcap_dump_can_write_encap, libpcap_dump_open },
682 /* WTAP_FILE_PCAP_SS990417 */
683 { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "pcap", "cap;dmp",
685 libpcap_dump_can_write_encap, libpcap_dump_open },
687 /* WTAP_FILE_PCAP_SS990915 */
688 { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "pcap", "cap;dmp",
690 libpcap_dump_can_write_encap, libpcap_dump_open },
692 /* WTAP_FILE_5VIEWS */
693 { "InfoVista 5View capture", "5views", "5vw", NULL,
695 _5views_dump_can_write_encap, _5views_dump_open },
697 /* WTAP_FILE_IPTRACE_1_0 */
698 { "AIX iptrace 1.0", "iptrace_1", NULL, NULL,
702 /* WTAP_FILE_IPTRACE_2_0 */
703 { "AIX iptrace 2.0", "iptrace_2", NULL, NULL,
708 { "ASN.1 Basic Encoding Rules", "ber", NULL, NULL,
712 /* WTAP_FILE_HCIDUMP */
713 { "Bluetooth HCI dump", "hcidump", NULL, NULL,
717 /* WTAP_FILE_CATAPULT_DCT2000 */
718 { "Catapult DCT2000 trace (.out format)", "dct2000", "out", NULL,
720 catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open },
722 /* WTAP_FILE_NETXRAY_OLD */
723 { "Cinco Networks NetXRay 1.x", "netxray1", "cap", NULL,
727 /* WTAP_FILE_NETXRAY_1_0 */
728 { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL,
732 /* WTAP_FILE_COSINE */
733 { "CoSine IPSX L2 capture", "cosine", "txt", NULL,
737 /* WTAP_FILE_CSIDS */
738 { "CSIDS IPLog", "csids", NULL, NULL,
742 /* WTAP_FILE_DBS_ETHERWATCH */
743 { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL,
748 { "Endace ERF capture", "erf", "erf", NULL,
750 erf_dump_can_write_encap, erf_dump_open },
752 /* WTAP_FILE_EYESDN */
753 { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "trc", NULL,
755 eyesdn_dump_can_write_encap, eyesdn_dump_open },
757 /* WTAP_FILE_NETTL */
758 { "HP-UX nettl trace", "nettl", "trc0", "trc1",
760 nettl_dump_can_write_encap, nettl_dump_open },
762 /* WTAP_FILE_ISERIES */
763 { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "txt", NULL,
767 /* WTAP_FILE_ISERIES_UNICODE */
768 { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL,
772 /* WTAP_FILE_I4BTRACE */
773 { "I4B ISDN trace", "i4btrace", NULL, NULL,
777 /* WTAP_FILE_ASCEND */
778 { "Lucent/Ascend access server trace", "ascend", "txt", NULL,
782 /* WTAP_FILE_NETMON_1_x */
783 { "Microsoft NetMon 1.x", "netmon1", "cap", NULL,
785 netmon_dump_can_write_encap_1_x, netmon_dump_open },
787 /* WTAP_FILE_NETMON_2_x */
788 { "Microsoft NetMon 2.x", "netmon2", "cap", NULL,
790 netmon_dump_can_write_encap_2_x, netmon_dump_open },
792 /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
793 { "Sniffer (DOS)", "ngsniffer", "cap", "enc;trc;fdc;syc",
795 ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
797 /* WTAP_FILE_NGSNIFFER_COMPRESSED */
798 { "Sniffer (DOS), compressed", "ngsniffer_comp", "cap", "enc;trc;fdc;syc",
802 /* WTAP_FILE_NETXRAY_1_1 */
803 { "NetXray, Sniffer (Windows) 1.1", "ngwsniffer_1_1", "cap", NULL,
805 netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 },
807 /* WTAP_FILE_NETXRAY_2_00x */
808 { "Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "cap", "caz",
810 netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 },
812 /* WTAP_FILE_NETWORK_INSTRUMENTS */
813 { "Network Instruments Observer", "niobserver", "bfr", NULL,
815 network_instruments_dump_can_write_encap, network_instruments_dump_open },
817 /* WTAP_FILE_LANALYZER */
818 { "Novell LANalyzer","lanalyzer", "tr1", NULL,
820 lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
822 /* WTAP_FILE_PPPDUMP */
823 { "pppd log (pppdump format)", "pppd", NULL, NULL,
827 /* WTAP_FILE_RADCOM */
828 { "RADCOM WAN/LAN analyzer", "radcom", NULL, NULL,
832 /* WTAP_FILE_SNOOP */
833 { "Sun snoop", "snoop", "snoop", "cap",
835 snoop_dump_can_write_encap, snoop_dump_open },
837 /* WTAP_FILE_SHOMITI */
838 { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL,
843 { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL,
848 { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL,
850 k12_dump_can_write_encap, k12_dump_open },
852 /* WTAP_FILE_TOSHIBA */
853 { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL,
857 /* WTAP_FILE_VISUAL_NETWORKS */
858 { "Visual Networks traffic capture", "visual", NULL, NULL,
860 visual_dump_can_write_encap, visual_dump_open },
862 /* WTAP_FILE_PEEKCLASSIC_V56 */
863 { "WildPackets classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz",
867 /* WTAP_FILE_PEEKCLASSIC_V7 */
868 { "WildPackets classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz",
872 /* WTAP_FILE_PEEKTAGGED */
873 { "WildPackets tagged", "peektagged", "pkt", "tpc;apc;wpz",
878 { "MPEG", "mpeg", "mpeg", "mpg;mp3",
882 /* WTAP_FILE_K12TEXT */
883 { "K12 text file", "k12text", "txt", NULL,
885 k12text_dump_can_write_encap, k12text_dump_open },
887 /* WTAP_FILE_NETSCREEN */
888 { "NetScreen snoop text file", "netscreen", "txt", NULL,
892 /* WTAP_FILE_COMMVIEW */
893 { "TamoSoft CommView", "commview", "ncf", NULL,
895 commview_dump_can_write_encap, commview_dump_open },
897 /* WTAP_FILE_BTSNOOP */
898 { "Symbian OS btsnoop", "btsnoop", "log", NULL,
900 btsnoop_dump_can_write_encap, btsnoop_dump_open_h4 },
903 { "Transport-Neutral Encapsulation Format", "tnef", NULL, NULL,
907 /* WTAP_FILE_DCT3TRACE */
908 { "Gammu DCT3 trace", "dct3trace", "xml", NULL,
912 /* WTAP_FILE_PACKETLOGGER */
913 { "PacketLogger", "pklg", "pklg", NULL,
917 /* WTAP_FILE_DAINTREE_SNA */
918 { "Daintree SNA", "dsna", "dcf", NULL,
922 /* WTAP_FILE_NETSCALER_1_0 */
923 { "NetScaler Trace (Version 1.0)", "nstrace10", NULL, NULL,
925 nstrace_10_dump_can_write_encap, nstrace_dump_open },
927 /* WTAP_FILE_NETSCALER_2_0 */
928 { "NetScaler Trace (Version 2.0)", "nstrace20", "cap", NULL,
930 nstrace_20_dump_can_write_encap, nstrace_dump_open },
932 /* WTAP_FILE_JPEG_JFIF */
933 { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif",
937 /* WTAP_FILE_IPFIX */
938 { "IPFIX File Format", "ipfix", "pfx", "ipfix",
942 /* WTAP_ENCAP_MIME */
943 { "MIME File Format", "mime", NULL, NULL,
947 /* WTAP_FILE_AETHRA */
948 { "Aethra .aps file", "aethra", "aps", NULL,
952 /* WTAP_FILE_MPEG_2_TS */
953 { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg",
957 /* WTAP_FILE_VWR_80211 */
958 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL,
962 /* WTAP_FILE_VWR_ETH */
963 { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL,
967 /* WTAP_FILE_CAMINS */
968 { "CAM Inspector file", "camins", "camins", NULL,
972 /* WTAP_FILE_STANAG_4607 */
973 { "STANAG 4607 Format", "stanag4607", NULL, NULL,
979 gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info);
981 static GArray* dump_open_table_arr = NULL;
982 static const struct file_type_info* dump_open_table = dump_open_table_base;
984 /* initialize the file types array if it has not being initialized yet */
985 static void init_file_types(void) {
987 if (dump_open_table_arr) return;
989 dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_info));
991 g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types);
993 dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
996 int wtap_register_file_type(const struct file_type_info* fi) {
999 g_array_append_val(dump_open_table_arr,*fi);
1001 dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
1003 return wtap_num_file_types++;
1006 int wtap_get_num_file_types(void)
1008 return wtap_num_file_types;
1012 * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
1013 * type that would be needed to write out a file with those types. If
1014 * there's only one type, it's that type, otherwise it's
1015 * WTAP_ENCAP_PER_PACKET.
1018 wtap_dump_file_encap_type(const GArray *file_encaps)
1022 encap = WTAP_ENCAP_PER_PACKET;
1023 if (file_encaps->len == 1) {
1024 /* OK, use the one-and-only encapsulation type. */
1025 encap = g_array_index(file_encaps, gint, 0);
1031 wtap_dump_can_write_encap(int filetype, int encap)
1033 if (filetype < 0 || filetype >= wtap_num_file_types
1034 || dump_open_table[filetype].can_write_encap == NULL)
1037 if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
1044 * Return TRUE if a capture with a given GArray of encapsulation types
1045 * and a given bitset of comment types can be written in a specified
1046 * format, and FALSE if it can't.
1049 wtap_dump_can_write_format(int ft, const GArray *file_encaps,
1050 guint32 required_comment_types)
1055 * Can we write in this format?
1057 if (!wtap_dump_can_open(ft)) {
1063 * Yes. Can we write out all the required comments in this
1066 if (!wtap_dump_supports_comment_types(ft, required_comment_types)) {
1072 * Yes. Is the required per-file encapsulation type supported?
1073 * This might be WTAP_ENCAP_PER_PACKET.
1075 if (!wtap_dump_can_write_encap(ft, wtap_dump_file_encap_type(file_encaps))) {
1081 * Yes. Are all the individual encapsulation types supported?
1083 for (i = 0; i < file_encaps->len; i++) {
1084 if (!wtap_dump_can_write_encap(ft,
1085 g_array_index(file_encaps, int, i))) {
1086 /* No - one of them isn't. */
1091 /* Yes - we're OK. */
1096 * Return TRUE if we can write a file with the given GArray of
1097 * encapsulation types and the given bitmask of comment types.
1100 wtap_dump_can_write(const GArray *file_encaps, guint32 required_comment_types)
1104 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1105 /* To save a file with Wiretap, Wiretap has to handle that format,
1106 and its code to handle that format must be able to write a file
1107 with this file's encapsulation types. */
1108 if (wtap_dump_can_write_format(ft, file_encaps, required_comment_types)) {
1109 /* OK, we can write it out in this type. */
1114 /* No, we couldn't save it in any format. */
1119 * Get a GArray of WTAP_FILE_ values for file types that can be used
1120 * to save a file of a given type with a given GArray of encapsulation
1121 * types and the given bitmask of comment types.
1124 wtap_get_savable_file_types(int file_type, const GArray *file_encaps,
1125 guint32 required_comment_types)
1127 GArray *savable_file_types;
1129 int default_file_type = -1;
1130 int other_file_type = -1;
1132 /* Can we save this file in its own file type? */
1133 if (wtap_dump_can_write_format(file_type, file_encaps,
1134 required_comment_types)) {
1135 /* Yes - make that the default file type. */
1136 default_file_type = file_type;
1138 /* OK, find the first file type we *can* save it as. */
1139 default_file_type = -1;
1140 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1141 if (wtap_dump_can_write_format(ft, file_encaps,
1142 required_comment_types)) {
1144 default_file_type = ft;
1149 if (default_file_type == -1) {
1150 /* We don't support writing this file as any file type. */
1154 /* Allocate the array. */
1155 savable_file_types = g_array_new(FALSE, FALSE, (guint)sizeof (int));
1157 /* Put the default file format first in the list. */
1158 g_array_append_val(savable_file_types, default_file_type);
1160 /* If the default is pcap, put pcap-NG right after it if we can
1161 also write it in pcap-NG format; otherwise, if the default is
1162 pcap-NG, put pcap right after it if we can also write it in
1164 if (default_file_type == WTAP_FILE_PCAP) {
1165 if (wtap_dump_can_write_format(WTAP_FILE_PCAPNG, file_encaps,
1166 required_comment_types))
1167 other_file_type = WTAP_FILE_PCAPNG;
1168 } else if (default_file_type == WTAP_FILE_PCAPNG) {
1169 if (wtap_dump_can_write_format(WTAP_FILE_PCAP, file_encaps,
1170 required_comment_types))
1171 other_file_type = WTAP_FILE_PCAP;
1173 if (other_file_type != -1)
1174 g_array_append_val(savable_file_types, other_file_type);
1176 /* Add all the other file types that work. */
1177 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1178 if (ft == WTAP_FILE_UNKNOWN)
1179 continue; /* not a real file type */
1180 if (ft == default_file_type || ft == other_file_type)
1181 continue; /* we've already done this one */
1182 if (wtap_dump_can_write_format(ft, file_encaps,
1183 required_comment_types)) {
1184 /* OK, we can write it out in this type. */
1185 g_array_append_val(savable_file_types, ft);
1189 return savable_file_types;
1192 /* Name that should be somewhat descriptive. */
1193 const char *wtap_file_type_string(int filetype)
1195 if (filetype < 0 || filetype >= wtap_num_file_types) {
1196 g_error("Unknown capture file type %d", filetype);
1197 /** g_error() does an abort() and thus never returns **/
1200 return dump_open_table[filetype].name;
1203 /* Name to use in, say, a command-line flag specifying the type. */
1204 const char *wtap_file_type_short_string(int filetype)
1206 if (filetype < 0 || filetype >= wtap_num_file_types)
1209 return dump_open_table[filetype].short_name;
1212 /* Translate a short name to a capture file type. */
1213 int wtap_short_string_to_file_type(const char *short_name)
1217 for (filetype = 0; filetype < wtap_num_file_types; filetype++) {
1218 if (dump_open_table[filetype].short_name != NULL &&
1219 strcmp(short_name, dump_open_table[filetype].short_name) == 0)
1224 * We now call the "libpcap" file format just "pcap", but we
1225 * allow it to be specified as "libpcap" as well, for
1226 * backwards compatibility.
1228 if (strcmp(short_name, "libpcap") == 0)
1229 return WTAP_FILE_PCAP;
1231 return -1; /* no such file type, or we can't write it */
1235 add_extensions_for_filetype(int filetype, GSList *extensions,
1236 GSList *compressed_file_extensions)
1238 gchar **extensions_set, **extensionp;
1242 * Add the default extension, and all compressed variants of
1245 extensions = add_extensions(extensions,
1246 dump_open_table[filetype].default_file_extension,
1247 compressed_file_extensions);
1249 if (dump_open_table[filetype].additional_file_extensions != NULL) {
1251 * We have additional extensions; add them.
1253 * First, split the extension-list string into a set of
1256 extensions_set = g_strsplit(dump_open_table[filetype].additional_file_extensions,
1260 * Add each of those extensions to the list.
1262 for (extensionp = extensions_set; *extensionp != NULL;
1264 extension = *extensionp;
1267 * Add the extension, and all compressed variants
1270 extensions = add_extensions(extensions, extension,
1271 compressed_file_extensions);
1274 g_strfreev(extensions_set);
1279 /* Return a list of file extensions that are used by the specified file type.
1281 If include_compressed is TRUE, the list will include compressed
1282 extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
1285 All strings in the list are allocated with g_malloc() and must be freed
1287 GSList *wtap_get_file_extensions_list(int filetype, gboolean include_compressed)
1289 GSList *compressed_file_extensions;
1292 if (filetype < 0 || filetype >= wtap_num_file_types)
1293 return NULL; /* not a valid file type */
1295 if (dump_open_table[filetype].default_file_extension == NULL)
1296 return NULL; /* valid, but no extensions known */
1298 extensions = NULL; /* empty list, to start with */
1301 * If include_compressions is true, get the list of compressed-file
1304 if (include_compressed)
1305 compressed_file_extensions = wtap_get_compressed_file_extensions();
1307 compressed_file_extensions = NULL;
1310 * Add all this file type's extensions, with compressed
1313 extensions = add_extensions_for_filetype(filetype, extensions,
1314 compressed_file_extensions);
1316 g_slist_free(compressed_file_extensions);
1321 * Free a list returned by wtap_get_file_extensions_list().
1323 void wtap_free_file_extensions_list(GSList *extensions)
1327 for (extension = extensions; extension != NULL;
1328 extension = g_slist_next(extension)) {
1329 g_free(extension->data);
1331 g_slist_free(extensions);
1334 /* Return the default file extension to use with the specified file type;
1335 that's just the extension, without any ".". */
1336 const char *wtap_default_file_extension(int filetype)
1338 if (filetype < 0 || filetype >= wtap_num_file_types)
1341 return dump_open_table[filetype].default_file_extension;
1344 gboolean wtap_dump_can_open(int filetype)
1346 if (filetype < 0 || filetype >= wtap_num_file_types
1347 || dump_open_table[filetype].dump_open == NULL)
1354 gboolean wtap_dump_can_compress(int filetype)
1357 * If this is an unknown file type, or if we have to
1358 * seek when writing out a file with this file type,
1361 if (filetype < 0 || filetype >= wtap_num_file_types
1362 || dump_open_table[filetype].writing_must_seek)
1368 gboolean wtap_dump_can_compress(int filetype _U_)
1374 gboolean wtap_dump_has_name_resolution(int filetype)
1376 if (filetype < 0 || filetype >= wtap_num_file_types
1377 || dump_open_table[filetype].has_name_resolution == FALSE)
1383 gboolean wtap_dump_supports_comment_types(int filetype, guint32 comment_types)
1385 guint32 supported_comment_types;
1387 if (filetype < 0 || filetype >= wtap_num_file_types)
1390 supported_comment_types = dump_open_table[filetype].supported_comment_types;
1392 if ((comment_types & supported_comment_types) == comment_types)
1397 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
1398 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1399 gboolean compressed, int *err);
1400 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err);
1402 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
1403 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
1404 static int wtap_dump_file_close(wtap_dumper *wdh);
1406 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
1407 int snaplen, gboolean compressed, int *err)
1409 return wtap_dump_open_ng(filename, filetype, encap,snaplen, compressed, NULL, NULL, err);
1412 static wtap_dumper *
1413 wtap_dump_init_dumper(int filetype, int encap, int snaplen, gboolean compressed,
1414 wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1418 /* Allocate a data structure for the output stream. */
1419 wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
1421 return NULL; /* couldn't allocate it */
1423 /* Set Section Header Block data */
1424 wdh->shb_hdr = shb_hdr;
1425 /* Set Interface Description Block data */
1426 if ((idb_inf != NULL) && (idb_inf->number_of_interfaces > 0)) {
1427 wdh->number_of_interfaces = idb_inf->number_of_interfaces;
1428 wdh->interface_data = idb_inf->interface_data;
1430 wtapng_if_descr_t descr;
1432 descr.wtap_encap = encap;
1433 descr.time_units_per_second = 1000000; /* default microsecond resolution */
1434 descr.link_type = wtap_wtap_encap_to_pcap_encap(encap);
1435 descr.snap_len = snaplen;
1436 descr.opt_comment = NULL;
1437 descr.if_name = g_strdup("Unknown/not available in original file format(libpcap)");
1438 descr.if_description = NULL;
1440 descr.if_tsresol = 6;
1441 descr.if_filter_str= NULL;
1442 descr.bpf_filter_len= 0;
1443 descr.if_filter_bpf_bytes= NULL;
1445 descr.if_fcslen = -1;
1446 descr.num_stat_entries = 0; /* Number of ISB:s */
1447 descr.interface_statistics = NULL;
1448 wdh->number_of_interfaces= 1;
1449 wdh->interface_data= g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1450 g_array_append_val(wdh->interface_data, descr);
1455 wtap_dumper* wtap_dump_open_ng(const char *filename, int filetype, int encap,
1456 int snaplen, gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1461 /* Check whether we can open a capture file with that file type
1462 and that encapsulation. */
1463 if (!wtap_dump_open_check(filetype, encap, compressed, err))
1466 /* Allocate and initialize a data structure for the output stream. */
1467 wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1468 shb_hdr, idb_inf, err);
1472 /* "-" means stdout */
1473 if (strcmp(filename, "-") == 0) {
1475 *err = EINVAL; /* XXX - return a Wiretap error code for this */
1477 return NULL; /* compress won't work on stdout */
1480 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1481 /* "Should not happen" */
1484 return NULL; /* couldn't put standard output in binary mode */
1489 /* In case "fopen()" fails but doesn't set "errno", set "errno"
1490 to a generic "the open failed" error. */
1491 errno = WTAP_ERR_CANT_OPEN;
1492 fh = wtap_dump_file_open(wdh, filename);
1496 return NULL; /* can't create file */
1501 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1502 /* Get rid of the file we created; we couldn't finish
1504 if (wdh->fh != stdout) {
1505 wtap_dump_file_close(wdh);
1506 ws_unlink(filename);
1514 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
1515 gboolean compressed, int *err)
1517 return wtap_dump_fdopen_ng(fd, filetype, encap, snaplen, compressed, NULL, NULL, err);
1520 wtap_dumper* wtap_dump_fdopen_ng(int fd, int filetype, int encap, int snaplen,
1521 gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1526 /* Check whether we can open a capture file with that file type
1527 and that encapsulation. */
1528 if (!wtap_dump_open_check(filetype, encap, compressed, err))
1531 /* Allocate and initialize a data structure for the output stream. */
1532 wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1533 shb_hdr, idb_inf, err);
1539 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1540 /* "Should not happen" */
1543 return NULL; /* couldn't put standard output in binary mode */
1548 /* In case "fopen()" fails but doesn't set "errno", set "errno"
1549 to a generic "the open failed" error. */
1550 errno = WTAP_ERR_CANT_OPEN;
1551 fh = wtap_dump_file_fdopen(wdh, fd);
1555 return NULL; /* can't create standard I/O stream */
1559 if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1560 wtap_dump_file_close(wdh);
1567 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err)
1569 if (!wtap_dump_can_open(filetype)) {
1570 /* Invalid type, or type we don't know how to write. */
1571 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1575 /* OK, we know how to write that type; can we write the specified
1576 encapsulation type? */
1577 *err = (*dump_open_table[filetype].can_write_encap)(encap);
1581 /* if compression is wanted, do we support this for this filetype? */
1582 if(compressed && !wtap_dump_can_compress(filetype)) {
1583 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
1587 *err = (*dump_open_table[filetype].can_write_encap)(encap);
1591 /* All systems go! */
1595 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1596 gboolean compressed, int *err)
1600 wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
1606 wdh->file_type = filetype;
1607 wdh->snaplen = snaplen;
1609 wdh->compressed = compressed;
1613 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err)
1618 /* Can we do a seek on the file descriptor?
1619 If not, note that fact. */
1623 fd = fileno((FILE *)wdh->fh);
1624 if (lseek(fd, 1, SEEK_CUR) == -1)
1627 /* Undo the seek. */
1628 lseek(fd, 0, SEEK_SET);
1633 /* If this file type requires seeking, and we can't seek, fail. */
1634 if (dump_open_table[filetype].writing_must_seek && cant_seek) {
1635 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
1639 /* Now try to open the file for writing. */
1640 if (!(*dump_open_table[filetype].dump_open)(wdh, err)) {
1644 return TRUE; /* success! */
1647 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1648 const guint8 *pd, int *err)
1650 return (wdh->subtype_write)(wdh, phdr, pd, err);
1653 void wtap_dump_flush(wtap_dumper *wdh)
1656 if(wdh->compressed) {
1657 gzwfile_flush((GZWFILE_T)wdh->fh);
1661 fflush((FILE *)wdh->fh);
1665 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
1667 gboolean ret = TRUE;
1669 if (wdh->subtype_close != NULL) {
1670 /* There's a close routine for this dump stream. */
1671 if (!(wdh->subtype_close)(wdh, err))
1674 errno = WTAP_ERR_CANT_CLOSE;
1675 /* Don't close stdout */
1676 if (wdh->fh != stdout) {
1677 if (wtap_dump_file_close(wdh) == EOF) {
1679 /* The per-format close function succeeded,
1680 but the fclose didn't. Save the reason
1681 why, if our caller asked for it. */
1688 /* as we don't close stdout, at least try to flush it */
1689 wtap_dump_flush(wdh);
1691 if (wdh->priv != NULL)
1697 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
1699 return wdh->bytes_dumped;
1702 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
1704 wdh->bytes_dumped = bytes_dumped;
1707 gboolean wtap_dump_set_addrinfo_list(wtap_dumper *wdh, addrinfo_lists_t *addrinfo_lists)
1709 if (!wdh || wdh->file_type < 0 || wdh->file_type >= wtap_num_file_types
1710 || dump_open_table[wdh->file_type].has_name_resolution == FALSE)
1712 wdh->addrinfo_lists = addrinfo_lists;
1716 /* internally open a file for writing (compressed or not) */
1718 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
1720 if(wdh->compressed) {
1721 return gzwfile_open(filename);
1723 return ws_fopen(filename, "wb");
1727 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
1729 return ws_fopen(filename, "wb");
1733 /* internally open a file for writing (compressed or not) */
1735 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
1737 if(wdh->compressed) {
1738 return gzwfile_fdopen(fd);
1740 return fdopen(fd, "wb");
1744 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
1746 return fdopen(fd, "wb");
1750 /* internally writing raw bytes (compressed or not) */
1751 gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize,
1757 if (wdh->compressed) {
1758 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned) bufsize);
1760 * gzwfile_write() returns 0 on error.
1762 if (nwritten == 0) {
1763 *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
1769 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
1771 * At least according to the Mac OS X man page,
1772 * this can return a short count on an error.
1774 if (nwritten != bufsize) {
1775 if (ferror((FILE *)wdh->fh))
1778 *err = WTAP_ERR_SHORT_WRITE;
1785 /* internally close a file for writing (compressed or not) */
1786 static int wtap_dump_file_close(wtap_dumper *wdh)
1789 if(wdh->compressed) {
1790 return gzwfile_close((GZWFILE_T)wdh->fh);
1794 return fclose((FILE *)wdh->fh);
1798 gint64 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
1801 if(wdh->compressed) {
1802 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1807 if (-1 == fseek((FILE *)wdh->fh, (long)offset, whence)) {
1816 gint64 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
1820 if(wdh->compressed) {
1821 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1826 if (-1 == (rval = ftell((FILE *)wdh->fh))) {