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