For the Windows Open dialog for capture files, get rid of the "(*.*)" in
[metze/wireshark/wip.git] / wiretap / file_access.c
1 /* file_access.c
2  *
3  * $Id$
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7  *
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.
12  *
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.
17  *
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.
21  */
22
23 #include "config.h"
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 #ifdef HAVE_FCNTL_H
30 #include <fcntl.h>
31 #endif
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 #include <errno.h>
38
39 #include <wsutil/file_util.h>
40
41 #include "wtap-int.h"
42 #include "file_wrappers.h"
43 #include "buffer.h"
44 #include "lanalyzer.h"
45 #include "ngsniffer.h"
46 #include "radcom.h"
47 #include "ascendtext.h"
48 #include "nettl.h"
49 #include "libpcap.h"
50 #include "snoop.h"
51 #include "iptrace.h"
52 #include "iseries.h"
53 #include "netmon.h"
54 #include "netxray.h"
55 #include "toshiba.h"
56 #include "eyesdn.h"
57 #include "i4btrace.h"
58 #include "csids.h"
59 #include "pppdump.h"
60 #include "peekclassic.h"
61 #include "peektagged.h"
62 #include "vms.h"
63 #include "dbs-etherwatch.h"
64 #include "visual.h"
65 #include "cosine.h"
66 #include "5views.h"
67 #include "erf.h"
68 #include "hcidump.h"
69 #include "network_instruments.h"
70 #include "k12.h"
71 #include "ber.h"
72 #include "catapult_dct2000.h"
73 #include "mp2t.h"
74 #include "mpeg.h"
75 #include "netscreen.h"
76 #include "commview.h"
77 #include "pcapng.h"
78 #include "aethra.h"
79 #include "btsnoop.h"
80 #include "tnef.h"
81 #include "dct3trace.h"
82 #include "packetlogger.h"
83 #include "daintree-sna.h"
84 #include "netscaler.h"
85 #include "mime_file.h"
86 #include "ipfix.h"
87 #include "vwr.h"
88 #include "camins.h"
89 #include "stanag4607.h"
90 #include "pcap-encap.h"
91
92 /* The open_file_* routines should return:
93  *
94  *      -1 on an I/O error;
95  *
96  *      1 if the file they're reading is one of the types it handles;
97  *
98  *      0 if the file they're reading isn't the type they're checking for.
99  *
100  * If the routine handles this type of file, it should set the "file_type"
101  * field in the "struct wtap" to the type of the file.
102  *
103  * Note that the routine does not have to free the private data pointer on
104  * error. The caller takes care of that by calling wtap_close on error.
105  * (See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8518)
106  *
107  * However, the caller does have to free the private data pointer when
108  * returning 0, since the next file type will be called and will likely
109  * just overwrite the pointer.
110  *
111  * Put the trace files that are merely saved telnet-sessions last, since it's
112  * possible that you could have captured someone a router telnet-session
113  * using another tool. So, a libpcap trace of an toshiba "snoop" session
114  * should be discovered as a libpcap file, not a toshiba file.
115  */
116
117
118 static wtap_open_routine_t open_routines_base[] = {
119         /* Files that have magic bytes in fixed locations. These
120          * are easy to identify.
121          */
122         libpcap_open,
123         pcapng_open,
124         lanalyzer_open,
125         ngsniffer_open,
126         snoop_open,
127         iptrace_open,
128         netmon_open,
129         netxray_open,
130         radcom_open,
131         nettl_open,
132         visual_open,
133         _5views_open,
134         network_instruments_open,
135         peektagged_open,
136         dbs_etherwatch_open,
137         k12_open,
138         catapult_dct2000_open,
139         ber_open,          /* XXX - this is really a heuristic */
140         aethra_open,
141         btsnoop_open,
142         eyesdn_open,
143         packetlogger_open, /* This type does not have a magic number, but its
144                             * files are sometimes grabbed by mpeg_open. */
145         mpeg_open,
146         tnef_open,
147         dct3trace_open,
148         daintree_sna_open,
149         mime_file_open,
150         stanag4607_open,
151         /* Files that don't have magic bytes at a fixed location,
152          * but that instead require a heuristic of some sort to
153          * identify them.  This includes the ASCII trace files that
154          * would be, for example, saved copies of a Telnet session
155          * to some box.
156          */
157
158         /* I put NetScreen *before* erf, because there were some
159          * false positives with my test-files (Sake Blok, July 2007)
160          *
161          * I put VWR *after* ERF, because there were some cases where
162          * ERF files were misidentified as vwr files (Stephen
163          * Donnelly, August 2013; see bug 9054)
164          */
165         netscreen_open,
166         erf_open,
167         vwr_open,
168         ipfix_open,
169         k12text_open,
170         peekclassic_open,
171         pppdump_open,
172         iseries_open,
173         ascend_open,
174         toshiba_open,
175         i4btrace_open,
176         mp2t_open,
177         csids_open,
178         vms_open,
179         cosine_open,
180         hcidump_open,
181         commview_open,
182         nstrace_open,
183         camins_open
184 };
185
186 #define N_FILE_TYPES    (sizeof open_routines_base / sizeof open_routines_base[0])
187
188 static wtap_open_routine_t* open_routines = NULL;
189
190 static GArray* open_routines_arr = NULL;
191
192
193 /* initialize the open routines array if it has not been initialized yet */
194 static void init_open_routines(void) {
195
196         if (open_routines_arr) return;
197
198         open_routines_arr = g_array_new(FALSE,TRUE,sizeof(wtap_open_routine_t));
199
200         g_array_append_vals(open_routines_arr,open_routines_base,N_FILE_TYPES);
201
202         open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
203 }
204
205 void wtap_register_open_routine(wtap_open_routine_t open_routine, gboolean has_magic) {
206         init_open_routines();
207
208         if (has_magic)
209                 g_array_prepend_val(open_routines_arr,open_routine);
210         else
211                 g_array_append_val(open_routines_arr,open_routine);
212
213         open_routines = (wtap_open_routine_t*)(void *)open_routines_arr->data;
214 }
215
216 /*
217  * Visual C++ on Win32 systems doesn't define these.  (Old UNIX systems don't
218  * define them either.)
219  *
220  * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
221  */
222 #ifndef S_ISREG
223 #define S_ISREG(mode)   (((mode) & S_IFMT) == S_IFREG)
224 #endif
225 #ifndef S_IFIFO
226 #define S_IFIFO _S_IFIFO
227 #endif
228 #ifndef S_ISFIFO
229 #define S_ISFIFO(mode)  (((mode) & S_IFMT) == S_IFIFO)
230 #endif
231 #ifndef S_ISDIR
232 #define S_ISDIR(mode)   (((mode) & S_IFMT) == S_IFDIR)
233 #endif
234
235 /* Opens a file and prepares a wtap struct.
236    If "do_random" is TRUE, it opens the file twice; the second open
237    allows the application to do random-access I/O without moving
238    the seek offset for sequential I/O, which is used by Wireshark
239    so that it can do sequential I/O to a capture file that's being
240    written to as new packets arrive independently of random I/O done
241    to display protocol trees for packets when they're selected. */
242 wtap* wtap_open_offline(const char *filename, int *err, char **err_info,
243                         gboolean do_random)
244 {
245         int     fd;
246         ws_statb64 statb;
247         wtap    *wth;
248         unsigned int    i;
249         gboolean use_stdin = FALSE;
250
251         /* open standard input if filename is '-' */
252         if (strcmp(filename, "-") == 0)
253                 use_stdin = TRUE;
254
255         /* First, make sure the file is valid */
256         if (use_stdin) {
257                 if (ws_fstat64(0, &statb) < 0) {
258                         *err = errno;
259                         return NULL;
260                 }
261         } else {
262                 if (ws_stat64(filename, &statb) < 0) {
263                         *err = errno;
264                         return NULL;
265                 }
266         }
267         if (S_ISFIFO(statb.st_mode)) {
268                 /*
269                  * Opens of FIFOs are allowed only when not opening
270                  * for random access.
271                  *
272                  * XXX - currently, we do seeking when trying to find
273                  * out the file type, so we don't actually support
274                  * opening FIFOs.  However, we may eventually
275                  * do buffering that allows us to do at least some
276                  * file type determination even on pipes, so we
277                  * allow FIFO opens and let things fail later when
278                  * we try to seek.
279                  */
280                 if (do_random) {
281                         *err = WTAP_ERR_RANDOM_OPEN_PIPE;
282                         return NULL;
283                 }
284         } else if (S_ISDIR(statb.st_mode)) {
285                 /*
286                  * Return different errors for "this is a directory"
287                  * and "this is some random special file type", so
288                  * the user can get a potentially more helpful error.
289                  */
290                 *err = EISDIR;
291                 return NULL;
292         } else if (! S_ISREG(statb.st_mode)) {
293                 *err = WTAP_ERR_NOT_REGULAR_FILE;
294                 return NULL;
295         }
296
297         /*
298          * We need two independent descriptors for random access, so
299          * they have different file positions.  If we're opening the
300          * standard input, we can only dup it to get additional
301          * descriptors, so we can't have two independent descriptors,
302          * and thus can't do random access.
303          */
304         if (use_stdin && do_random) {
305                 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
306                 return NULL;
307         }
308
309         errno = ENOMEM;
310         wth = (wtap *)g_malloc0(sizeof(wtap));
311
312         /* Open the file */
313         errno = WTAP_ERR_CANT_OPEN;
314         if (use_stdin) {
315                 /*
316                  * We dup FD 0, so that we don't have to worry about
317                  * a file_close of wth->fh closing the standard
318                  * input of the process.
319                  */
320                 fd = ws_dup(0);
321                 if (fd < 0) {
322                         *err = errno;
323                         g_free(wth);
324                         return NULL;
325                 }
326 #ifdef _WIN32
327                 if (_setmode(fd, O_BINARY) == -1) {
328                         /* "Shouldn't happen" */
329                         *err = errno;
330                         g_free(wth);
331                         return NULL;
332                 }
333 #endif
334                 if (!(wth->fh = file_fdopen(fd))) {
335                         *err = errno;
336                         ws_close(fd);
337                         g_free(wth);
338                         return NULL;
339                 }
340         } else {
341                 if (!(wth->fh = file_open(filename))) {
342                         *err = errno;
343                         g_free(wth);
344                         return NULL;
345                 }
346         }
347
348         if (do_random) {
349                 if (!(wth->random_fh = file_open(filename))) {
350                         *err = errno;
351                         file_close(wth->fh);
352                         g_free(wth);
353                         return NULL;
354                 }
355         } else
356                 wth->random_fh = NULL;
357
358         /* initialization */
359         wth->file_encap = WTAP_ENCAP_UNKNOWN;
360         wth->subtype_sequential_close = NULL;
361         wth->subtype_close = NULL;
362         wth->tsprecision = WTAP_FILE_TSPREC_USEC;
363         wth->priv = NULL;
364
365         init_open_routines();
366         if (wth->random_fh) {
367                 wth->fast_seek = g_ptr_array_new();
368
369                 file_set_random_access(wth->fh, FALSE, wth->fast_seek);
370                 file_set_random_access(wth->random_fh, TRUE, wth->fast_seek);
371         }
372
373         /* Try all file types */
374         for (i = 0; i < open_routines_arr->len; i++) {
375                 /* Seek back to the beginning of the file; the open routine
376                    for the previous file type may have left the file
377                    position somewhere other than the beginning, and the
378                    open routine for this file type will probably want
379                    to start reading at the beginning.
380
381                    Initialize the data offset while we're at it. */
382                 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
383                         /* I/O error - give up */
384                         wtap_close(wth);
385                         return NULL;
386                 }
387
388                 switch ((*open_routines[i])(wth, err, err_info)) {
389
390                 case -1:
391                         /* I/O error - give up */
392                         wtap_close(wth);
393                         return NULL;
394
395                 case 0:
396                         /* No I/O error, but not that type of file */
397                         break;
398
399                 case 1:
400                         /* We found the file type */
401                         goto success;
402                 }
403         }
404
405         /* Well, it's not one of the types of file we know about. */
406         wtap_close(wth);
407         *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
408         return NULL;
409
410 success:
411         wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
412         buffer_init(wth->frame_buffer, 1500);
413
414         if(wth->file_type == WTAP_FILE_PCAP){
415
416                 wtapng_if_descr_t descr;
417
418                 descr.wtap_encap = wth->file_encap;
419                 descr.time_units_per_second = 1000000; /* default microsecond resolution */
420                 descr.link_type = wtap_wtap_encap_to_pcap_encap(wth->file_encap);
421                 descr.snap_len = wth->snapshot_length;
422                 descr.opt_comment = NULL;
423                 descr.if_name = NULL;
424                 descr.if_description = NULL;
425                 descr.if_speed = 0;
426                 descr.if_tsresol = 6;
427                 descr.if_filter_str= NULL;
428                 descr.bpf_filter_len= 0;
429                 descr.if_filter_bpf_bytes= NULL;
430                 descr.if_os = NULL;
431                 descr.if_fcslen = -1;
432                 descr.num_stat_entries = 0;          /* Number of ISB:s */
433                 descr.interface_statistics = NULL;
434                 wth->number_of_interfaces= 1;
435                 wth->interface_data= g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
436                 g_array_append_val(wth->interface_data, descr);
437
438         }
439         return wth;
440 }
441
442 /*
443  * Given the pathname of the file we just closed with wtap_fdclose(), attempt
444  * to reopen that file and assign the new file descriptor(s) to the sequential
445  * stream and, if do_random is TRUE, to the random stream.  Used on Windows
446  * after the rename of a file we had open was done or if the rename of a
447  * file on top of a file we had open failed.
448  *
449  * This is only required by Wireshark, not TShark, and, at the point that
450  * Wireshark is doing this, the sequential stream is closed, and the
451  * random stream is open, so this refuses to open pipes, and only
452  * reopens the random stream.
453  */
454 gboolean
455 wtap_fdreopen(wtap *wth, const char *filename, int *err)
456 {
457         ws_statb64 statb;
458
459         /*
460          * We need two independent descriptors for random access, so
461          * they have different file positions.  If we're opening the
462          * standard input, we can only dup it to get additional
463          * descriptors, so we can't have two independent descriptors,
464          * and thus can't do random access.
465          */
466         if (strcmp(filename, "-") == 0) {
467                 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
468                 return FALSE;
469         }
470
471         /* First, make sure the file is valid */
472         if (ws_stat64(filename, &statb) < 0) {
473                 *err = errno;
474                 return FALSE;
475         }
476         if (S_ISFIFO(statb.st_mode)) {
477                 /*
478                  * Opens of FIFOs are not allowed; see above.
479                  */
480                 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
481                 return FALSE;
482         } else if (S_ISDIR(statb.st_mode)) {
483                 /*
484                  * Return different errors for "this is a directory"
485                  * and "this is some random special file type", so
486                  * the user can get a potentially more helpful error.
487                  */
488                 *err = EISDIR;
489                 return FALSE;
490         } else if (! S_ISREG(statb.st_mode)) {
491                 *err = WTAP_ERR_NOT_REGULAR_FILE;
492                 return FALSE;
493         }
494
495         /* Open the file */
496         errno = WTAP_ERR_CANT_OPEN;
497         if (!file_fdreopen(wth->random_fh, filename)) {
498                 *err = errno;
499                 return FALSE;
500         }
501         return TRUE;
502 }
503
504 /* Table of the file types we know about.
505    Entries must be sorted by WTAP_FILE_xxx values in ascending order */
506 static const struct file_type_info dump_open_table_base[] = {
507         /* WTAP_FILE_UNKNOWN (only used internally for initialization) */
508         { NULL, NULL, NULL, NULL,
509           FALSE, FALSE, 0,
510           NULL, NULL },
511
512         /* WTAP_FILE_PCAP */
513         /* Gianluca Varenni suggests that we add "deprecated" to the description. */
514         { "Wireshark/tcpdump/... - pcap", "pcap", "pcap", "cap;dmp",
515           FALSE, FALSE, 0,
516           libpcap_dump_can_write_encap, libpcap_dump_open },
517
518         /* WTAP_FILE_PCAPNG */
519         { "Wireshark/... - pcapng", "pcapng", "pcapng", "ntar",
520           FALSE, TRUE, WTAP_COMMENT_PER_SECTION|WTAP_COMMENT_PER_INTERFACE|WTAP_COMMENT_PER_PACKET,
521           pcapng_dump_can_write_encap, pcapng_dump_open },
522
523         /* WTAP_FILE_PCAP_NSEC */
524         { "Wireshark - nanosecond libpcap", "nseclibpcap", "pcap", "cap;dmp",
525           FALSE, FALSE, 0,
526           libpcap_dump_can_write_encap, libpcap_dump_open },
527
528         /* WTAP_FILE_PCAP_AIX */
529         { "AIX tcpdump - libpcap", "aixlibpcap", "pcap", "cap;dmp",
530           FALSE, FALSE, 0,
531           NULL, NULL },
532
533         /* WTAP_FILE_PCAP_SS991029 */
534         { "Modified tcpdump - libpcap", "modlibpcap", "pcap", "cap;dmp",
535           FALSE, FALSE, 0,
536           libpcap_dump_can_write_encap, libpcap_dump_open },
537
538         /* WTAP_FILE_PCAP_NOKIA */
539         { "Nokia tcpdump - libpcap ", "nokialibpcap", "pcap", "cap;dmp",
540           FALSE, FALSE, 0,
541           libpcap_dump_can_write_encap, libpcap_dump_open },
542
543         /* WTAP_FILE_PCAP_SS990417 */
544         { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "pcap", "cap;dmp",
545           FALSE, FALSE, 0,
546           libpcap_dump_can_write_encap, libpcap_dump_open },
547
548         /* WTAP_FILE_PCAP_SS990915 */
549         { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "pcap", "cap;dmp",
550           FALSE, FALSE, 0,
551           libpcap_dump_can_write_encap, libpcap_dump_open },
552
553         /* WTAP_FILE_5VIEWS */
554         { "InfoVista 5View capture", "5views", "5vw", NULL,
555            TRUE, FALSE, 0,
556           _5views_dump_can_write_encap, _5views_dump_open },
557
558         /* WTAP_FILE_IPTRACE_1_0 */
559         { "AIX iptrace 1.0", "iptrace_1", NULL, NULL,
560           FALSE, FALSE, 0,
561           NULL, NULL },
562
563         /* WTAP_FILE_IPTRACE_2_0 */
564         { "AIX iptrace 2.0", "iptrace_2", NULL, NULL,
565           FALSE, FALSE, 0,
566           NULL, NULL },
567
568         /* WTAP_FILE_BER */
569         { "ASN.1 Basic Encoding Rules", "ber", NULL, NULL,
570           FALSE, FALSE, 0,
571           NULL, NULL },
572
573         /* WTAP_FILE_HCIDUMP */
574         { "Bluetooth HCI dump", "hcidump", NULL, NULL,
575           FALSE, FALSE, 0,
576           NULL, NULL },
577
578         /* WTAP_FILE_CATAPULT_DCT2000 */
579         { "Catapult DCT2000 trace (.out format)", "dct2000", "out", NULL,
580           FALSE, FALSE, 0,
581           catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open },
582
583         /* WTAP_FILE_NETXRAY_OLD */
584         { "Cinco Networks NetXRay 1.x", "netxray1", "cap", NULL,
585           TRUE, FALSE, 0,
586           NULL, NULL },
587
588         /* WTAP_FILE_NETXRAY_1_0 */
589         { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL,
590           TRUE, FALSE, 0,
591           NULL, NULL },
592
593         /* WTAP_FILE_COSINE */
594         { "CoSine IPSX L2 capture", "cosine", "txt", NULL,
595           FALSE, FALSE, 0,
596           NULL, NULL },
597
598         /* WTAP_FILE_CSIDS */
599         { "CSIDS IPLog", "csids", NULL, NULL,
600           FALSE, FALSE, 0,
601           NULL, NULL },
602
603         /* WTAP_FILE_DBS_ETHERWATCH */
604         { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL,
605           FALSE, FALSE, 0,
606           NULL, NULL},
607
608         /* WTAP_FILE_ERF */
609         { "Endace ERF capture", "erf", "erf", NULL,
610           FALSE, FALSE, 0,
611           erf_dump_can_write_encap, erf_dump_open },
612
613         /* WTAP_FILE_EYESDN */
614         { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "trc", NULL,
615            FALSE, FALSE, 0,
616            eyesdn_dump_can_write_encap, eyesdn_dump_open },
617
618         /* WTAP_FILE_NETTL */
619         { "HP-UX nettl trace", "nettl", "trc0", "trc1",
620           FALSE, FALSE, 0,
621           nettl_dump_can_write_encap, nettl_dump_open },
622
623         /* WTAP_FILE_ISERIES */
624         { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "txt", NULL,
625           FALSE, FALSE, 0,
626           NULL, NULL },
627
628         /* WTAP_FILE_ISERIES_UNICODE */
629         { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL,
630           FALSE, FALSE, 0,
631           NULL, NULL },
632
633         /* WTAP_FILE_I4BTRACE */
634         { "I4B ISDN trace", "i4btrace", NULL, NULL,
635           FALSE, FALSE, 0,
636           NULL, NULL },
637
638         /* WTAP_FILE_ASCEND */
639         { "Lucent/Ascend access server trace", "ascend", "txt", NULL,
640           FALSE, FALSE, 0,
641           NULL, NULL },
642
643         /* WTAP_FILE_NETMON_1_x */
644         { "Microsoft NetMon 1.x", "netmon1", "cap", NULL,
645           TRUE, FALSE, 0,
646           netmon_dump_can_write_encap_1_x, netmon_dump_open },
647
648         /* WTAP_FILE_NETMON_2_x */
649         { "Microsoft NetMon 2.x", "netmon2", "cap", NULL,
650           TRUE, FALSE, 0,
651           netmon_dump_can_write_encap_2_x, netmon_dump_open },
652
653         /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
654         { "NA Sniffer (DOS)", "ngsniffer", "cap", "enc;trc;fdc;syc",
655           FALSE, FALSE, 0,
656           ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
657
658         /* WTAP_FILE_NGSNIFFER_COMPRESSED */
659         { "NA Sniffer (DOS), compressed", "ngsniffer_comp", "cap", "enc;trc;fdc;syc",
660           FALSE, FALSE, 0,
661           NULL, NULL },
662
663         /* WTAP_FILE_NETXRAY_1_1 */
664         { "NA Sniffer (Windows) 1.1", "ngwsniffer_1_1", "cap", NULL,
665           TRUE, FALSE, 0,
666           netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 },
667
668         /* WTAP_FILE_NETXRAY_2_00x */
669         { "NA Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "cap", "caz",
670           TRUE, FALSE, 0,
671           netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 },
672
673         /* WTAP_FILE_NETWORK_INSTRUMENTS */
674         { "Network Instruments Observer", "niobserver", "bfr", NULL,
675           FALSE, FALSE, 0,
676           network_instruments_dump_can_write_encap, network_instruments_dump_open },
677
678         /* WTAP_FILE_LANALYZER */
679         { "Novell LANalyzer","lanalyzer", "tr1", NULL,
680           TRUE, FALSE, 0,
681           lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
682
683         /* WTAP_FILE_PPPDUMP */
684         { "pppd log (pppdump format)", "pppd", NULL, NULL,
685           FALSE, FALSE, 0,
686           NULL, NULL },
687
688         /* WTAP_FILE_RADCOM */
689         { "RADCOM WAN/LAN analyzer", "radcom", NULL, NULL,
690           FALSE, FALSE, 0,
691           NULL, NULL },
692
693         /* WTAP_FILE_SNOOP */
694         { "Sun snoop", "snoop", "snoop", "cap",
695           FALSE, FALSE, 0,
696           snoop_dump_can_write_encap, snoop_dump_open },
697
698         /* WTAP_FILE_SHOMITI */
699         { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL,
700           FALSE, FALSE, 0,
701           NULL, NULL },
702
703         /* WTAP_FILE_VMS */
704         { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL,
705           FALSE, FALSE, 0,
706           NULL, NULL},
707
708         /* WTAP_FILE_K12 */
709         { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL,
710            TRUE, FALSE, 0,
711            k12_dump_can_write_encap, k12_dump_open },
712
713         /* WTAP_FILE_TOSHIBA */
714         { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL,
715           FALSE, FALSE, 0,
716           NULL, NULL },
717
718         /* WTAP_FILE_VISUAL_NETWORKS */
719         { "Visual Networks traffic capture", "visual", NULL, NULL,
720           TRUE, FALSE, 0,
721           visual_dump_can_write_encap, visual_dump_open },
722
723         /* WTAP_FILE_PEEKCLASSIC_V56 */
724         { "WildPackets classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz",
725           FALSE, FALSE, 0,
726           NULL, NULL },
727
728         /* WTAP_FILE_PEEKCLASSIC_V7 */
729         { "WildPackets classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz",
730           FALSE, FALSE, 0,
731           NULL, NULL },
732
733         /* WTAP_FILE_PEEKTAGGED */
734         { "WildPackets tagged", "peektagged", "pkt", "tpc;apc;wpz",
735           FALSE, FALSE, 0,
736           NULL, NULL },
737
738         /* WTAP_FILE_MPEG */
739         { "MPEG", "mpeg", "mpeg", "mpg;mp3",
740           FALSE, FALSE, 0,
741           NULL, NULL },
742
743         /* WTAP_FILE_K12TEXT  */
744         { "K12 text file", "k12text", "txt", NULL,
745           FALSE, FALSE, 0,
746           k12text_dump_can_write_encap, k12text_dump_open },
747
748         /* WTAP_FILE_NETSCREEN */
749         { "NetScreen snoop text file", "netscreen", "txt", NULL,
750           FALSE, FALSE, 0,
751           NULL, NULL },
752
753         /* WTAP_FILE_COMMVIEW */
754         { "TamoSoft CommView", "commview", "ncf", NULL,
755           FALSE, FALSE, 0,
756           commview_dump_can_write_encap, commview_dump_open },
757
758         /* WTAP_FILE_BTSNOOP */
759         { "Symbian OS btsnoop", "btsnoop", "log", NULL,
760           FALSE, FALSE, 0,
761           btsnoop_dump_can_write_encap, btsnoop_dump_open_h4 },
762
763         /* WTAP_FILE_TNEF */
764         { "Transport-Neutral Encapsulation Format", "tnef", NULL, NULL,
765           FALSE, FALSE, 0,
766           NULL, NULL },
767
768         /* WTAP_FILE_DCT3TRACE */
769         { "Gammu DCT3 trace", "dct3trace", "xml", NULL,
770           FALSE, FALSE, 0,
771           NULL, NULL },
772
773         /* WTAP_FILE_PACKETLOGGER */
774         { "PacketLogger", "pklg", "pklg", NULL,
775           FALSE, FALSE, 0,
776           NULL, NULL },
777
778         /* WTAP_FILE_DAINTREE_SNA */
779         { "Daintree SNA", "dsna", "dcf", NULL,
780           FALSE, FALSE, 0,
781           NULL, NULL },
782
783         /* WTAP_FILE_NETSCALER_1_0 */
784         { "NetScaler Trace (Version 1.0)", "nstrace10", NULL, NULL,
785           TRUE, FALSE, 0,
786           nstrace_10_dump_can_write_encap, nstrace_dump_open },
787
788         /* WTAP_FILE_NETSCALER_2_0 */
789         { "NetScaler Trace (Version 2.0)", "nstrace20", "cap", NULL,
790           TRUE, FALSE, 0,
791           nstrace_20_dump_can_write_encap, nstrace_dump_open },
792
793         /* WTAP_FILE_JPEG_JFIF */
794         { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif",
795           FALSE, FALSE, 0,
796           NULL, NULL },
797
798         /* WTAP_FILE_IPFIX */
799         { "IPFIX File Format", "ipfix", "pfx", "ipfix",
800           FALSE, FALSE, 0,
801           NULL, NULL },
802
803         /* WTAP_ENCAP_MIME */
804         { "MIME File Format", "mime", NULL, NULL,
805            FALSE, FALSE, 0,
806            NULL, NULL },
807
808         /* WTAP_FILE_AETHRA */
809         { "Aethra .aps file", "aethra", "aps", NULL,
810           FALSE, FALSE, 0,
811           NULL, NULL },
812
813         /* WTAP_FILE_MPEG_2_TS */
814         { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg",
815           FALSE, FALSE, 0,
816           NULL, NULL },
817
818         /* WTAP_FILE_VWR_80211 */
819         { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL,
820           FALSE, FALSE, 0,
821           NULL, NULL },
822
823         /* WTAP_FILE_VWR_ETH */
824         { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL,
825           FALSE, FALSE, 0,
826           NULL, NULL },
827
828         /* WTAP_FILE_CAMINS */
829         { "CAM Inspector file", "camins", "camins", NULL,
830           FALSE, FALSE, 0,
831           NULL, NULL },
832
833         /* WTAP_FILE_STANAG_4607 */
834         { "STANAG 4607 Format", "stanag4607", NULL, NULL,
835           FALSE, FALSE, 0,
836           NULL, NULL }
837
838 };
839
840 gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info);
841
842 static GArray*  dump_open_table_arr = NULL;
843 static const struct file_type_info* dump_open_table = dump_open_table_base;
844
845 /* initialize the open routines array if it has not being initialized yet */
846 static void init_file_types(void) {
847
848         if (dump_open_table_arr) return;
849
850         dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_info));
851
852         g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types);
853
854         dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
855 }
856
857 int wtap_register_file_type(const struct file_type_info* fi) {
858         init_file_types();
859
860         g_array_append_val(dump_open_table_arr,*fi);
861
862         dump_open_table = (const struct file_type_info*)(void *)dump_open_table_arr->data;
863
864         return wtap_num_file_types++;
865 }
866
867 int wtap_get_num_file_types(void)
868 {
869         return wtap_num_file_types;
870 }
871
872 /*
873  * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
874  * type that would be needed to write out a file with those types.  If
875  * there's only one type, it's that type, otherwise it's
876  * WTAP_ENCAP_PER_PACKET.
877  */
878 int
879 wtap_dump_file_encap_type(const GArray *file_encaps)
880 {
881         int encap;
882
883         encap = WTAP_ENCAP_PER_PACKET;
884         if (file_encaps->len == 1) {
885                 /* OK, use the one-and-only encapsulation type. */
886                 encap = g_array_index(file_encaps, gint, 0);
887         }
888         return encap;
889 }
890
891 static gboolean
892 wtap_dump_can_write_encap(int filetype, int encap)
893 {
894         if (filetype < 0 || filetype >= wtap_num_file_types
895             || dump_open_table[filetype].can_write_encap == NULL)
896                 return FALSE;
897
898         if ((*dump_open_table[filetype].can_write_encap)(encap) != 0)
899                 return FALSE;
900
901         return TRUE;
902 }
903
904 /*
905  * Return TRUE if a capture with a given GArray of encapsulation types
906  * and a given bitset of comment types can be written in a specified
907  * format, and FALSE if it can't.
908  */
909 static gboolean
910 wtap_dump_can_write_format(int ft, const GArray *file_encaps,
911     guint32 required_comment_types)
912 {
913         guint i;
914
915         /*
916          * Can we write in this format?
917          */
918         if (!wtap_dump_can_open(ft)) {
919                 /* No. */
920                 return FALSE;
921         }
922
923         /*
924          * Yes.  Can we write out all the required comments in this
925          * format?
926          */
927         if (!wtap_dump_supports_comment_types(ft, required_comment_types)) {
928                 /* No. */
929                 return FALSE;
930         }
931
932         /*
933          * Yes.  Is the required per-file encapsulation type supported?
934          * This might be WTAP_ENCAP_PER_PACKET.
935          */
936         if (!wtap_dump_can_write_encap(ft, wtap_dump_file_encap_type(file_encaps))) {
937                 /* No. */
938                 return FALSE;
939         }
940
941         /*
942          * Yes.  Are all the individual encapsulation types supported?
943          */
944         for (i = 0; i < file_encaps->len; i++) {
945                 if (!wtap_dump_can_write_encap(ft,
946                     g_array_index(file_encaps, int, i))) {
947                         /* No - one of them isn't. */
948                         return FALSE;
949                 }
950         }
951
952         /* Yes - we're OK. */
953         return TRUE;
954 }
955
956 /**
957  * Return TRUE if we can write a file with the given GArray of
958  * encapsulation types and the given bitmask of comment types.
959  */
960 gboolean
961 wtap_dump_can_write(const GArray *file_encaps, guint32 required_comment_types)
962 {
963   int ft;
964
965   for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
966     /* To save a file with Wiretap, Wiretap has to handle that format,
967        and its code to handle that format must be able to write a file
968        with this file's encapsulation types. */
969     if (wtap_dump_can_write_format(ft, file_encaps, required_comment_types)) {
970       /* OK, we can write it out in this type. */
971       return TRUE;
972     }
973   }
974
975   /* No, we couldn't save it in any format. */
976   return FALSE;
977 }
978
979 /**
980  * Get a GArray of WTAP_FILE_ values for file types that can be used
981  * to save a file of a given type with a given GArray of encapsulation
982  * types and the given bitmask of comment types.
983  */
984 GArray *
985 wtap_get_savable_file_types(int file_type, const GArray *file_encaps,
986     guint32 required_comment_types)
987 {
988         GArray *savable_file_types;
989         int ft;
990         int default_file_type = -1;
991         int other_file_type = -1;
992
993         /* Can we save this file in its own file type? */
994         if (wtap_dump_can_write_format(file_type, file_encaps,
995                                        required_comment_types)) {
996                 /* Yes - make that the default file type. */
997                 default_file_type = file_type;
998         } else {
999                 /* OK, find the first file type we *can* save it as. */
1000                 default_file_type = -1;
1001                 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1002                         if (wtap_dump_can_write_format(ft, file_encaps,
1003                                                        required_comment_types)) {
1004                                 /* OK, got it. */
1005                                 default_file_type = ft;
1006                         }
1007                 }
1008         }
1009
1010         if (default_file_type == -1) {
1011                 /* We don't support writing this file as any file type. */
1012                 return NULL;
1013         }
1014
1015         /* Allocate the array. */
1016         savable_file_types = g_array_new(FALSE, FALSE, (guint)sizeof (int));
1017
1018         /* Put the default file format first in the list. */
1019         g_array_append_val(savable_file_types, default_file_type);
1020
1021         /* If the default is pcap, put pcap-NG right after it if we can
1022            also write it in pcap-NG format; otherwise, if the default is
1023            pcap-NG, put pcap right after it if we can also write it in
1024            pcap format. */
1025         if (default_file_type == WTAP_FILE_PCAP) {
1026                 if (wtap_dump_can_write_format(WTAP_FILE_PCAPNG, file_encaps,
1027                                                required_comment_types))
1028                         other_file_type = WTAP_FILE_PCAPNG;
1029         } else if (default_file_type == WTAP_FILE_PCAPNG) {
1030                 if (wtap_dump_can_write_format(WTAP_FILE_PCAP, file_encaps,
1031                                                required_comment_types))
1032                         other_file_type = WTAP_FILE_PCAP;
1033         }
1034         if (other_file_type != -1)
1035                 g_array_append_val(savable_file_types, other_file_type);
1036
1037         /* Add all the other file types that work. */
1038         for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1039                 if (ft == WTAP_FILE_UNKNOWN)
1040                         continue;       /* not a real file type */
1041                 if (ft == default_file_type || ft == other_file_type)
1042                         continue;       /* we've already done this one */
1043                 if (wtap_dump_can_write_format(ft, file_encaps,
1044                                                required_comment_types)) {
1045                         /* OK, we can write it out in this type. */
1046                         g_array_append_val(savable_file_types, ft);
1047                 }
1048         }
1049
1050         return savable_file_types;
1051 }
1052
1053 /* Name that should be somewhat descriptive. */
1054 const char *wtap_file_type_string(int filetype)
1055 {
1056         if (filetype < 0 || filetype >= wtap_num_file_types) {
1057                 g_error("Unknown capture file type %d", filetype);
1058                 /** g_error() does an abort() and thus never returns **/
1059                 return "";
1060         } else
1061                 return dump_open_table[filetype].name;
1062 }
1063
1064 /* Name to use in, say, a command-line flag specifying the type. */
1065 const char *wtap_file_type_short_string(int filetype)
1066 {
1067         if (filetype < 0 || filetype >= wtap_num_file_types)
1068                 return NULL;
1069         else
1070                 return dump_open_table[filetype].short_name;
1071 }
1072
1073 /* Translate a short name to a capture file type. */
1074 int wtap_short_string_to_file_type(const char *short_name)
1075 {
1076         int filetype;
1077
1078         for (filetype = 0; filetype < wtap_num_file_types; filetype++) {
1079                 if (dump_open_table[filetype].short_name != NULL &&
1080                     strcmp(short_name, dump_open_table[filetype].short_name) == 0)
1081                         return filetype;
1082         }
1083
1084         /*
1085          * We now call the "libpcap" file format just "pcap", but we
1086          * allow it to be specified as "libpcap" as well, for
1087          * backwards compatibility.
1088          */
1089         if (strcmp(short_name, "libpcap") == 0)
1090                 return WTAP_FILE_PCAP;
1091
1092         return -1;      /* no such file type, or we can't write it */
1093 }
1094
1095 static GSList *add_extensions(GSList *extensions, const gchar *extension,
1096     GSList *compressed_file_extensions)
1097 {
1098         GSList *compressed_file_extension;
1099
1100         /*
1101          * Add the specified extension.
1102          */
1103         extensions = g_slist_append(extensions, g_strdup(extension));
1104
1105         /*
1106          * Now add the extensions for compressed-file versions of
1107          * that extension.
1108          */
1109         for (compressed_file_extension = compressed_file_extensions;
1110             compressed_file_extension != NULL;
1111             compressed_file_extension = g_slist_next(compressed_file_extension)) {
1112                 extensions = g_slist_append(extensions,
1113                     g_strdup_printf("%s.%s", extension,
1114                       (gchar *)compressed_file_extension->data));
1115         }
1116
1117         return extensions;
1118 }
1119
1120 static GSList *
1121 add_extensions_for_filetype(int filetype, GSList *extensions,
1122     GSList *compressed_file_extensions)
1123 {
1124         gchar **extensions_set, **extensionp;
1125         gchar *extension;
1126
1127         /*
1128          * Add the default extension, and all compressed variants of
1129          * it.
1130          */
1131         extensions = add_extensions(extensions,
1132             dump_open_table[filetype].default_file_extension,
1133             compressed_file_extensions);
1134
1135         if (dump_open_table[filetype].additional_file_extensions != NULL) {
1136                 /*
1137                  * We have additional extensions; add them.
1138                  *
1139                  * First, split the extension-list string into a set of
1140                  * extensions.
1141                  */
1142                 extensions_set = g_strsplit(dump_open_table[filetype].additional_file_extensions,
1143                     ";", 0);
1144
1145                 /*
1146                  * Add each of those extensions to the list.
1147                  */
1148                 for (extensionp = extensions_set; *extensionp != NULL;
1149                     extensionp++) {
1150                         extension = *extensionp;
1151
1152                         /*
1153                          * Add the extension, and all compressed variants
1154                          * of it.
1155                          */
1156                         extensions = add_extensions(extensions, extension,
1157                             compressed_file_extensions);
1158                 }
1159
1160                 g_strfreev(extensions_set);
1161         }
1162         return extensions;
1163 }
1164
1165 /* Return a list of all extensions that are used by all file types,
1166    including compressed extensions, e.g. not just "pcap" but also
1167    "pcap.gz" if we can read gzipped files.
1168
1169    All strings in the list are allocated with g_malloc() and must be freed
1170    with g_free(). */
1171 GSList *wtap_get_all_file_extensions_list(void)
1172 {
1173         GSList *compressed_file_extensions;
1174         GSList *extensions;
1175         int filetype;
1176
1177         extensions = NULL;      /* empty list, to start with */
1178
1179         /*
1180          * Get the list of compressed-file extensions.
1181          */
1182         compressed_file_extensions = wtap_get_compressed_file_extensions();
1183
1184         for (filetype = 0; filetype < WTAP_NUM_FILE_TYPES; filetype++) {
1185                 if (dump_open_table[filetype].default_file_extension != NULL) {
1186                         /*
1187                          * This file type has at least one extension.
1188                          * Add all its extensions, with compressed
1189                          * variants.
1190                          */
1191                         extensions = add_extensions_for_filetype(filetype,
1192                             extensions, compressed_file_extensions);
1193                 }
1194         }
1195
1196         g_slist_free(compressed_file_extensions);
1197         return extensions;
1198 }
1199
1200 /* Return a list of file extensions that are used by the specified file type.
1201
1202    If include_compressed is TRUE, the list will include compressed
1203    extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
1204    gzipped files.
1205
1206    All strings in the list are allocated with g_malloc() and must be freed
1207    with g_free(). */
1208 GSList *wtap_get_file_extensions_list(int filetype, gboolean include_compressed)
1209 {
1210         GSList *compressed_file_extensions;
1211         GSList *extensions;
1212
1213         if (filetype < 0 || filetype >= wtap_num_file_types)
1214                 return NULL;    /* not a valid file type */
1215
1216         if (dump_open_table[filetype].default_file_extension == NULL)
1217                 return NULL;    /* valid, but no extensions known */
1218
1219         extensions = NULL;      /* empty list, to start with */
1220
1221         /*
1222          * If include_compressions is true, get the list of compressed-file
1223          * extensions.
1224          */
1225         if (include_compressed)
1226                 compressed_file_extensions = wtap_get_compressed_file_extensions();
1227         else
1228                 compressed_file_extensions = NULL;
1229
1230         /*
1231          * Add all this file type's extensions, with compressed
1232          * variants.
1233          */
1234         extensions = add_extensions_for_filetype(filetype, extensions,
1235             compressed_file_extensions);
1236
1237         g_slist_free(compressed_file_extensions);
1238         return extensions;
1239 }
1240
1241 /*
1242  * Free a list returned by wtap_get_file_extensions_list().
1243  */
1244 void wtap_free_file_extensions_list(GSList *extensions)
1245 {
1246         GSList *extension;
1247
1248         for (extension = extensions; extension != NULL;
1249             extension = g_slist_next(extension)) {
1250                 g_free(extension->data);
1251         }
1252         g_slist_free(extensions);
1253 }
1254
1255 /* Return the default file extension to use with the specified file type;
1256    that's just the extension, without any ".". */
1257 const char *wtap_default_file_extension(int filetype)
1258 {
1259         if (filetype < 0 || filetype >= wtap_num_file_types)
1260                 return NULL;
1261         else
1262                 return dump_open_table[filetype].default_file_extension;
1263 }
1264
1265 gboolean wtap_dump_can_open(int filetype)
1266 {
1267         if (filetype < 0 || filetype >= wtap_num_file_types
1268             || dump_open_table[filetype].dump_open == NULL)
1269                 return FALSE;
1270
1271         return TRUE;
1272 }
1273
1274 #ifdef HAVE_LIBZ
1275 gboolean wtap_dump_can_compress(int filetype)
1276 {
1277         /*
1278          * If this is an unknown file type, or if we have to
1279          * seek when writing out a file with this file type,
1280          * return FALSE.
1281          */
1282         if (filetype < 0 || filetype >= wtap_num_file_types
1283             || dump_open_table[filetype].writing_must_seek)
1284                 return FALSE;
1285
1286         return TRUE;
1287 }
1288 #else
1289 gboolean wtap_dump_can_compress(int filetype _U_)
1290 {
1291         return FALSE;
1292 }
1293 #endif
1294
1295 gboolean wtap_dump_has_name_resolution(int filetype)
1296 {
1297         if (filetype < 0 || filetype >= wtap_num_file_types
1298             || dump_open_table[filetype].has_name_resolution == FALSE)
1299                 return FALSE;
1300
1301         return TRUE;
1302 }
1303
1304 gboolean wtap_dump_supports_comment_types(int filetype, guint32 comment_types)
1305 {
1306         guint32 supported_comment_types;
1307
1308         if (filetype < 0 || filetype >= wtap_num_file_types)
1309                 return FALSE;
1310
1311         supported_comment_types = dump_open_table[filetype].supported_comment_types;
1312
1313         if ((comment_types & supported_comment_types) == comment_types)
1314                 return TRUE;
1315         return FALSE;
1316 }
1317
1318 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err);
1319 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1320                                         gboolean compressed, int *err);
1321 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err);
1322
1323 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
1324 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
1325 static int wtap_dump_file_close(wtap_dumper *wdh);
1326
1327 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
1328                                 int snaplen, gboolean compressed, int *err)
1329 {
1330         return wtap_dump_open_ng(filename, filetype, encap,snaplen, compressed, NULL, NULL, err);
1331 }
1332
1333 static wtap_dumper *
1334 wtap_dump_init_dumper(int filetype, int encap, int snaplen, gboolean compressed,
1335     wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1336 {
1337         wtap_dumper *wdh;
1338
1339         /* Allocate a data structure for the output stream. */
1340         wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err);
1341         if (wdh == NULL)
1342                 return NULL;    /* couldn't allocate it */
1343
1344         /* Set Section Header Block data */
1345         wdh->shb_hdr = shb_hdr;
1346         /* Set Interface Description Block data */
1347         if ((idb_inf != NULL) && (idb_inf->number_of_interfaces > 0)) {
1348                 wdh->number_of_interfaces = idb_inf->number_of_interfaces;
1349                 wdh->interface_data = idb_inf->interface_data;
1350         } else {
1351                 wtapng_if_descr_t descr;
1352
1353                 descr.wtap_encap = encap;
1354                 descr.time_units_per_second = 1000000; /* default microsecond resolution */
1355                 descr.link_type = wtap_wtap_encap_to_pcap_encap(encap);
1356                 descr.snap_len = snaplen;
1357                 descr.opt_comment = NULL;
1358                 descr.if_name = g_strdup("Unknown/not available in original file format(libpcap)");
1359                 descr.if_description = NULL;
1360                 descr.if_speed = 0;
1361                 descr.if_tsresol = 6;
1362                 descr.if_filter_str= NULL;
1363                 descr.bpf_filter_len= 0;
1364                 descr.if_filter_bpf_bytes= NULL;
1365                 descr.if_os = NULL;
1366                 descr.if_fcslen = -1;
1367                 descr.num_stat_entries = 0;          /* Number of ISB:s */
1368                 descr.interface_statistics = NULL;
1369                 wdh->number_of_interfaces= 1;
1370                 wdh->interface_data= g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1371                 g_array_append_val(wdh->interface_data, descr);
1372         }
1373         return wdh;
1374 }
1375
1376 wtap_dumper* wtap_dump_open_ng(const char *filename, int filetype, int encap,
1377                                 int snaplen, gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1378 {
1379         wtap_dumper *wdh;
1380         WFILE_T fh;
1381
1382         /* Check whether we can open a capture file with that file type
1383            and that encapsulation. */
1384         if (!wtap_dump_open_check(filetype, encap, compressed, err))
1385                 return NULL;
1386
1387         /* Allocate and initialize a data structure for the output stream. */
1388         wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1389             shb_hdr, idb_inf, err);
1390         if (wdh == NULL)
1391                 return NULL;
1392
1393         /* "-" means stdout */
1394         if (strcmp(filename, "-") == 0) {
1395                 if (compressed) {
1396                         *err = EINVAL;  /* XXX - return a Wiretap error code for this */
1397                         g_free(wdh);
1398                         return NULL;    /* compress won't work on stdout */
1399                 }
1400 #ifdef _WIN32
1401                 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1402                         /* "Should not happen" */
1403                         *err = errno;
1404                         g_free(wdh);
1405                         return NULL;    /* couldn't put standard output in binary mode */
1406                 }
1407 #endif
1408                 wdh->fh = stdout;
1409         } else {
1410                 /* In case "fopen()" fails but doesn't set "errno", set "errno"
1411                    to a generic "the open failed" error. */
1412                 errno = WTAP_ERR_CANT_OPEN;
1413                 fh = wtap_dump_file_open(wdh, filename);
1414                 if (fh == NULL) {
1415                         *err = errno;
1416                         g_free(wdh);
1417                         return NULL;    /* can't create file */
1418                 }
1419                 wdh->fh = fh;
1420         }
1421
1422         if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1423                 /* Get rid of the file we created; we couldn't finish
1424                    opening it. */
1425                 if (wdh->fh != stdout) {
1426                         wtap_dump_file_close(wdh);
1427                         ws_unlink(filename);
1428                 }
1429                 g_free(wdh);
1430                 return NULL;
1431         }
1432         return wdh;
1433 }
1434
1435 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
1436                                 gboolean compressed, int *err)
1437 {
1438         return wtap_dump_fdopen_ng(fd, filetype, encap, snaplen, compressed, NULL, NULL, err);
1439 }
1440
1441 wtap_dumper* wtap_dump_fdopen_ng(int fd, int filetype, int encap, int snaplen,
1442                                 gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
1443 {
1444         wtap_dumper *wdh;
1445         WFILE_T fh;
1446
1447         /* Check whether we can open a capture file with that file type
1448            and that encapsulation. */
1449         if (!wtap_dump_open_check(filetype, encap, compressed, err))
1450                 return NULL;
1451
1452         /* Allocate and initialize a data structure for the output stream. */
1453         wdh = wtap_dump_init_dumper(filetype, encap, snaplen, compressed,
1454             shb_hdr, idb_inf, err);
1455         if (wdh == NULL)
1456                 return NULL;
1457
1458 #ifdef _WIN32
1459         if (fd == 1) {
1460                 if (_setmode(fileno(stdout), O_BINARY) == -1) {
1461                         /* "Should not happen" */
1462                         *err = errno;
1463                         g_free(wdh);
1464                         return NULL;    /* couldn't put standard output in binary mode */
1465                 }
1466         }
1467 #endif
1468
1469         /* In case "fopen()" fails but doesn't set "errno", set "errno"
1470            to a generic "the open failed" error. */
1471         errno = WTAP_ERR_CANT_OPEN;
1472         fh = wtap_dump_file_fdopen(wdh, fd);
1473         if (fh == NULL) {
1474                 *err = errno;
1475                 g_free(wdh);
1476                 return NULL;    /* can't create standard I/O stream */
1477         }
1478         wdh->fh = fh;
1479
1480         if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) {
1481                 wtap_dump_file_close(wdh);
1482                 g_free(wdh);
1483                 return NULL;
1484         }
1485         return wdh;
1486 }
1487
1488 static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err)
1489 {
1490         if (!wtap_dump_can_open(filetype)) {
1491                 /* Invalid type, or type we don't know how to write. */
1492                 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1493                 return FALSE;
1494         }
1495
1496         /* OK, we know how to write that type; can we write the specified
1497            encapsulation type? */
1498         *err = (*dump_open_table[filetype].can_write_encap)(encap);
1499         if (*err != 0)
1500                 return FALSE;
1501
1502         /* if compression is wanted, do we support this for this filetype? */
1503         if(compressed && !wtap_dump_can_compress(filetype)) {
1504                 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
1505                 return FALSE;
1506         }
1507
1508         *err = (*dump_open_table[filetype].can_write_encap)(encap);
1509         if (*err != 0)
1510                 return FALSE;
1511
1512         /* All systems go! */
1513         return TRUE;
1514 }
1515
1516 static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen,
1517                                         gboolean compressed, int *err)
1518 {
1519         wtap_dumper *wdh;
1520
1521         wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
1522         if (wdh == NULL) {
1523                 *err = errno;
1524                 return NULL;
1525         }
1526
1527         wdh->file_type = filetype;
1528         wdh->snaplen = snaplen;
1529         wdh->encap = encap;
1530         wdh->compressed = compressed;
1531         return wdh;
1532 }
1533
1534 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err)
1535 {
1536         int fd;
1537         gboolean cant_seek;
1538
1539         /* Can we do a seek on the file descriptor?
1540            If not, note that fact. */
1541         if(compressed) {
1542                 cant_seek = TRUE;
1543         } else {
1544                 fd = fileno((FILE *)wdh->fh);
1545                 if (lseek(fd, 1, SEEK_CUR) == -1)
1546                         cant_seek = TRUE;
1547                 else {
1548                         /* Undo the seek. */
1549                         lseek(fd, 0, SEEK_SET);
1550                         cant_seek = FALSE;
1551                 }
1552         }
1553
1554         /* If this file type requires seeking, and we can't seek, fail. */
1555         if (dump_open_table[filetype].writing_must_seek && cant_seek) {
1556                 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
1557                 return FALSE;
1558         }
1559
1560         /* Now try to open the file for writing. */
1561         if (!(*dump_open_table[filetype].dump_open)(wdh, err)) {
1562                 return FALSE;
1563         }
1564
1565         return TRUE;    /* success! */
1566 }
1567
1568 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1569                    const guint8 *pd, int *err)
1570 {
1571         return (wdh->subtype_write)(wdh, phdr, pd, err);
1572 }
1573
1574 void wtap_dump_flush(wtap_dumper *wdh)
1575 {
1576 #ifdef HAVE_LIBZ
1577         if(wdh->compressed) {
1578                 gzwfile_flush((GZWFILE_T)wdh->fh);
1579         } else
1580 #endif
1581         {
1582                 fflush((FILE *)wdh->fh);
1583         }
1584 }
1585
1586 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
1587 {
1588         gboolean ret = TRUE;
1589
1590         if (wdh->subtype_close != NULL) {
1591                 /* There's a close routine for this dump stream. */
1592                 if (!(wdh->subtype_close)(wdh, err))
1593                         ret = FALSE;
1594         }
1595         errno = WTAP_ERR_CANT_CLOSE;
1596         /* Don't close stdout */
1597         if (wdh->fh != stdout) {
1598                 if (wtap_dump_file_close(wdh) == EOF) {
1599                         if (ret) {
1600                                 /* The per-format close function succeeded,
1601                                    but the fclose didn't.  Save the reason
1602                                    why, if our caller asked for it. */
1603                                 if (err != NULL)
1604                                         *err = errno;
1605                         }
1606                         ret = FALSE;
1607                 }
1608         } else {
1609                 /* as we don't close stdout, at least try to flush it */
1610                 wtap_dump_flush(wdh);
1611         }
1612         if (wdh->priv != NULL)
1613                 g_free(wdh->priv);
1614         g_free(wdh);
1615         return ret;
1616 }
1617
1618 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
1619 {
1620         return wdh->bytes_dumped;
1621 }
1622
1623 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
1624 {
1625         wdh->bytes_dumped = bytes_dumped;
1626 }
1627
1628 gboolean wtap_dump_set_addrinfo_list(wtap_dumper *wdh, struct addrinfo *addrinfo_list)
1629 {
1630         if (!wdh || wdh->file_type < 0 || wdh->file_type >= wtap_num_file_types
1631                 || dump_open_table[wdh->file_type].has_name_resolution == FALSE)
1632                         return FALSE;
1633         wdh->addrinfo_list = addrinfo_list;
1634         return TRUE;
1635 }
1636
1637 /* internally open a file for writing (compressed or not) */
1638 #ifdef HAVE_LIBZ
1639 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
1640 {
1641         if(wdh->compressed) {
1642                 return gzwfile_open(filename);
1643         } else {
1644                 return ws_fopen(filename, "wb");
1645         }
1646 }
1647 #else
1648 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
1649 {
1650         return ws_fopen(filename, "wb");
1651 }
1652 #endif
1653
1654 /* internally open a file for writing (compressed or not) */
1655 #ifdef HAVE_LIBZ
1656 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
1657 {
1658         if(wdh->compressed) {
1659                 return gzwfile_fdopen(fd);
1660         } else {
1661                 return fdopen(fd, "wb");
1662         }
1663 }
1664 #else
1665 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
1666 {
1667         return fdopen(fd, "wb");
1668 }
1669 #endif
1670
1671 /* internally writing raw bytes (compressed or not) */
1672 gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize,
1673                      int *err)
1674 {
1675         size_t nwritten;
1676
1677 #ifdef HAVE_LIBZ
1678         if (wdh->compressed) {
1679                 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned) bufsize);
1680                 /*
1681                  * gzwfile_write() returns 0 on error.
1682                  */
1683                 if (nwritten == 0) {
1684                         *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
1685                         return FALSE;
1686                 }
1687         } else
1688 #endif
1689         {
1690                 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
1691                 /*
1692                  * At least according to the Mac OS X man page,
1693                  * this can return a short count on an error.
1694                  */
1695                 if (nwritten != bufsize) {
1696                         if (ferror((FILE *)wdh->fh))
1697                                 *err = errno;
1698                         else
1699                                 *err = WTAP_ERR_SHORT_WRITE;
1700                         return FALSE;
1701                 }
1702         }
1703         return TRUE;
1704 }
1705
1706 /* internally close a file for writing (compressed or not) */
1707 static int wtap_dump_file_close(wtap_dumper *wdh)
1708 {
1709 #ifdef HAVE_LIBZ
1710         if(wdh->compressed) {
1711                 return gzwfile_close((GZWFILE_T)wdh->fh);
1712         } else
1713 #endif
1714         {
1715                 return fclose((FILE *)wdh->fh);
1716         }
1717 }
1718
1719 gint64 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
1720 {
1721 #ifdef HAVE_LIBZ
1722         if(wdh->compressed) {
1723                 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1724                 return -1;
1725         } else
1726 #endif
1727         {
1728                 if (-1 == fseek((FILE *)wdh->fh, (long)offset, whence)) {
1729                         *err = errno;
1730                         return -1;
1731                 } else
1732                 {
1733                         return 0;
1734                 }       
1735         }
1736 }
1737 gint64 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
1738 {
1739         gint64 rval;
1740 #ifdef HAVE_LIBZ
1741         if(wdh->compressed) {
1742                 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
1743                 return -1;
1744         } else
1745 #endif
1746         {
1747                 if (-1 == (rval = ftell((FILE *)wdh->fh))) {
1748                         *err = errno;
1749                         return -1;
1750                 } else
1751                 {
1752                         return rval;
1753                 }       
1754         }
1755 }