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