434ec1249059bdf4b2bfb763ed7c8ec0dc983536
[metze/wireshark/wip.git] / wiretap / file_access.c
1 /* file_access.c
2  *
3  * Wiretap Library
4  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include "config.h"
22
23 #include <string.h>
24 #include <stdlib.h>
25
26 #include <errno.h>
27
28 #include <wsutil/file_util.h>
29 #include <wsutil/tempfile.h>
30
31 #include "wtap-int.h"
32 #include "file_wrappers.h"
33 #include <wsutil/buffer.h>
34 #include "lanalyzer.h"
35 #include "ngsniffer.h"
36 #include "radcom.h"
37 #include "ascendtext.h"
38 #include "nettl.h"
39 #include "libpcap.h"
40 #include "snoop.h"
41 #include "iptrace.h"
42 #include "iseries.h"
43 #include "netmon.h"
44 #include "netxray.h"
45 #include "toshiba.h"
46 #include "eyesdn.h"
47 #include "i4btrace.h"
48 #include "csids.h"
49 #include "pppdump.h"
50 #include "peekclassic.h"
51 #include "peektagged.h"
52 #include "vms.h"
53 #include "dbs-etherwatch.h"
54 #include "visual.h"
55 #include "cosine.h"
56 #include "5views.h"
57 #include "erf.h"
58 #include "hcidump.h"
59 #include "logcat.h"
60 #include "logcat_text.h"
61 #include "json.h"
62 #include "network_instruments.h"
63 #include "k12.h"
64 #include "ber.h"
65 #include "catapult_dct2000.h"
66 #include "mp2t.h"
67 #include "mpeg.h"
68 #include "netscreen.h"
69 #include "commview.h"
70 #include "pcapng.h"
71 #include "aethra.h"
72 #include "btsnoop.h"
73 #include "tnef.h"
74 #include "dct3trace.h"
75 #include "packetlogger.h"
76 #include "daintree-sna.h"
77 #include "netscaler.h"
78 #include "mime_file.h"
79 #include "ipfix.h"
80 #include "vwr.h"
81 #include "camins.h"
82 #include "stanag4607.h"
83 #include "capsa.h"
84 #include "pcap-encap.h"
85 #include "nettrace_3gpp_32_423.h"
86 #include "mplog.h"
87
88 /*
89  * Add an extension, and all compressed versions thereof, to a GSList
90  * of extensions.
91  */
92 static GSList *
93 add_extensions(GSList *extensions, const gchar *extension,
94     const char **compressed_file_extensions)
95 {
96         const char **compressed_file_extensionp;
97
98         /*
99          * Add the specified extension.
100          */
101         extensions = g_slist_append(extensions, g_strdup(extension));
102
103         /*
104          * Now add the extensions for compressed-file versions of
105          * that extension.
106          */
107         for (compressed_file_extensionp = compressed_file_extensions;
108             *compressed_file_extensionp != NULL;
109             compressed_file_extensionp++) {
110                 extensions = g_slist_append(extensions,
111                     g_strdup_printf("%s.%s", extension,
112                       *compressed_file_extensionp));
113         }
114
115         return extensions;
116 }
117
118 /*
119  * File types that can be identified by file extensions.
120  *
121  * These are used in file open dialogs to offer choices of extensions
122  * for which to filter.  Note that the first field can list more than
123  * one type of file, because, for example, ".cap" is a popular
124  * extension used by a number of capture file types.
125  */
126 static const struct file_extension_info file_type_extensions_base[] = {
127         { "Wireshark/tcpdump/... - pcap", TRUE, "pcap;cap;dmp" },
128         { "Wireshark/... - pcapng", TRUE, "pcapng;ntar" },
129         { "Network Monitor, Surveyor, NetScaler", TRUE, "cap" },
130         { "InfoVista 5View capture", TRUE, "5vw" },
131         { "Sniffer (DOS)", TRUE, "cap;enc;trc;fdc;syc" },
132         { "Cinco NetXRay, Sniffer (Windows)", TRUE, "cap;caz" },
133         { "Endace ERF capture", TRUE, "erf" },
134         { "EyeSDN USB S0/E1 ISDN trace format", TRUE, "trc" },
135         { "HP-UX nettl trace", TRUE, "trc0;trc1" },
136         { "Network Instruments Observer", TRUE, "bfr" },
137         { "Colasoft Capsa", TRUE, "cscpkt" },
138         { "Novell LANalyzer", TRUE, "tr1" },
139         { "Tektronix K12xx 32-bit .rf5 format", TRUE, "rf5" },
140         { "Savvius *Peek", TRUE, "pkt;tpc;apc;wpz" },
141         { "Catapult DCT2000 trace (.out format)", TRUE, "out" },
142         { "Micropross mplog", TRUE, "mplog" },
143         { "TamoSoft CommView", TRUE, "ncf" },
144         { "Symbian OS btsnoop", TRUE, "log" },
145         { "XML files (including Gammu DCT3 traces)", TRUE, "xml" },
146         { "OS X PacketLogger", TRUE, "pklg" },
147         { "Daintree SNA", TRUE, "dcf" },
148         { "IPFIX File Format", TRUE, "pfx;ipfix" },
149         { "Aethra .aps file", TRUE, "aps" },
150         { "MPEG2 transport stream", TRUE, "mp2t;ts;mpg" },
151         { "Ixia IxVeriWave .vwr Raw 802.11 Capture", TRUE, "vwr" },
152         { "CAM Inspector file", TRUE, "camins" },
153         { "MPEG files", FALSE, "mpg;mp3" },
154         { "Transport-Neutral Encapsulation Format", FALSE, "tnef" },
155         { "JPEG/JFIF files", FALSE, "jpg;jpeg;jfif" },
156         { "JavaScript Object Notation file", FALSE, "json" }
157 };
158
159 #define N_FILE_TYPE_EXTENSIONS  (sizeof file_type_extensions_base / sizeof file_type_extensions_base[0])
160
161 static const struct file_extension_info* file_type_extensions = NULL;
162
163 static GArray* file_type_extensions_arr = NULL;
164
165 /* initialize the extensions array if it has not been initialized yet */
166 static void
167 init_file_type_extensions(void)
168 {
169
170         if (file_type_extensions_arr) return;
171
172         file_type_extensions_arr = g_array_new(FALSE,TRUE,sizeof(struct file_extension_info));
173
174         g_array_append_vals(file_type_extensions_arr,file_type_extensions_base,N_FILE_TYPE_EXTENSIONS);
175
176         file_type_extensions = (struct file_extension_info*)(void *)file_type_extensions_arr->data;
177 }
178
179 void
180 wtap_register_file_type_extension(const struct file_extension_info *ei)
181 {
182         init_file_type_extensions();
183
184         g_array_append_val(file_type_extensions_arr,*ei);
185
186         file_type_extensions = (const struct file_extension_info*)(void *)file_type_extensions_arr->data;
187 }
188
189 int
190 wtap_get_num_file_type_extensions(void)
191 {
192         return file_type_extensions_arr->len;
193 }
194
195 const char *
196 wtap_get_file_extension_type_name(int extension_type)
197 {
198         return file_type_extensions[extension_type].name;
199 }
200
201 static GSList *
202 add_extensions_for_file_extensions_type(int extension_type,
203     GSList *extensions, const char **compressed_file_extensions)
204 {
205         gchar **extensions_set, **extensionp, *extension;
206
207         /*
208          * Split the extension-list string into a set of extensions.
209          */
210         extensions_set = g_strsplit(file_type_extensions[extension_type].extensions,
211             ";", 0);
212
213         /*
214          * Add each of those extensions to the list.
215          */
216         for (extensionp = extensions_set; *extensionp != NULL; extensionp++) {
217                 extension = *extensionp;
218
219                 /*
220                  * Add the extension, and all compressed variants
221                  * of it.
222                  */
223                 extensions = add_extensions(extensions, extension,
224                     compressed_file_extensions);
225         }
226
227         g_strfreev(extensions_set);
228         return extensions;
229 }
230
231 /* Return a list of file extensions that are used by the specified file
232    extension type.
233
234    All strings in the list are allocated with g_malloc() and must be freed
235    with g_free(). */
236 GSList *
237 wtap_get_file_extension_type_extensions(guint extension_type)
238 {
239         GSList *extensions;
240
241         if (extension_type >= file_type_extensions_arr->len)
242                 return NULL;    /* not a valid extension type */
243
244         extensions = NULL;      /* empty list, to start with */
245
246         /*
247          * Add all this file extension type's extensions, with compressed
248          * variants.
249          */
250         extensions = add_extensions_for_file_extensions_type(extension_type,
251             extensions, compressed_file_extension_table);
252
253         return extensions;
254 }
255
256 /* Return a list of all extensions that are used by all capture file
257    types, including compressed extensions, e.g. not just "pcap" but
258    also "pcap.gz" if we can read gzipped files.
259
260    "Capture files" means "include file types that correspond to
261    collections of network packets, but not file types that
262    store data that just happens to be transported over protocols
263    such as HTTP but that aren't collections of network packets",
264    so that it could be used for "All Capture Files" without picking
265    up JPEG files or files such as that - those aren't capture files,
266    and we *do* have them listed in the long list of individual file
267    types, so omitting them from "All Capture Files" is the right
268    thing to do.
269
270    All strings in the list are allocated with g_malloc() and must be freed
271    with g_free(). */
272 GSList *
273 wtap_get_all_capture_file_extensions_list(void)
274 {
275         GSList *extensions;
276         unsigned int i;
277
278         init_file_type_extensions();
279
280         extensions = NULL;      /* empty list, to start with */
281
282         for (i = 0; i < file_type_extensions_arr->len; i++) {
283                 /*
284                  * Is this a capture file, rather than one of the
285                  * other random file types we can read?
286                  */
287                 if (file_type_extensions[i].is_capture_file) {
288                         /*
289                          * Yes.  Add all this file extension type's
290                          * extensions, with compressed variants.
291                          */
292                         extensions = add_extensions_for_file_extensions_type(i,
293                             extensions, compressed_file_extension_table);
294                 }
295         }
296
297         return extensions;
298 }
299
300 /*
301  * The open_file_* routines should return:
302  *
303  *      -1 on an I/O error;
304  *
305  *      1 if the file they're reading is one of the types it handles;
306  *
307  *      0 if the file they're reading isn't the type they're checking for.
308  *
309  * If the routine handles this type of file, it should set the "file_type"
310  * field in the "struct wtap" to the type of the file.
311  *
312  * Note that the routine does not have to free the private data pointer on
313  * error. The caller takes care of that by calling wtap_close on error.
314  * (See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8518)
315  *
316  * However, the caller does have to free the private data pointer when
317  * returning 0, since the next file type will be called and will likely
318  * just overwrite the pointer.
319  *
320  * The names are used in file open dialogs to select, for files that
321  * don't have magic numbers and that could potentially be files of
322  * more than one type based on the heuristics, a particular file
323  * type to interpret it as, if the file name has no extension, the
324  * extension isn't sufficient to determine the appropriate file type,
325  * or the extension is wrong.
326  *
327  * NOTE: when adding file formats to this list you may also want to add them
328  * to the following files so that the various desktop environments will
329  * know that Wireshark can open the file:
330  *      1) wireshark-mime-package.xml (for freedesktop.org environments)
331  *      2) packaging/macosx/Info.plist.in (for OS X)
332  *      3) packaging/nsis/AdditionalTasksPage.ini, packaging/nsis/common.nsh,
333  *         and packaging/wix/ComponentGroups.wxi (for Windows)
334  *
335  * If your file format has an expected extension (e.g., ".pcap") then you
336  * should probably also add it to file_type_extensions_base[] (in this file).
337  */
338 static struct open_info open_info_base[] = {
339         { "Wireshark/tcpdump/... - pcap",           OPEN_INFO_MAGIC,     libpcap_open,             "pcap",     NULL, NULL },
340         { "Wireshark/... - pcapng",                 OPEN_INFO_MAGIC,     pcapng_open,              "pcapng",   NULL, NULL },
341         { "Sniffer (DOS)",                          OPEN_INFO_MAGIC,     ngsniffer_open,           NULL,       NULL, NULL },
342         { "Snoop, Shomiti/Finisar Surveyor",        OPEN_INFO_MAGIC,     snoop_open,               NULL,       NULL, NULL },
343         { "AIX iptrace",                            OPEN_INFO_MAGIC,     iptrace_open,             NULL,       NULL, NULL },
344         { "Microsoft Network Monitor",              OPEN_INFO_MAGIC,     netmon_open,              NULL,       NULL, NULL },
345         { "Cinco NetXray/Sniffer (Windows)",        OPEN_INFO_MAGIC,     netxray_open,             NULL,       NULL, NULL },
346         { "RADCOM WAN/LAN analyzer",                OPEN_INFO_MAGIC,     radcom_open,              NULL,       NULL, NULL },
347         { "HP-UX nettl trace",                      OPEN_INFO_MAGIC,     nettl_open,               NULL,       NULL, NULL },
348         { "Visual Networks traffic capture",        OPEN_INFO_MAGIC,     visual_open,              NULL,       NULL, NULL },
349         { "InfoVista 5View capture",                OPEN_INFO_MAGIC,     _5views_open,             NULL,       NULL, NULL },
350         { "Network Instruments Observer",           OPEN_INFO_MAGIC,     network_instruments_open, NULL,       NULL, NULL },
351         { "Savvius tagged",                         OPEN_INFO_MAGIC,     peektagged_open,          NULL,       NULL, NULL },
352         { "Colasoft Capsa",                         OPEN_INFO_MAGIC,     capsa_open,               NULL,       NULL, NULL },
353         { "DBS Etherwatch (VMS)",                   OPEN_INFO_MAGIC,     dbs_etherwatch_open,      NULL,       NULL, NULL },
354         { "Tektronix K12xx 32-bit .rf5 format",     OPEN_INFO_MAGIC,     k12_open,                 NULL,       NULL, NULL },
355         { "Catapult DCT2000 trace (.out format)",   OPEN_INFO_MAGIC,     catapult_dct2000_open,    NULL,       NULL, NULL },
356         { "Aethra .aps file",                       OPEN_INFO_MAGIC,     aethra_open,              NULL,       NULL, NULL },
357         { "Symbian OS btsnoop",                     OPEN_INFO_MAGIC,     btsnoop_open,             "log",      NULL, NULL },
358         { "EyeSDN USB S0/E1 ISDN trace format",     OPEN_INFO_MAGIC,     eyesdn_open,              NULL,       NULL, NULL },
359         { "Transport-Neutral Encapsulation Format", OPEN_INFO_MAGIC,     tnef_open,                NULL,       NULL, NULL },
360         /* 3GPP TS 32.423 Trace must come before MIME Files as it's XML based*/
361         { "3GPP TS 32.423 Trace format",            OPEN_INFO_MAGIC,     nettrace_3gpp_32_423_file_open, NULL, NULL, NULL },
362         /* Gammu DCT3 trace must come before MIME files as it's XML based*/
363         { "Gammu DCT3 trace",                       OPEN_INFO_MAGIC,     dct3trace_open,           NULL,       NULL, NULL },
364         { "MIME Files Format",                      OPEN_INFO_MAGIC,     mime_file_open,           NULL,       NULL, NULL },
365         { "Micropross mplog",                       OPEN_INFO_MAGIC,     mplog_open,               "mplog",    NULL, NULL },
366         { "Novell LANalyzer",                       OPEN_INFO_HEURISTIC, lanalyzer_open,           "tr1",      NULL, NULL },
367         /*
368          * PacketLogger must come before MPEG, because its files
369          * are sometimes grabbed by mpeg_open.
370          */
371         { "OS X PacketLogger",                      OPEN_INFO_HEURISTIC, packetlogger_open,        "pklg",     NULL, NULL },
372         /* Some MPEG files have magic numbers, others just have heuristics. */
373         { "MPEG",                                   OPEN_INFO_HEURISTIC, mpeg_open,                "mpg;mp3",  NULL, NULL },
374         { "Daintree SNA",                           OPEN_INFO_HEURISTIC, daintree_sna_open,        "dcf",      NULL, NULL },
375         { "STANAG 4607 Format",                     OPEN_INFO_HEURISTIC, stanag4607_open,          NULL,       NULL, NULL },
376         { "ASN.1 Basic Encoding Rules",             OPEN_INFO_HEURISTIC, ber_open,                 NULL,       NULL, NULL },
377         /*
378          * I put NetScreen *before* erf, because there were some
379          * false positives with my test-files (Sake Blok, July 2007)
380          *
381          * I put VWR *after* ERF, because there were some cases where
382          * ERF files were misidentified as vwr files (Stephen
383          * Donnelly, August 2013; see bug 9054)
384          *
385          * I put VWR *after* Peek Classic, CommView, iSeries text,
386          * Toshiba text, K12 text, VMS tcpiptrace text, and NetScaler,
387          * because there were some cases where files of those types were
388          * misidentified as vwr files (Guy Harris, December 2013)
389          */
390         { "NetScreen snoop text file",              OPEN_INFO_HEURISTIC, netscreen_open,           "txt",      NULL, NULL },
391         { "Endace ERF capture",                     OPEN_INFO_HEURISTIC, erf_open,                 "erf",      NULL, NULL },
392         { "IPFIX File Format",                      OPEN_INFO_HEURISTIC, ipfix_open,               "pfx;ipfix",NULL, NULL },
393         { "K12 text file",                          OPEN_INFO_HEURISTIC, k12text_open,             "txt",      NULL, NULL },
394         { "Savvius classic",                        OPEN_INFO_HEURISTIC, peekclassic_open,         "pkt;tpc;apc;wpz", NULL, NULL },
395         { "pppd log (pppdump format)",              OPEN_INFO_HEURISTIC, pppdump_open,             NULL,       NULL, NULL },
396         { "IBM iSeries comm. trace",                OPEN_INFO_HEURISTIC, iseries_open,             "txt",      NULL, NULL },
397         { "I4B ISDN trace",                         OPEN_INFO_HEURISTIC, i4btrace_open,            NULL,       NULL, NULL },
398         { "MPEG2 transport stream",                 OPEN_INFO_HEURISTIC, mp2t_open,                "ts;mpg",   NULL, NULL },
399         { "CSIDS IPLog",                            OPEN_INFO_HEURISTIC, csids_open,               NULL,       NULL, NULL },
400         { "TCPIPtrace (VMS)",                       OPEN_INFO_HEURISTIC, vms_open,                 "txt",      NULL, NULL },
401         { "CoSine IPSX L2 capture",                 OPEN_INFO_HEURISTIC, cosine_open,              "txt",      NULL, NULL },
402         { "Bluetooth HCI dump",                     OPEN_INFO_HEURISTIC, hcidump_open,             NULL,       NULL, NULL },
403         { "TamoSoft CommView",                      OPEN_INFO_HEURISTIC, commview_open,            "ncf",      NULL, NULL },
404         { "NetScaler",                              OPEN_INFO_HEURISTIC, nstrace_open,             "cap",      NULL, NULL },
405         { "Android Logcat Binary format",           OPEN_INFO_HEURISTIC, logcat_open,              "logcat",   NULL, NULL },
406         { "Android Logcat Text formats",            OPEN_INFO_HEURISTIC, logcat_text_open,         "txt",      NULL, NULL },
407         /* ASCII trace files from Telnet sessions. */
408         { "Lucent/Ascend access server trace",      OPEN_INFO_HEURISTIC, ascend_open,              "txt",      NULL, NULL },
409         { "Toshiba Compact ISDN Router snoop",      OPEN_INFO_HEURISTIC, toshiba_open,             "txt",      NULL, NULL },
410         /* Extremely weak heuristics - put them at the end. */
411         { "Ixia IxVeriWave .vwr Raw Capture",       OPEN_INFO_HEURISTIC, vwr_open,                 "vwr",      NULL, NULL },
412         { "CAM Inspector file",                     OPEN_INFO_HEURISTIC, camins_open,              "camins",   NULL, NULL },
413         { "JavaScript Object Notation",             OPEN_INFO_HEURISTIC, json_open,                "json",     NULL, NULL }
414 };
415
416 /* this is only used to build the dynamic array on load, do NOT use this
417  * for anything else, because the size of the actual array will change if
418  * Lua scripts register a new file reader.
419  */
420 #define N_OPEN_INFO_ROUTINES  ((sizeof open_info_base / sizeof open_info_base[0]))
421
422 static GArray *open_info_arr = NULL;
423
424 /* this always points to the top of the created array */
425 struct open_info *open_routines = NULL;
426
427 /* this points to the first OPEN_INFO_HEURISTIC type in the array */
428 static guint heuristic_open_routine_idx = 0;
429
430 static void
431 set_heuristic_routine(void)
432 {
433         guint i;
434         g_assert(open_info_arr != NULL);
435
436         for (i = 0; i < open_info_arr->len; i++) {
437                 if (open_routines[i].type == OPEN_INFO_HEURISTIC) {
438                         heuristic_open_routine_idx = i;
439                         break;
440                 }
441                 /* sanity check */
442                 g_assert(open_routines[i].type == OPEN_INFO_MAGIC);
443         }
444
445         g_assert(heuristic_open_routine_idx > 0);
446 }
447
448 void
449 init_open_routines(void)
450 {
451         unsigned int i;
452         struct open_info *i_open;
453
454         if (open_info_arr)
455                 return;
456
457         open_info_arr = g_array_new(TRUE,TRUE,sizeof(struct open_info));
458
459         g_array_append_vals(open_info_arr, open_info_base, N_OPEN_INFO_ROUTINES);
460
461         open_routines = (struct open_info *)(void*) open_info_arr->data;
462
463         /* Populate the extensions_set list now */
464         for (i = 0, i_open = open_routines; i < open_info_arr->len; i++, i_open++) {
465                 if (i_open->extensions != NULL)
466                         i_open->extensions_set = g_strsplit(i_open->extensions, ";", 0);
467         }
468
469         set_heuristic_routine();
470 }
471
472 /*
473  * Registers a new file reader - currently only called by wslua code for Lua readers.
474  * If first_routine is true, it's added before other readers of its type (magic or heuristic).
475  * Also, it checks for an existing reader of the same name and errors if it finds one; if
476  * you want to handle that condition more gracefully, call wtap_has_open_info() first.
477  */
478 void
479 wtap_register_open_info(struct open_info *oi, const gboolean first_routine)
480 {
481         init_open_routines();
482
483         if (!oi || !oi->name) {
484                 g_error("No open_info name given to register");
485                 return;
486         }
487
488         /* verify name doesn't already exist */
489         if (wtap_has_open_info(oi->name)) {
490                 g_error("Name given to register_open_info already exists");
491                 return;
492         }
493
494         if (oi->extensions != NULL)
495                 oi->extensions_set = g_strsplit(oi->extensions, ";", 0);
496
497         /* if it's magic and first, prepend it; if it's heuristic and not first,
498            append it; if it's anything else, stick it in the middle */
499         if (first_routine && oi->type == OPEN_INFO_MAGIC) {
500                 g_array_prepend_val(open_info_arr, *oi);
501         } else if (!first_routine && oi->type == OPEN_INFO_HEURISTIC) {
502                 g_array_append_val(open_info_arr, *oi);
503         } else {
504                 g_array_insert_val(open_info_arr, heuristic_open_routine_idx, *oi);
505         }
506
507         open_routines = (struct open_info *)(void*) open_info_arr->data;
508         set_heuristic_routine();
509 }
510
511 /* De-registers a file reader by removign it from the GArray based on its name.
512  * This function must NOT be called during wtap_open_offline(), since it changes the array.
513  * Note: this function will error if it doesn't find the given name; if you want to handle
514  * that condition more gracefully, call wtap_has_open_info() first.
515  */
516 void
517 wtap_deregister_open_info(const gchar *name)
518 {
519         guint i;
520         init_open_routines();
521
522         if (!name) {
523                 g_error("Missing open_info name to de-register");
524                 return;
525         }
526
527         for (i = 0; i < open_info_arr->len; i++) {
528                 if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) {
529                         if (open_routines[i].extensions_set != NULL)
530                                 g_strfreev(open_routines[i].extensions_set);
531                         open_info_arr = g_array_remove_index(open_info_arr, i);
532                         set_heuristic_routine();
533                         return;
534                 }
535         }
536
537         g_error("deregister_open_info: name not found");
538 }
539
540 /* Determines if a open routine short name already exists
541  */
542 gboolean
543 wtap_has_open_info(const gchar *name)
544 {
545         guint i;
546         init_open_routines();
547
548         if (!name) {
549                 g_error("No name given to wtap_has_open_info!");
550                 return FALSE;
551         }
552
553
554         for (i = 0; i < open_info_arr->len; i++) {
555                 if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) {
556                         return TRUE;
557                 }
558         }
559
560         return FALSE;
561 }
562
563 /*
564  * Visual C++ on Win32 systems doesn't define these.  (Old UNIX systems don't
565  * define them either.)
566  *
567  * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
568  */
569 #ifndef S_ISREG
570 #define S_ISREG(mode)   (((mode) & S_IFMT) == S_IFREG)
571 #endif
572 #ifndef S_IFIFO
573 #define S_IFIFO _S_IFIFO
574 #endif
575 #ifndef S_ISFIFO
576 #define S_ISFIFO(mode)  (((mode) & S_IFMT) == S_IFIFO)
577 #endif
578 #ifndef S_ISDIR
579 #define S_ISDIR(mode)   (((mode) & S_IFMT) == S_IFDIR)
580 #endif
581
582 /* returns the 'type' number to use for wtap_open_offline based on the
583    passed-in name (the name in the open_info struct). It returns WTAP_TYPE_AUTO
584    on failure, which is the number 0. The 'type' number is the entry's index+1,
585    because that's what wtap_open_offline() expects it to be. */
586 unsigned int
587 open_info_name_to_type(const char *name)
588 {
589         unsigned int i;
590         init_open_routines();
591
592         if (!name)
593                 return WTAP_TYPE_AUTO;
594
595         for (i = 0; i < open_info_arr->len; i++) {
596                 if (open_routines[i].name != NULL &&
597                     strcmp(name, open_routines[i].name) == 0)
598                         return i+1;
599         }
600
601         return WTAP_TYPE_AUTO; /* no such file type */
602 }
603
604 static char *
605 get_file_extension(const char *pathname)
606 {
607         gchar *filename;
608         gchar **components;
609         size_t ncomponents;
610         const char **compressed_file_extensionp;
611         gchar *extensionp;
612
613         /*
614          * Is the pathname empty?
615          */
616         if (strcmp(pathname, "") == 0)
617                 return NULL;    /* no extension */
618
619         /*
620          * Find the last component of the pathname.
621          */
622         filename = g_path_get_basename(pathname);
623
624         /*
625          * Does it have an extension?
626          */
627         if (strchr(filename, '.') == NULL) {
628                 g_free(filename);
629                 return NULL;    /* no extension whatsoever */
630         }
631
632         /*
633          * Yes.  Split it into components separated by ".".
634          */
635         components = g_strsplit(filename, ".", 0);
636         g_free(filename);
637
638         /*
639          * Count the components.
640          */
641         for (ncomponents = 0; components[ncomponents] != NULL; ncomponents++)
642                 ;
643
644         if (ncomponents == 0) {
645                 g_strfreev(components);
646                 return NULL;    /* no components */
647         }
648         if (ncomponents == 1) {
649                 g_strfreev(components);
650                 return NULL;    /* only one component, with no "." */
651         }
652
653         /*
654          * Is the last component one of the extensions used for compressed
655          * files?
656          */
657         extensionp = components[ncomponents - 1];
658         for (compressed_file_extensionp = compressed_file_extension_table;
659             *compressed_file_extensionp != NULL;
660             compressed_file_extensionp++) {
661                 if (strcmp(extensionp, *compressed_file_extensionp) == 0) {
662                         /*
663                          * Yes, it's one of the compressed-file extensions.
664                          * Is there an extension before that?
665                          */
666                         if (ncomponents == 2) {
667                                 g_strfreev(components);
668                                 return NULL;    /* no, only two components */
669                         }
670
671                         /*
672                          * Yes, return that extension.
673                          */
674                         extensionp = g_strdup(components[ncomponents - 2]);
675                         g_strfreev(components);
676                         return extensionp;
677                 }
678         }
679
680         /*
681          * The extension isn't one of the compressed-file extensions;
682          * return it.
683          */
684         extensionp = g_strdup(extensionp);
685         g_strfreev(components);
686         return extensionp;
687 }
688
689 /*
690  * Check if file extension is used in this heuristic
691  */
692 static gboolean
693 heuristic_uses_extension(unsigned int i, const char *extension)
694 {
695         gchar **extensionp;
696
697         /*
698          * Does this file type *have* any extensions?
699          */
700         if (open_routines[i].extensions == NULL)
701                 return FALSE;   /* no */
702
703         /*
704          * Check each of them against the specified extension.
705          */
706         for (extensionp = open_routines[i].extensions_set; *extensionp != NULL;
707             extensionp++) {
708                 if (strcmp(extension, *extensionp) == 0) {
709                         return TRUE;    /* it's one of them */
710                 }
711         }
712
713         return FALSE;   /* it's not one of them */
714 }
715
716 /* Opens a file and prepares a wtap struct.
717    If "do_random" is TRUE, it opens the file twice; the second open
718    allows the application to do random-access I/O without moving
719    the seek offset for sequential I/O, which is used by Wireshark
720    so that it can do sequential I/O to a capture file that's being
721    written to as new packets arrive independently of random I/O done
722    to display protocol trees for packets when they're selected. */
723 wtap *
724 wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_info,
725                   gboolean do_random)
726 {
727         int     fd;
728         ws_statb64 statb;
729         wtap    *wth;
730         unsigned int    i;
731         gboolean use_stdin = FALSE;
732         gchar *extension;
733         wtap_block_t shb;
734
735         *err = 0;
736         *err_info = NULL;
737
738         init_open_routines();
739
740         /* open standard input if filename is '-' */
741         if (strcmp(filename, "-") == 0)
742                 use_stdin = TRUE;
743
744         /* First, make sure the file is valid */
745         if (use_stdin) {
746                 if (ws_fstat64(0, &statb) < 0) {
747                         *err = errno;
748                         return NULL;
749                 }
750         } else {
751                 if (ws_stat64(filename, &statb) < 0) {
752                         *err = errno;
753                         return NULL;
754                 }
755         }
756         if (S_ISFIFO(statb.st_mode)) {
757                 /*
758                  * Opens of FIFOs are allowed only when not opening
759                  * for random access.
760                  *
761                  * Currently, we do seeking when trying to find out
762                  * the file type, but our I/O routines do some amount
763                  * of buffering, and do backward seeks within the buffer
764                  * if possible, so at least some file types can be
765                  * opened from pipes, so we don't completely disallow opens
766                  * of pipes.
767                  */
768                 if (do_random) {
769                         *err = WTAP_ERR_RANDOM_OPEN_PIPE;
770                         return NULL;
771                 }
772         } else if (S_ISDIR(statb.st_mode)) {
773                 /*
774                  * Return different errors for "this is a directory"
775                  * and "this is some random special file type", so
776                  * the user can get a potentially more helpful error.
777                  */
778                 *err = EISDIR;
779                 return NULL;
780         } else if (! S_ISREG(statb.st_mode)) {
781                 *err = WTAP_ERR_NOT_REGULAR_FILE;
782                 return NULL;
783         }
784
785         /*
786          * We need two independent descriptors for random access, so
787          * they have different file positions.  If we're opening the
788          * standard input, we can only dup it to get additional
789          * descriptors, so we can't have two independent descriptors,
790          * and thus can't do random access.
791          */
792         if (use_stdin && do_random) {
793                 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
794                 return NULL;
795         }
796
797         errno = ENOMEM;
798         wth = (wtap *)g_malloc0(sizeof(wtap));
799
800         /* Open the file */
801         errno = WTAP_ERR_CANT_OPEN;
802         if (use_stdin) {
803                 /*
804                  * We dup FD 0, so that we don't have to worry about
805                  * a file_close of wth->fh closing the standard
806                  * input of the process.
807                  */
808                 fd = ws_dup(0);
809                 if (fd < 0) {
810                         *err = errno;
811                         g_free(wth);
812                         return NULL;
813                 }
814 #ifdef _WIN32
815                 if (_setmode(fd, O_BINARY) == -1) {
816                         /* "Shouldn't happen" */
817                         *err = errno;
818                         g_free(wth);
819                         return NULL;
820                 }
821 #endif
822                 if (!(wth->fh = file_fdopen(fd))) {
823                         *err = errno;
824                         ws_close(fd);
825                         g_free(wth);
826                         return NULL;
827                 }
828         } else {
829                 if (!(wth->fh = file_open(filename))) {
830                         *err = errno;
831                         g_free(wth);
832                         return NULL;
833                 }
834         }
835
836         if (do_random) {
837                 if (!(wth->random_fh = file_open(filename))) {
838                         *err = errno;
839                         file_close(wth->fh);
840                         g_free(wth);
841                         return NULL;
842                 }
843         } else
844                 wth->random_fh = NULL;
845
846         /* initialization */
847         wth->file_encap = WTAP_ENCAP_UNKNOWN;
848         wth->subtype_sequential_close = NULL;
849         wth->subtype_close = NULL;
850         wth->file_tsprec = WTAP_TSPREC_USEC;
851         wth->priv = NULL;
852         wth->wslua_data = NULL;
853         wth->shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
854         shb = wtap_block_create(WTAP_BLOCK_NG_SECTION);
855         if (shb)
856                 g_array_append_val(wth->shb_hdrs, shb);
857
858         /* Initialize the array containing a list of interfaces. pcapng_open and
859          * erf_open needs this (and libpcap_open for ERF encapsulation types).
860          * Always initing it here saves checking for a NULL ptr later. */
861         wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
862
863         if (wth->random_fh) {
864                 wth->fast_seek = g_ptr_array_new();
865
866                 file_set_random_access(wth->fh, FALSE, wth->fast_seek);
867                 file_set_random_access(wth->random_fh, TRUE, wth->fast_seek);
868         }
869
870         /* 'type' is 1 greater than the array index */
871         if (type != WTAP_TYPE_AUTO && type <= open_info_arr->len) {
872                 int result;
873
874                 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
875                         /* I/O error - give up */
876                         wtap_close(wth);
877                         return NULL;
878                 }
879
880                 /* Set wth with wslua data if any - this is how we pass the data
881                  * to the file reader, kinda like the priv member but not free'd later.
882                  * It's ok for this to copy a NULL.
883                  */
884                 wth->wslua_data = open_routines[type - 1].wslua_data;
885
886                 result = (*open_routines[type - 1].open_routine)(wth, err, err_info);
887
888                 switch (result) {
889                         case WTAP_OPEN_ERROR:
890                                 /* Error - give up */
891                                 wtap_close(wth);
892                                 return NULL;
893
894                         case WTAP_OPEN_NOT_MINE:
895                                 /* No error, but not that type of file */
896                                 goto fail;
897
898                         case WTAP_OPEN_MINE:
899                                 /* We found the file type */
900                                 goto success;
901                 }
902         }
903
904         /* Try all file types that support magic numbers */
905         for (i = 0; i < heuristic_open_routine_idx; i++) {
906                 /* Seek back to the beginning of the file; the open routine
907                    for the previous file type may have left the file
908                    position somewhere other than the beginning, and the
909                    open routine for this file type will probably want
910                    to start reading at the beginning.
911
912                    Initialize the data offset while we're at it. */
913                 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
914                         /* Error - give up */
915                         wtap_close(wth);
916                         return NULL;
917                 }
918
919                 /* Set wth with wslua data if any - this is how we pass the data
920                  * to the file reader, kinda like the priv member but not free'd later.
921                  * It's ok for this to copy a NULL.
922                  */
923                 wth->wslua_data = open_routines[i].wslua_data;
924
925                 switch ((*open_routines[i].open_routine)(wth, err, err_info)) {
926
927                 case WTAP_OPEN_ERROR:
928                         /* Error - give up */
929                         wtap_close(wth);
930                         return NULL;
931
932                 case WTAP_OPEN_NOT_MINE:
933                         /* No error, but not that type of file */
934                         break;
935
936                 case WTAP_OPEN_MINE:
937                         /* We found the file type */
938                         goto success;
939                 }
940         }
941
942
943         /* Does this file's name have an extension? */
944         extension = get_file_extension(filename);
945         if (extension != NULL) {
946                 /* Yes - try the heuristic types that use that extension first. */
947                 for (i = heuristic_open_routine_idx; i < open_info_arr->len; i++) {
948                         /* Does this type use that extension? */
949                         if (heuristic_uses_extension(i, extension)) {
950                                 /* Yes. */
951                                 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
952                                         /* Error - give up */
953                                         g_free(extension);
954                                         wtap_close(wth);
955                                         return NULL;
956                                 }
957
958                                 /* Set wth with wslua data if any - this is how we pass the data
959                                  * to the file reader, kind of like priv but not free'd later.
960                                  */
961                                 wth->wslua_data = open_routines[i].wslua_data;
962
963                                 switch ((*open_routines[i].open_routine)(wth,
964                                     err, err_info)) {
965
966                                 case WTAP_OPEN_ERROR:
967                                         /* Error - give up */
968                                         g_free(extension);
969                                         wtap_close(wth);
970                                         return NULL;
971
972                                 case WTAP_OPEN_NOT_MINE:
973                                         /* No error, but not that type of file */
974                                         break;
975
976                                 case WTAP_OPEN_MINE:
977                                         /* We found the file type */
978                                         g_free(extension);
979                                         goto success;
980                                 }
981                         }
982                 }
983
984                 /*
985                  * Now try the heuristic types that have no extensions
986                  * to check; we try those before the ones that have
987                  * extensions that *don't* match this file's extension,
988                  * on the theory that files of those types generally
989                  * have one of the type's extensions, and, as this file
990                  * *doesn't* have one of those extensions, it's probably
991                  * *not* one of those files.
992                  */
993                 for (i = heuristic_open_routine_idx; i < open_info_arr->len; i++) {
994                         /* Does this type have any extensions? */
995                         if (open_routines[i].extensions == NULL) {
996                                 /* No. */
997                                 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
998                                         /* Error - give up */
999                                         g_free(extension);
1000                                         wtap_close(wth);
1001                                         return NULL;
1002                                 }
1003
1004                                 /* Set wth with wslua data if any - this is how we pass the data
1005                                  * to the file reader, kind of like priv but not free'd later.
1006                                  */
1007                                 wth->wslua_data = open_routines[i].wslua_data;
1008
1009                                 switch ((*open_routines[i].open_routine)(wth,
1010                                     err, err_info)) {
1011
1012                                 case WTAP_OPEN_ERROR:
1013                                         /* Error - give up */
1014                                         g_free(extension);
1015                                         wtap_close(wth);
1016                                         return NULL;
1017
1018                                 case WTAP_OPEN_NOT_MINE:
1019                                         /* No error, but not that type of file */
1020                                         break;
1021
1022                                 case WTAP_OPEN_MINE:
1023                                         /* We found the file type */
1024                                         g_free(extension);
1025                                         goto success;
1026                                 }
1027                         }
1028                 }
1029
1030                 /*
1031                  * Now try the ones that have extensions where none of
1032                  * them matches this file's extensions.
1033                  */
1034                 for (i = heuristic_open_routine_idx; i < open_info_arr->len; i++) {
1035                         /*
1036                          * Does this type have extensions and is this file's
1037                          * extension one of them?
1038                          */
1039                         if (open_routines[i].extensions != NULL &&
1040                             !heuristic_uses_extension(i, extension)) {
1041                                 /* Yes and no. */
1042                                 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
1043                                         /* Error - give up */
1044                                         g_free(extension);
1045                                         wtap_close(wth);
1046                                         return NULL;
1047                                 }
1048
1049                                 /* Set wth with wslua data if any - this is how we pass the data
1050                                  * to the file reader, kind of like priv but not free'd later.
1051                                  */
1052                                 wth->wslua_data = open_routines[i].wslua_data;
1053
1054                                 switch ((*open_routines[i].open_routine)(wth,
1055                                     err, err_info)) {
1056
1057                                 case WTAP_OPEN_ERROR:
1058                                         /* Error - give up */
1059                                         g_free(extension);
1060                                         wtap_close(wth);
1061                                         return NULL;
1062
1063                                 case WTAP_OPEN_NOT_MINE:
1064                                         /* No error, but not that type of file */
1065                                         break;
1066
1067                                 case WTAP_OPEN_MINE:
1068                                         /* We found the file type */
1069                                         g_free(extension);
1070                                         goto success;
1071                                 }
1072                         }
1073                 }
1074                 g_free(extension);
1075         } else {
1076                 /* No - try all the heuristics types in order. */
1077                 for (i = heuristic_open_routine_idx; i < open_info_arr->len; i++) {
1078
1079                         if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
1080                                 /* Error - give up */
1081                                 wtap_close(wth);
1082                                 return NULL;
1083                         }
1084
1085                         /* Set wth with wslua data if any - this is how we pass the data
1086                          * to the file reader, kind of like priv but not free'd later.
1087                          */
1088                         wth->wslua_data = open_routines[i].wslua_data;
1089
1090                         switch ((*open_routines[i].open_routine)(wth, err, err_info)) {
1091
1092                         case WTAP_OPEN_ERROR:
1093                                 /* Error - give up */
1094                                 wtap_close(wth);
1095                                 return NULL;
1096
1097                         case WTAP_OPEN_NOT_MINE:
1098                                 /* No error, but not that type of file */
1099                                 break;
1100
1101                         case WTAP_OPEN_MINE:
1102                                 /* We found the file type */
1103                                 goto success;
1104                         }
1105                 }
1106         }
1107
1108 fail:
1109
1110         /* Well, it's not one of the types of file we know about. */
1111         wtap_close(wth);
1112         *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
1113         return NULL;
1114
1115 success:
1116         wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
1117         ws_buffer_init(wth->frame_buffer, 1500);
1118
1119         if ((wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP) ||
1120                 (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC)) {
1121
1122                 wtap_block_t descr = wtap_block_create(WTAP_BLOCK_IF_DESCR);
1123                 wtapng_if_descr_mandatory_t* descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(descr);
1124
1125                 descr_mand->wtap_encap = wth->file_encap;
1126                 if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC) {
1127                         descr_mand->time_units_per_second = 1000000000; /* nanosecond resolution */
1128                         wtap_block_add_uint8_option(descr, OPT_IDB_TSRESOL, 9);
1129                         descr_mand->tsprecision = WTAP_TSPREC_NSEC;
1130                 } else {
1131                         descr_mand->time_units_per_second = 1000000; /* default microsecond resolution */
1132                         /* No need to add an option, this is the default */
1133                         descr_mand->tsprecision = WTAP_TSPREC_USEC;
1134                 }
1135                 descr_mand->link_type = wtap_wtap_encap_to_pcap_encap(wth->file_encap);
1136                 descr_mand->snap_len = wth->snapshot_length;
1137
1138                 descr_mand->num_stat_entries = 0;          /* Number of ISB:s */
1139                 descr_mand->interface_statistics = NULL;
1140                 g_array_append_val(wth->interface_data, descr);
1141
1142         }
1143         return wth;
1144 }
1145
1146 /*
1147  * Given the pathname of the file we just closed with wtap_fdclose(), attempt
1148  * to reopen that file and assign the new file descriptor(s) to the sequential
1149  * stream and, if do_random is TRUE, to the random stream.  Used on Windows
1150  * after the rename of a file we had open was done or if the rename of a
1151  * file on top of a file we had open failed.
1152  *
1153  * This is only required by Wireshark, not TShark, and, at the point that
1154  * Wireshark is doing this, the sequential stream is closed, and the
1155  * random stream is open, so this refuses to open pipes, and only
1156  * reopens the random stream.
1157  */
1158 gboolean
1159 wtap_fdreopen(wtap *wth, const char *filename, int *err)
1160 {
1161         ws_statb64 statb;
1162
1163         /*
1164          * We need two independent descriptors for random access, so
1165          * they have different file positions.  If we're opening the
1166          * standard input, we can only dup it to get additional
1167          * descriptors, so we can't have two independent descriptors,
1168          * and thus can't do random access.
1169          */
1170         if (strcmp(filename, "-") == 0) {
1171                 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
1172                 return FALSE;
1173         }
1174
1175         /* First, make sure the file is valid */
1176         if (ws_stat64(filename, &statb) < 0) {
1177                 *err = errno;
1178                 return FALSE;
1179         }
1180         if (S_ISFIFO(statb.st_mode)) {
1181                 /*
1182                  * Opens of FIFOs are not allowed; see above.
1183                  */
1184                 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
1185                 return FALSE;
1186         } else if (S_ISDIR(statb.st_mode)) {
1187                 /*
1188                  * Return different errors for "this is a directory"
1189                  * and "this is some random special file type", so
1190                  * the user can get a potentially more helpful error.
1191                  */
1192                 *err = EISDIR;
1193                 return FALSE;
1194         } else if (! S_ISREG(statb.st_mode)) {
1195                 *err = WTAP_ERR_NOT_REGULAR_FILE;
1196                 return FALSE;
1197         }
1198
1199         /* Open the file */
1200         errno = WTAP_ERR_CANT_OPEN;
1201         if (!file_fdreopen(wth->random_fh, filename)) {
1202                 *err = errno;
1203                 return FALSE;
1204         }
1205         return TRUE;
1206 }
1207
1208 /* Table of the file types and subtypes for which we have built-in support.
1209    Entries must be sorted by WTAP_FILE_TYPE_SUBTYPE_xxx values in ascending
1210    order.
1211
1212    These are used to report what type and subtype a given file is and
1213    to let the user select a format when writing out packets.
1214
1215    This table is what we start with, but it can be modified.
1216    If we need to modify it, we allocate a GArray, copy the entries
1217    in the above table to that GArray, use the copy as the table, and
1218    make all changes to the copy. */
1219 static const struct file_type_subtype_info dump_open_table_base[] = {
1220         /* WTAP_FILE_TYPE_SUBTYPE_UNKNOWN (only used internally for initialization) */
1221         { NULL, NULL, NULL, NULL,
1222           FALSE, FALSE, 0,
1223           NULL, NULL, NULL },
1224
1225         /* WTAP_FILE_TYPE_SUBTYPE_PCAP */
1226         /* Gianluca Varenni suggests that we add "deprecated" to the description. */
1227         { "Wireshark/tcpdump/... - pcap", "pcap", "pcap", "cap;dmp",
1228           FALSE, FALSE, 0,
1229           libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1230
1231         /* WTAP_FILE_TYPE_SUBTYPE_PCAPNG */
1232         { "Wireshark/... - pcapng", "pcapng", "pcapng", "ntar",
1233           FALSE, TRUE, WTAP_COMMENT_PER_SECTION|WTAP_COMMENT_PER_INTERFACE|WTAP_COMMENT_PER_PACKET,
1234           pcapng_dump_can_write_encap, pcapng_dump_open, NULL },
1235
1236         /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC */
1237         { "Wireshark - nanosecond libpcap", "nseclibpcap", "pcap", "cap;dmp",
1238           FALSE, FALSE, 0,
1239           libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1240
1241         /* WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX */
1242         { "AIX tcpdump - libpcap", "aixlibpcap", "pcap", "cap;dmp",
1243           FALSE, FALSE, 0,
1244           NULL, NULL, NULL },
1245
1246         /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029 */
1247         { "Modified tcpdump - libpcap", "modlibpcap", "pcap", "cap;dmp",
1248           FALSE, FALSE, 0,
1249           libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1250
1251         /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA */
1252         { "Nokia tcpdump - libpcap ", "nokialibpcap", "pcap", "cap;dmp",
1253           FALSE, FALSE, 0,
1254           libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1255
1256         /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417 */
1257         { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "pcap", "cap;dmp",
1258           FALSE, FALSE, 0,
1259           libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1260
1261         /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915 */
1262         { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "pcap", "cap;dmp",
1263           FALSE, FALSE, 0,
1264           libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1265
1266         /* WTAP_FILE_TYPE_SUBTYPE_5VIEWS */
1267         { "InfoVista 5View capture", "5views", "5vw", NULL,
1268            TRUE, FALSE, 0,
1269           _5views_dump_can_write_encap, _5views_dump_open, NULL },
1270
1271         /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_1_0 */
1272         { "AIX iptrace 1.0", "iptrace_1", NULL, NULL,
1273           FALSE, FALSE, 0,
1274           NULL, NULL, NULL },
1275
1276         /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_2_0 */
1277         { "AIX iptrace 2.0", "iptrace_2", NULL, NULL,
1278           FALSE, FALSE, 0,
1279           NULL, NULL, NULL },
1280
1281         /* WTAP_FILE_TYPE_SUBTYPE_BER */
1282         { "ASN.1 Basic Encoding Rules", "ber", NULL, NULL,
1283           FALSE, FALSE, 0,
1284           NULL, NULL, NULL },
1285
1286         /* WTAP_FILE_TYPE_SUBTYPE_HCIDUMP */
1287         { "Bluetooth HCI dump", "hcidump", NULL, NULL,
1288           FALSE, FALSE, 0,
1289           NULL, NULL, NULL },
1290
1291         /* WTAP_FILE_TYPE_SUBTYPE_CATAPULT_DCT2000 */
1292         { "Catapult DCT2000 trace (.out format)", "dct2000", "out", NULL,
1293           FALSE, FALSE, 0,
1294           catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open, NULL },
1295
1296         /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_OLD */
1297         { "Cinco Networks NetXRay 1.x", "netxray1", "cap", NULL,
1298           TRUE, FALSE, 0,
1299           NULL, NULL, NULL },
1300
1301         /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_0 */
1302         { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL,
1303           TRUE, FALSE, 0,
1304           NULL, NULL, NULL },
1305
1306         /* WTAP_FILE_TYPE_SUBTYPE_COSINE */
1307         { "CoSine IPSX L2 capture", "cosine", "txt", NULL,
1308           FALSE, FALSE, 0,
1309           NULL, NULL, NULL },
1310
1311         /* WTAP_FILE_TYPE_SUBTYPE_CSIDS */
1312         { "CSIDS IPLog", "csids", NULL, NULL,
1313           FALSE, FALSE, 0,
1314           NULL, NULL, NULL },
1315
1316         /* WTAP_FILE_TYPE_SUBTYPE_DBS_ETHERWATCH */
1317         { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL,
1318           FALSE, FALSE, 0,
1319           NULL, NULL, NULL },
1320
1321         /* WTAP_FILE_TYPE_SUBTYPE_ERF */
1322         { "Endace ERF capture", "erf", "erf", NULL,
1323           FALSE, FALSE, 0,
1324           erf_dump_can_write_encap, erf_dump_open, NULL },
1325
1326         /* WTAP_FILE_TYPE_SUBTYPE_EYESDN */
1327         { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "trc", NULL,
1328            FALSE, FALSE, 0,
1329            eyesdn_dump_can_write_encap, eyesdn_dump_open, NULL },
1330
1331         /* WTAP_FILE_TYPE_SUBTYPE_NETTL */
1332         { "HP-UX nettl trace", "nettl", "trc0", "trc1",
1333           FALSE, FALSE, 0,
1334           nettl_dump_can_write_encap, nettl_dump_open, NULL },
1335
1336         /* WTAP_FILE_TYPE_SUBTYPE_ISERIES */
1337         { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "txt", NULL,
1338           FALSE, FALSE, 0,
1339           NULL, NULL, NULL },
1340
1341         /* WTAP_FILE_TYPE_SUBTYPE_ISERIES_UNICODE */
1342         { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL,
1343           FALSE, FALSE, 0,
1344           NULL, NULL, NULL },
1345
1346         /* WTAP_FILE_TYPE_SUBTYPE_I4BTRACE */
1347         { "I4B ISDN trace", "i4btrace", NULL, NULL,
1348           FALSE, FALSE, 0,
1349           NULL, NULL, NULL },
1350
1351         /* WTAP_FILE_TYPE_SUBTYPE_ASCEND */
1352         { "Lucent/Ascend access server trace", "ascend", "txt", NULL,
1353           FALSE, FALSE, 0,
1354           NULL, NULL, NULL },
1355
1356         /* WTAP_FILE_TYPE_SUBTYPE_NETMON_1_x */
1357         { "Microsoft NetMon 1.x", "netmon1", "cap", NULL,
1358           TRUE, FALSE, 0,
1359           netmon_dump_can_write_encap_1_x, netmon_dump_open, NULL },
1360
1361         /* WTAP_FILE_TYPE_SUBTYPE_NETMON_2_x */
1362         { "Microsoft NetMon 2.x", "netmon2", "cap", NULL,
1363           TRUE, FALSE, 0,
1364           netmon_dump_can_write_encap_2_x, netmon_dump_open, NULL },
1365
1366         /* WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_UNCOMPRESSED */
1367         { "Sniffer (DOS)", "ngsniffer", "cap", "enc;trc;fdc;syc",
1368           FALSE, FALSE, 0,
1369           ngsniffer_dump_can_write_encap, ngsniffer_dump_open, NULL },
1370
1371         /* WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_COMPRESSED */
1372         { "Sniffer (DOS), compressed", "ngsniffer_comp", "cap", "enc;trc;fdc;syc",
1373           FALSE, FALSE, 0,
1374           NULL, NULL, NULL },
1375
1376         /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_1 */
1377         { "NetXray, Sniffer (Windows) 1.1", "ngwsniffer_1_1", "cap", NULL,
1378           TRUE, FALSE, 0,
1379           netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1, NULL },
1380
1381         /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_2_00x */
1382         { "Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "cap", "caz",
1383           TRUE, FALSE, 0,
1384           netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0, NULL },
1385
1386         /* WTAP_FILE_TYPE_SUBTYPE_NETWORK_INSTRUMENTS */
1387         { "Network Instruments Observer", "niobserver", "bfr", NULL,
1388           FALSE, FALSE, 0,
1389           network_instruments_dump_can_write_encap, network_instruments_dump_open, NULL },
1390
1391         /* WTAP_FILE_TYPE_SUBTYPE_LANALYZER */
1392         { "Novell LANalyzer","lanalyzer", "tr1", NULL,
1393           TRUE, FALSE, 0,
1394           lanalyzer_dump_can_write_encap, lanalyzer_dump_open, NULL },
1395
1396         /* WTAP_FILE_TYPE_SUBTYPE_PPPDUMP */
1397         { "pppd log (pppdump format)", "pppd", NULL, NULL,
1398           FALSE, FALSE, 0,
1399           NULL, NULL, NULL },
1400
1401         /* WTAP_FILE_TYPE_SUBTYPE_RADCOM */
1402         { "RADCOM WAN/LAN analyzer", "radcom", NULL, NULL,
1403           FALSE, FALSE, 0,
1404           NULL, NULL, NULL },
1405
1406         /* WTAP_FILE_TYPE_SUBTYPE_SNOOP */
1407         { "Sun snoop", "snoop", "snoop", "cap",
1408           FALSE, FALSE, 0,
1409           snoop_dump_can_write_encap, snoop_dump_open, NULL },
1410
1411         /* WTAP_FILE_TYPE_SUBTYPE_SHOMITI */
1412         { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL,
1413           FALSE, FALSE, 0,
1414           NULL, NULL, NULL },
1415
1416         /* WTAP_FILE_TYPE_SUBTYPE_VMS */
1417         { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL,
1418           FALSE, FALSE, 0,
1419           NULL, NULL, NULL },
1420
1421         /* WTAP_FILE_TYPE_SUBTYPE_K12 */
1422         { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL,
1423            TRUE, FALSE, 0,
1424            k12_dump_can_write_encap, k12_dump_open, NULL },
1425
1426         /* WTAP_FILE_TYPE_SUBTYPE_TOSHIBA */
1427         { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL,
1428           FALSE, FALSE, 0,
1429           NULL, NULL, NULL },
1430
1431         /* WTAP_FILE_TYPE_SUBTYPE_VISUAL_NETWORKS */
1432         { "Visual Networks traffic capture", "visual", NULL, NULL,
1433           TRUE, FALSE, 0,
1434           visual_dump_can_write_encap, visual_dump_open, NULL },
1435
1436         /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V56 */
1437         { "Savvius classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz",
1438           FALSE, FALSE, 0,
1439           NULL, NULL, NULL },
1440
1441         /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V7 */
1442         { "Savvius classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz",
1443           FALSE, FALSE, 0,
1444           NULL, NULL, NULL },
1445
1446         /* WTAP_FILE_TYPE_SUBTYPE_PEEKTAGGED */
1447         { "Savvius tagged", "peektagged", "pkt", "tpc;apc;wpz",
1448           FALSE, FALSE, 0,
1449           NULL, NULL, NULL },
1450
1451         /* WTAP_FILE_TYPE_SUBTYPE_MPEG */
1452         { "MPEG", "mpeg", "mpeg", "mpg;mp3",
1453           FALSE, FALSE, 0,
1454           NULL, NULL, NULL },
1455
1456         /* WTAP_FILE_TYPE_SUBTYPE_K12TEXT  */
1457         { "K12 text file", "k12text", "txt", NULL,
1458           FALSE, FALSE, 0,
1459           k12text_dump_can_write_encap, k12text_dump_open, NULL },
1460
1461         /* WTAP_FILE_TYPE_SUBTYPE_NETSCREEN */
1462         { "NetScreen snoop text file", "netscreen", "txt", NULL,
1463           FALSE, FALSE, 0,
1464           NULL, NULL, NULL },
1465
1466         /* WTAP_FILE_TYPE_SUBTYPE_COMMVIEW */
1467         { "TamoSoft CommView", "commview", "ncf", NULL,
1468           FALSE, FALSE, 0,
1469           commview_dump_can_write_encap, commview_dump_open, NULL },
1470
1471         /* WTAP_FILE_TYPE_SUBTYPE_BTSNOOP */
1472         { "Symbian OS btsnoop", "btsnoop", "log", NULL,
1473           FALSE, FALSE, 0,
1474           btsnoop_dump_can_write_encap, btsnoop_dump_open_h4, NULL },
1475
1476         /* WTAP_FILE_TYPE_SUBTYPE_TNEF */
1477         { "Transport-Neutral Encapsulation Format", "tnef", NULL, NULL,
1478           FALSE, FALSE, 0,
1479           NULL, NULL, NULL },
1480
1481         /* WTAP_FILE_TYPE_SUBTYPE_DCT3TRACE */
1482         { "Gammu DCT3 trace", "dct3trace", "xml", NULL,
1483           FALSE, FALSE, 0,
1484           NULL, NULL, NULL },
1485
1486         /* WTAP_FILE_TYPE_SUBTYPE_PACKETLOGGER */
1487         { "OS X PacketLogger", "pklg", "pklg", NULL,
1488           FALSE, FALSE, 0,
1489           NULL, NULL, NULL },
1490
1491         /* WTAP_FILE_TYPE_SUBTYPE_DAINTREE_SNA */
1492         { "Daintree SNA", "dsna", "dcf", NULL,
1493           FALSE, FALSE, 0,
1494           NULL, NULL, NULL },
1495
1496         /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0 */
1497         { "NetScaler Trace (Version 1.0)", "nstrace10", NULL, NULL,
1498           TRUE, FALSE, 0,
1499           nstrace_10_dump_can_write_encap, nstrace_dump_open, NULL },
1500
1501         /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0 */
1502         { "NetScaler Trace (Version 2.0)", "nstrace20", "cap", NULL,
1503           TRUE, FALSE, 0,
1504           nstrace_20_dump_can_write_encap, nstrace_dump_open, NULL },
1505
1506         /* WTAP_FILE_TYPE_SUBTYPE_JPEG_JFIF */
1507         { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif",
1508           FALSE, FALSE, 0,
1509           NULL, NULL, NULL },
1510
1511         /* WTAP_FILE_TYPE_SUBTYPE_IPFIX */
1512         { "IPFIX File Format", "ipfix", "pfx", "ipfix",
1513           FALSE, FALSE, 0,
1514           NULL, NULL, NULL },
1515
1516         /* WTAP_ENCAP_MIME */
1517         { "MIME File Format", "mime", NULL, NULL,
1518            FALSE, FALSE, 0,
1519            NULL, NULL, NULL },
1520
1521         /* WTAP_FILE_TYPE_SUBTYPE_AETHRA */
1522         { "Aethra .aps file", "aethra", "aps", NULL,
1523           FALSE, FALSE, 0,
1524           NULL, NULL, NULL },
1525
1526         /* WTAP_FILE_TYPE_SUBTYPE_MPEG_2_TS */
1527         { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg",
1528           FALSE, FALSE, 0,
1529           NULL, NULL, NULL },
1530
1531         /* WTAP_FILE_TYPE_SUBTYPE_VWR_80211 */
1532         { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL,
1533           FALSE, FALSE, 0,
1534           NULL, NULL, NULL },
1535
1536         /* WTAP_FILE_TYPE_SUBTYPE_VWR_ETH */
1537         { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL,
1538           FALSE, FALSE, 0,
1539           NULL, NULL, NULL },
1540
1541         /* WTAP_FILE_TYPE_SUBTYPE_CAMINS */
1542         { "CAM Inspector file", "camins", "camins", NULL,
1543           FALSE, FALSE, 0,
1544           NULL, NULL, NULL },
1545
1546         /* WTAP_FILE_TYPE_SUBTYPE_STANAG_4607 */
1547         { "STANAG 4607 Format", "stanag4607", NULL, NULL,
1548           FALSE, FALSE, 0,
1549           NULL, NULL, NULL },
1550
1551         /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0 */
1552         { "NetScaler Trace (Version 3.0)", "nstrace30", "cap", NULL,
1553           TRUE, FALSE, 0,
1554           nstrace_30_dump_can_write_encap, nstrace_dump_open, NULL },
1555
1556         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT */
1557         { "Android Logcat Binary format", "logcat", "logcat", NULL,
1558           FALSE, FALSE, 0,
1559           logcat_dump_can_write_encap, logcat_binary_dump_open, NULL },
1560
1561         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_BRIEF */
1562         { "Android Logcat Brief text format", "logcat-brief", NULL, NULL,
1563           FALSE, FALSE, 0,
1564           logcat_text_brief_dump_can_write_encap, logcat_text_brief_dump_open, NULL },
1565
1566         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_PROCESS */
1567         { "Android Logcat Process text format", "logcat-process", NULL, NULL,
1568           FALSE, FALSE, 0,
1569           logcat_text_process_dump_can_write_encap, logcat_text_process_dump_open, NULL },
1570
1571         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_TAG */
1572         { "Android Logcat Tag text format", "logcat-tag", NULL, NULL,
1573           FALSE, FALSE, 0,
1574           logcat_text_tag_dump_can_write_encap, logcat_text_tag_dump_open, NULL },
1575
1576         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_THREAD */
1577         { "Android Logcat Thread text format", "logcat-thread", NULL, NULL,
1578            FALSE, FALSE, 0,
1579            logcat_text_thread_dump_can_write_encap, logcat_text_thread_dump_open, NULL },
1580
1581         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_TIME */
1582         { "Android Logcat Time text format", "logcat-time", NULL, NULL,
1583           FALSE, FALSE, 0,
1584           logcat_text_time_dump_can_write_encap, logcat_text_time_dump_open, NULL },
1585
1586         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_THREADTIME */
1587         { "Android Logcat Threadtime text format", "logcat-threadtime", NULL, NULL,
1588           FALSE, FALSE, 0,
1589           logcat_text_threadtime_dump_can_write_encap, logcat_text_threadtime_dump_open, NULL },
1590
1591         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_LONG */
1592         { "Android Logcat Long text format", "logcat-long", NULL, NULL,
1593           FALSE, FALSE, 0,
1594           logcat_text_long_dump_can_write_encap, logcat_text_long_dump_open, NULL },
1595
1596         /* WTAP_FILE_TYPE_SUBTYPE_COLASOFT_CAPSA */
1597         { "Colasoft Capsa format", "capsa", "cscpkt", NULL,
1598           FALSE, FALSE, 0,
1599           NULL, NULL, NULL },
1600
1601         /* WTAP_FILE_TYPE_SUBTYPE_COLASOFT_PACKET_BUILDER */
1602         { "Colasoft Packet Builder format", "colasoft-pb", "cscpkt", NULL,
1603           FALSE, FALSE, 0,
1604           NULL, NULL, NULL },
1605
1606         /* WTAP_FILE_TYPE_SUBTYPE_JSON */
1607         { "JavaScript Object Notation", "json", "json", "NULL",
1608           FALSE, FALSE, 0,
1609           NULL, NULL, NULL },
1610
1611         /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_5 */
1612         { "NetScaler Trace (Version 3.5)", "nstrace35", "cap", NULL,
1613           TRUE, FALSE, 0,
1614           nstrace_35_dump_can_write_encap, nstrace_dump_open, NULL },
1615
1616         /* WTAP_FILE_TYPE_SUBTYPE_NETTRACE_3GPP_32_423 */
1617         { "3GPP TS 32.423 Trace", "3gpp32423", NULL, NULL,
1618           FALSE, FALSE, 0,
1619           NULL, NULL, NULL },
1620
1621         /* WTAP_FILE_TYPE_MPLOG */
1622         { "Micropross mplog file", "mplog", "mplog", NULL,
1623           FALSE, FALSE, 0,
1624           NULL, NULL, NULL }
1625 };
1626
1627 /*
1628  * Pointer to the table we're currently using.  It's initialized to point
1629  * to the static table, but, if we have to allocate the GArray, it's
1630  * changed to point to the data in the GArray.
1631  */
1632 static const struct file_type_subtype_info* dump_open_table = dump_open_table_base;
1633
1634 /*
1635  * Number of elements in the table we're currently using.  It's initialized
1636  * to the number of elements in the static table, but, if we have to
1637  * allocate the GArray, it's changed to have the size of the GArray.
1638  */
1639 gint wtap_num_file_types_subtypes = sizeof(dump_open_table_base) / sizeof(struct file_type_subtype_info);
1640
1641 /*
1642  * Pointer to the GArray; NULL until it's needed.
1643  */
1644 static GArray*  dump_open_table_arr = NULL;
1645
1646 /*
1647  * Create the GArray from the static table if it hasn't already been created.
1648  */
1649 static void
1650 init_file_types_subtypes_garray(void)
1651 {
1652         if (dump_open_table_arr) return;
1653
1654         dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_subtype_info));
1655
1656         g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types_subtypes);
1657
1658         dump_open_table = (const struct file_type_subtype_info*)(void *)dump_open_table_arr->data;
1659 }
1660
1661 /* if subtype is WTAP_FILE_TYPE_SUBTYPE_UNKNOWN, then create a new subtype as well as register it, else replace the
1662    existing entry in that spot */
1663 int
1664 wtap_register_file_type_subtypes(const struct file_type_subtype_info* fi, const int subtype)
1665 {
1666         struct file_type_subtype_info* finfo;
1667
1668         if (!fi || !fi->name || !fi->short_name || subtype > wtap_num_file_types_subtypes) {
1669                 g_error("no file type info or invalid file type to register");
1670                 return subtype;
1671         }
1672
1673         /* do we want a new registration? */
1674         if (subtype == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) {
1675                 /* register a new one; first verify there isn't one named this already */
1676                 if (wtap_short_string_to_file_type_subtype(fi->short_name) > -1 ) {
1677                         g_error("file type short name already exists");
1678                         return subtype;
1679                 }
1680
1681                 /*
1682                  * Create the GArray if it hasn't already been created.
1683                  */
1684                 init_file_types_subtypes_garray();
1685
1686                 g_array_append_val(dump_open_table_arr,*fi);
1687
1688                 dump_open_table = (const struct file_type_subtype_info*)(void *)dump_open_table_arr->data;
1689
1690                 return wtap_num_file_types_subtypes++;
1691         }
1692
1693         /* re-register an existing one - verify the short names do match (sanity check really) */
1694         if (!dump_open_table[subtype].short_name || strcmp(dump_open_table[subtype].short_name,fi->short_name) != 0) {
1695                 g_error("invalid file type name given to register");
1696                 return subtype;
1697         }
1698
1699         /*
1700          * Create the GArray if it hasn't already been created.
1701          */
1702         init_file_types_subtypes_garray();
1703
1704         /*
1705          * Get the pointer from the GArray, so that we get a non-const
1706          * pointer.
1707          */
1708         finfo = &g_array_index(dump_open_table_arr, struct file_type_subtype_info, subtype);
1709         /*finfo->name = fi->name;*/
1710         /*finfo->short_name = fi->short_name;*/
1711         finfo->default_file_extension     = fi->default_file_extension;
1712         finfo->additional_file_extensions = fi->additional_file_extensions;
1713         finfo->writing_must_seek          = fi->writing_must_seek;
1714         finfo->has_name_resolution        = fi->has_name_resolution;
1715         finfo->supported_comment_types    = fi->supported_comment_types;
1716         finfo->can_write_encap            = fi->can_write_encap;
1717         finfo->dump_open                  = fi->dump_open;
1718         finfo->wslua_info                 = fi->wslua_info;
1719
1720         return subtype;
1721 }
1722
1723 /* De-registers a file writer - they can never be removed from the GArray, but we can "clear" an entry.
1724  */
1725 void
1726 wtap_deregister_file_type_subtype(const int subtype)
1727 {
1728         struct file_type_subtype_info* finfo;
1729
1730         if (subtype < 0 || subtype >= wtap_num_file_types_subtypes) {
1731                 g_error("invalid file type to de-register");
1732                 return;
1733         }
1734
1735         /*
1736          * Create the GArray if it hasn't already been created.
1737          */
1738         init_file_types_subtypes_garray();
1739
1740         /*
1741          * Get the pointer from the GArray, so that we get a non-const
1742          * pointer.
1743          */
1744         finfo = &g_array_index(dump_open_table_arr, struct file_type_subtype_info, subtype);
1745         /* unfortunately, it's not safe to null-out the name or short_name; bunch of other code doesn't guard aainst that, afaict */
1746         /*finfo->name = NULL;*/
1747         /*finfo->short_name = NULL;*/
1748         finfo->default_file_extension = NULL;
1749         finfo->additional_file_extensions = NULL;
1750         finfo->writing_must_seek = FALSE;
1751         finfo->has_name_resolution = FALSE;
1752         finfo->supported_comment_types = 0;
1753         finfo->can_write_encap = NULL;
1754         finfo->dump_open = NULL;
1755         finfo->wslua_info = NULL;
1756 }
1757
1758 int
1759 wtap_get_num_file_types_subtypes(void)
1760 {
1761         return wtap_num_file_types_subtypes;
1762 }
1763
1764 /*
1765  * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
1766  * type that would be needed to write out a file with those types.  If
1767  * there's only one type, it's that type, otherwise it's
1768  * WTAP_ENCAP_PER_PACKET.
1769  */
1770 int
1771 wtap_dump_file_encap_type(const GArray *file_encaps)
1772 {
1773         int encap;
1774
1775         encap = WTAP_ENCAP_PER_PACKET;
1776         if (file_encaps->len == 1) {
1777                 /* OK, use the one-and-only encapsulation type. */
1778                 encap = g_array_index(file_encaps, gint, 0);
1779         }
1780         return encap;
1781 }
1782
1783 static gboolean
1784 wtap_dump_can_write_encap(int filetype, int encap)
1785 {
1786         int result = 0;
1787
1788         if (filetype < 0 || filetype >= wtap_num_file_types_subtypes
1789             || dump_open_table[filetype].can_write_encap == NULL)
1790                 return FALSE;
1791
1792         result = (*dump_open_table[filetype].can_write_encap)(encap);
1793
1794         if (result != 0) {
1795                 /* if the err said to check wslua's can_write_encap, try that */
1796                 if (result == WTAP_ERR_CHECK_WSLUA
1797                         && dump_open_table[filetype].wslua_info != NULL
1798                         && dump_open_table[filetype].wslua_info->wslua_can_write_encap != NULL) {
1799
1800                         result = (*dump_open_table[filetype].wslua_info->wslua_can_write_encap)(encap, dump_open_table[filetype].wslua_info->wslua_data);
1801
1802                 }
1803
1804                 if (result != 0)
1805                         return FALSE;
1806         }
1807
1808         return TRUE;
1809 }
1810
1811 /*
1812  * Return TRUE if a capture with a given GArray of encapsulation types
1813  * and a given bitset of comment types can be written in a specified
1814  * format, and FALSE if it can't.
1815  */
1816 static gboolean
1817 wtap_dump_can_write_format(int ft, const GArray *file_encaps,
1818     guint32 required_comment_types)
1819 {
1820         guint i;
1821
1822         /*
1823          * Can we write in this format?
1824          */
1825         if (!wtap_dump_can_open(ft)) {
1826                 /* No. */
1827                 return FALSE;
1828         }
1829
1830         /*
1831          * Yes.  Can we write out all the required comments in this
1832          * format?
1833          */
1834         if (!wtap_dump_supports_comment_types(ft, required_comment_types)) {
1835                 /* No. */
1836                 return FALSE;
1837         }
1838
1839         /*
1840          * Yes.  Is the required per-file encapsulation type supported?
1841          * This might be WTAP_ENCAP_PER_PACKET.
1842          */
1843         if (!wtap_dump_can_write_encap(ft, wtap_dump_file_encap_type(file_encaps))) {
1844                 /* No. */
1845                 return FALSE;
1846         }
1847
1848         /*
1849          * Yes.  Are all the individual encapsulation types supported?
1850          */
1851         for (i = 0; i < file_encaps->len; i++) {
1852                 if (!wtap_dump_can_write_encap(ft,
1853                     g_array_index(file_encaps, int, i))) {
1854                         /* No - one of them isn't. */
1855                         return FALSE;
1856                 }
1857         }
1858
1859         /* Yes - we're OK. */
1860         return TRUE;
1861 }
1862
1863 /**
1864  * Return TRUE if we can write a file with the given GArray of
1865  * encapsulation types and the given bitmask of comment types.
1866  */
1867 gboolean
1868 wtap_dump_can_write(const GArray *file_encaps, guint32 required_comment_types)
1869 {
1870         int ft;
1871
1872         for (ft = 0; ft < WTAP_NUM_FILE_TYPES_SUBTYPES; ft++) {
1873                 /* To save a file with Wiretap, Wiretap has to handle that format,
1874                  * and its code to handle that format must be able to write a file
1875                  * with this file's encapsulation types.
1876                  */
1877                 if (wtap_dump_can_write_format(ft, file_encaps, required_comment_types)) {
1878                         /* OK, we can write it out in this type. */
1879                         return TRUE;
1880                 }
1881         }
1882
1883         /* No, we couldn't save it in any format. */
1884         return FALSE;
1885 }
1886
1887 /**
1888  * Get a GArray of WTAP_FILE_TYPE_SUBTYPE_ values for file types/subtypes
1889  * that can be used to save a file of a given type/subtype with a given
1890  * GArray of encapsulation types and the given bitmask of comment types.
1891  */
1892 GArray *
1893 wtap_get_savable_file_types_subtypes(int file_type_subtype,
1894     const GArray *file_encaps, guint32 required_comment_types)
1895 {
1896         GArray *savable_file_types_subtypes;
1897         int ft;
1898         int default_file_type_subtype = -1;
1899         int other_file_type_subtype = -1;
1900
1901         /* Can we save this file in its own file type/subtype? */
1902         if (wtap_dump_can_write_format(file_type_subtype, file_encaps,
1903                                        required_comment_types)) {
1904                 /* Yes - make that the default file type/subtype. */
1905                 default_file_type_subtype = file_type_subtype;
1906         } else {
1907                 /* OK, find the first file type/subtype we *can* save it as. */
1908                 default_file_type_subtype = -1;
1909                 for (ft = 0; ft < WTAP_NUM_FILE_TYPES_SUBTYPES; ft++) {
1910                         if (wtap_dump_can_write_format(ft, file_encaps,
1911                                                        required_comment_types)) {
1912                                 /* OK, got it. */
1913                                 default_file_type_subtype = ft;
1914                         }
1915                 }
1916         }
1917
1918         if (default_file_type_subtype == -1) {
1919                 /* We don't support writing this file as any file type/subtype. */
1920                 return NULL;
1921         }
1922
1923         /* Allocate the array. */
1924         savable_file_types_subtypes = g_array_new(FALSE, FALSE, (guint)sizeof (int));
1925
1926         /* Put the default file type/subtype first in the list. */
1927         g_array_append_val(savable_file_types_subtypes, default_file_type_subtype);
1928
1929         /* If the default is pcap, put pcap-NG right after it if we can
1930            also write it in pcap-NG format; otherwise, if the default is
1931            pcap-NG, put pcap right after it if we can also write it in
1932            pcap format. */
1933         if (default_file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP) {
1934                 if (wtap_dump_can_write_format(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, file_encaps,
1935                                                required_comment_types))
1936                         other_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
1937         } else if (default_file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAPNG) {
1938                 if (wtap_dump_can_write_format(WTAP_FILE_TYPE_SUBTYPE_PCAP, file_encaps,
1939                                                required_comment_types))
1940                         other_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAP;
1941         }
1942         if (other_file_type_subtype != -1)
1943                 g_array_append_val(savable_file_types_subtypes, other_file_type_subtype);
1944
1945         /* Add all the other file types/subtypes that work. */
1946         for (ft = 0; ft < WTAP_NUM_FILE_TYPES_SUBTYPES; ft++) {
1947                 if (ft == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN)
1948                         continue;       /* not a real file type */
1949                 if (ft == default_file_type_subtype || ft == other_file_type_subtype)
1950                         continue;       /* we've already done this one */
1951                 if (wtap_dump_can_write_format(ft, file_encaps,
1952                                                required_comment_types)) {
1953                         /* OK, we can write it out in this type. */
1954                         g_array_append_val(savable_file_types_subtypes, ft);
1955                 }
1956         }
1957
1958         return savable_file_types_subtypes;
1959 }
1960
1961 /* Name that should be somewhat descriptive. */
1962 const char *
1963 wtap_file_type_subtype_string(int file_type_subtype)
1964 {
1965         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes) {
1966                 g_error("Unknown capture file type %d", file_type_subtype);
1967                 /** g_error() does an abort() and thus never returns **/
1968                 return "";
1969         } else
1970                 return dump_open_table[file_type_subtype].name;
1971 }
1972
1973 /* Name to use in, say, a command-line flag specifying the type/subtype. */
1974 const char *
1975 wtap_file_type_subtype_short_string(int file_type_subtype)
1976 {
1977         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
1978                 return NULL;
1979         else
1980                 return dump_open_table[file_type_subtype].short_name;
1981 }
1982
1983 /* Translate a short name to a capture file type/subtype. */
1984 int
1985 wtap_short_string_to_file_type_subtype(const char *short_name)
1986 {
1987         int file_type_subtype;
1988
1989         for (file_type_subtype = 0; file_type_subtype < wtap_num_file_types_subtypes; file_type_subtype++) {
1990                 if (dump_open_table[file_type_subtype].short_name != NULL &&
1991                     strcmp(short_name, dump_open_table[file_type_subtype].short_name) == 0)
1992                         return file_type_subtype;
1993         }
1994
1995         /*
1996          * We now call the "libpcap" file format just "pcap", but we
1997          * allow it to be specified as "libpcap" as well, for
1998          * backwards compatibility.
1999          */
2000         if (strcmp(short_name, "libpcap") == 0)
2001                 return WTAP_FILE_TYPE_SUBTYPE_PCAP;
2002
2003         return -1;      /* no such file type, or we can't write it */
2004 }
2005
2006 static GSList *
2007 add_extensions_for_file_type_subtype(int file_type_subtype, GSList *extensions,
2008     const char **compressed_file_extensions)
2009 {
2010         gchar **extensions_set, **extensionp;
2011         gchar *extension;
2012
2013         /*
2014          * Add the default extension, and all compressed variants of
2015          * it.
2016          */
2017         extensions = add_extensions(extensions,
2018             dump_open_table[file_type_subtype].default_file_extension,
2019             compressed_file_extensions);
2020
2021         if (dump_open_table[file_type_subtype].additional_file_extensions != NULL) {
2022                 /*
2023                  * We have additional extensions; add them.
2024                  *
2025                  * First, split the extension-list string into a set of
2026                  * extensions.
2027                  */
2028                 extensions_set = g_strsplit(dump_open_table[file_type_subtype].additional_file_extensions,
2029                     ";", 0);
2030
2031                 /*
2032                  * Add each of those extensions to the list.
2033                  */
2034                 for (extensionp = extensions_set; *extensionp != NULL;
2035                     extensionp++) {
2036                         extension = *extensionp;
2037
2038                         /*
2039                          * Add the extension, and all compressed variants
2040                          * of it.
2041                          */
2042                         extensions = add_extensions(extensions, extension,
2043                             compressed_file_extensions);
2044                 }
2045
2046                 g_strfreev(extensions_set);
2047         }
2048         return extensions;
2049 }
2050
2051 /* Return a list of file extensions that are used by the specified file type.
2052
2053    If include_compressed is TRUE, the list will include compressed
2054    extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
2055    gzipped files.
2056
2057    All strings in the list are allocated with g_malloc() and must be freed
2058    with g_free(). */
2059 GSList *
2060 wtap_get_file_extensions_list(int file_type_subtype, gboolean include_compressed)
2061 {
2062         GSList *extensions;
2063         static const char *no_compressed_extensions[] = {
2064                 NULL
2065         };
2066
2067         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
2068                 return NULL;    /* not a valid file type */
2069
2070         if (dump_open_table[file_type_subtype].default_file_extension == NULL)
2071                 return NULL;    /* valid, but no extensions known */
2072
2073         extensions = NULL;      /* empty list, to start with */
2074
2075         /*
2076          * Add all this file type's extensions, with compressed
2077          * variants if include_compressed is true.
2078          */
2079         extensions = add_extensions_for_file_type_subtype(file_type_subtype, extensions,
2080             include_compressed ? compressed_file_extension_table : no_compressed_extensions);
2081
2082         return extensions;
2083 }
2084
2085 /*
2086  * Free a list returned by wtap_get_file_extension_type_extensions(),
2087  * wtap_get_all_capture_file_extensions_list, or
2088  * wtap_get_file_extensions_list().
2089  */
2090 void
2091 wtap_free_extensions_list(GSList *extensions)
2092 {
2093         GSList *extension;
2094
2095         for (extension = extensions; extension != NULL;
2096             extension = g_slist_next(extension)) {
2097                 g_free(extension->data);
2098         }
2099         g_slist_free(extensions);
2100 }
2101
2102 /* Return the default file extension to use with the specified file type;
2103    that's just the extension, without any ".". */
2104 const char *
2105 wtap_default_file_extension(int file_type_subtype)
2106 {
2107         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
2108                 return NULL;
2109         else
2110                 return dump_open_table[file_type_subtype].default_file_extension;
2111 }
2112
2113 gboolean
2114 wtap_dump_can_open(int file_type_subtype)
2115 {
2116         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
2117             || dump_open_table[file_type_subtype].dump_open == NULL)
2118                 return FALSE;
2119
2120         return TRUE;
2121 }
2122
2123 #ifdef HAVE_ZLIB
2124 gboolean
2125 wtap_dump_can_compress(int file_type_subtype)
2126 {
2127         /*
2128          * If this is an unknown file type, or if we have to
2129          * seek when writing out a file with this file type,
2130          * return FALSE.
2131          */
2132         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
2133             || dump_open_table[file_type_subtype].writing_must_seek)
2134                 return FALSE;
2135
2136         return TRUE;
2137 }
2138 #else
2139 gboolean
2140 wtap_dump_can_compress(int file_type_subtype _U_)
2141 {
2142         return FALSE;
2143 }
2144 #endif
2145
2146 gboolean
2147 wtap_dump_has_name_resolution(int file_type_subtype)
2148 {
2149         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
2150             || dump_open_table[file_type_subtype].has_name_resolution == FALSE)
2151                 return FALSE;
2152
2153         return TRUE;
2154 }
2155
2156 gboolean
2157 wtap_dump_supports_comment_types(int file_type_subtype, guint32 comment_types)
2158 {
2159         guint32 supported_comment_types;
2160
2161         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
2162                 return FALSE;
2163
2164         supported_comment_types = dump_open_table[file_type_subtype].supported_comment_types;
2165
2166         if ((comment_types & supported_comment_types) == comment_types)
2167                 return TRUE;
2168         return FALSE;
2169 }
2170
2171 static gboolean wtap_dump_open_check(int file_type_subtype, int encap, gboolean comressed, int *err);
2172 static wtap_dumper* wtap_dump_alloc_wdh(int file_type_subtype, int encap, int snaplen,
2173                                         gboolean compressed, int *err);
2174 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int file_type_subtype, gboolean compressed, int *err);
2175
2176 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
2177 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
2178 static int wtap_dump_file_close(wtap_dumper *wdh);
2179
2180 static wtap_dumper *
2181 wtap_dump_init_dumper(int file_type_subtype, int encap, int snaplen, gboolean compressed,
2182                       GArray* shb_hdrs, wtapng_iface_descriptions_t *idb_inf,
2183                       GArray* nrb_hdrs, int *err)
2184 {
2185         wtap_dumper *wdh;
2186         wtap_block_t descr, file_int_data;
2187         wtapng_if_descr_mandatory_t *descr_mand, *file_int_data_mand;
2188
2189         /* Check whether we can open a capture file with that file type
2190            and that encapsulation. */
2191         if (!wtap_dump_open_check(file_type_subtype, encap, compressed, err))
2192                 return NULL;
2193
2194         /* Allocate a data structure for the output stream. */
2195         wdh = wtap_dump_alloc_wdh(file_type_subtype, encap, snaplen, compressed, err);
2196         if (wdh == NULL)
2197                 return NULL;    /* couldn't allocate it */
2198
2199         /* Set Section Header Block data */
2200         wdh->shb_hdrs = shb_hdrs;
2201         /* Set Name Resolution Block data */
2202         wdh->nrb_hdrs = nrb_hdrs;
2203         /* Set Interface Description Block data */
2204         if ((idb_inf != NULL) && (idb_inf->interface_data->len > 0)) {
2205                 guint itf_count;
2206
2207                 /* XXX: what free's this stuff? */
2208                 wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
2209                 for (itf_count = 0; itf_count < idb_inf->interface_data->len; itf_count++) {
2210                         file_int_data = g_array_index(idb_inf->interface_data, wtap_block_t, itf_count);
2211                         file_int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(file_int_data);
2212                         descr = wtap_block_create(WTAP_BLOCK_IF_DESCR);
2213                         wtap_block_copy(descr, file_int_data);
2214                         if ((encap != WTAP_ENCAP_PER_PACKET) && (encap != file_int_data_mand->wtap_encap)) {
2215                                 descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(descr);
2216                                 descr_mand->wtap_encap = encap;
2217                                 descr_mand->link_type = wtap_wtap_encap_to_pcap_encap(encap);
2218                         }
2219                         g_array_append_val(wdh->interface_data, descr);
2220                 }
2221         } else {
2222                 descr = wtap_block_create(WTAP_BLOCK_IF_DESCR);
2223                 descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(descr);
2224                 descr_mand->wtap_encap = encap;
2225                 descr_mand->time_units_per_second = 1000000; /* default microsecond resolution */
2226                 descr_mand->link_type = wtap_wtap_encap_to_pcap_encap(encap);
2227                 descr_mand->snap_len = snaplen;
2228                 descr_mand->num_stat_entries = 0;          /* Number of ISB:s */
2229                 descr_mand->interface_statistics = NULL;
2230                 wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
2231                 g_array_append_val(wdh->interface_data, descr);
2232         }
2233         return wdh;
2234 }
2235
2236 wtap_dumper *
2237 wtap_dump_open(const char *filename, int file_type_subtype, int encap,
2238                int snaplen, gboolean compressed, int *err)
2239 {
2240         return wtap_dump_open_ng(filename, file_type_subtype, encap,snaplen, compressed, NULL, NULL, NULL, err);
2241 }
2242
2243 wtap_dumper *
2244 wtap_dump_open_ng(const char *filename, int file_type_subtype, int encap,
2245                   int snaplen, gboolean compressed, GArray* shb_hdrs, wtapng_iface_descriptions_t *idb_inf,
2246                   GArray* nrb_hdrs, int *err)
2247 {
2248         wtap_dumper *wdh;
2249         WFILE_T fh;
2250
2251         /* Allocate and initialize a data structure for the output stream. */
2252         wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2253             shb_hdrs, idb_inf, nrb_hdrs, err);
2254         if (wdh == NULL)
2255                 return NULL;
2256
2257         /* In case "fopen()" fails but doesn't set "errno", set "errno"
2258            to a generic "the open failed" error. */
2259         errno = WTAP_ERR_CANT_OPEN;
2260         fh = wtap_dump_file_open(wdh, filename);
2261         if (fh == NULL) {
2262                 *err = errno;
2263                 g_free(wdh);
2264                 return NULL;    /* can't create file */
2265         }
2266         wdh->fh = fh;
2267
2268         if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2269                 /* Get rid of the file we created; we couldn't finish
2270                    opening it. */
2271                 wtap_dump_file_close(wdh);
2272                 ws_unlink(filename);
2273                 g_free(wdh);
2274                 return NULL;
2275         }
2276         return wdh;
2277 }
2278
2279 wtap_dumper *
2280 wtap_dump_open_tempfile(char **filenamep, const char *pfx,
2281                         int file_type_subtype, int encap,
2282                         int snaplen, gboolean compressed, int *err)
2283 {
2284         return wtap_dump_open_tempfile_ng(filenamep, pfx, file_type_subtype, encap,snaplen, compressed, NULL, NULL, NULL, err);
2285 }
2286
2287 wtap_dumper *
2288 wtap_dump_open_tempfile_ng(char **filenamep, const char *pfx,
2289                            int file_type_subtype, int encap,
2290                            int snaplen, gboolean compressed,
2291                            GArray* shb_hdrs,
2292                            wtapng_iface_descriptions_t *idb_inf,
2293                            GArray* nrb_hdrs, int *err)
2294 {
2295         int fd;
2296         char *tmpname;
2297         wtap_dumper *wdh;
2298         WFILE_T fh;
2299
2300         /* No path name for the temporary file yet. */
2301         *filenamep = NULL;
2302
2303         /* Allocate and initialize a data structure for the output stream. */
2304         wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2305             shb_hdrs, idb_inf, nrb_hdrs, err);
2306         if (wdh == NULL)
2307                 return NULL;
2308
2309         /* Choose a random name for the file */
2310         fd = create_tempfile(&tmpname, pfx, ".pcapng");
2311         if (fd == -1) {
2312                 *err = errno;
2313                 g_free(wdh);
2314                 return NULL;    /* can't create file */
2315         }
2316         *filenamep = tmpname;
2317
2318         /* In case "fopen()" fails but doesn't set "errno", set "errno"
2319            to a generic "the open failed" error. */
2320         errno = WTAP_ERR_CANT_OPEN;
2321         fh = wtap_dump_file_fdopen(wdh, fd);
2322         if (fh == NULL) {
2323                 *err = errno;
2324                 ws_close(fd);
2325                 g_free(wdh);
2326                 return NULL;    /* can't create file */
2327         }
2328         wdh->fh = fh;
2329
2330         if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2331                 /* Get rid of the file we created; we couldn't finish
2332                    opening it. */
2333                 wtap_dump_file_close(wdh);
2334                 ws_unlink(tmpname);
2335                 g_free(wdh);
2336                 return NULL;
2337         }
2338         return wdh;
2339 }
2340
2341 wtap_dumper *
2342 wtap_dump_fdopen(int fd, int file_type_subtype, int encap, int snaplen,
2343                  gboolean compressed, int *err)
2344 {
2345         return wtap_dump_fdopen_ng(fd, file_type_subtype, encap, snaplen, compressed, NULL, NULL, NULL, err);
2346 }
2347
2348 wtap_dumper *
2349 wtap_dump_fdopen_ng(int fd, int file_type_subtype, int encap, int snaplen,
2350                     gboolean compressed, GArray* shb_hdrs, wtapng_iface_descriptions_t *idb_inf,
2351                     GArray* nrb_hdrs, int *err)
2352 {
2353         wtap_dumper *wdh;
2354         WFILE_T fh;
2355
2356         /* Allocate and initialize a data structure for the output stream. */
2357         wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2358             shb_hdrs, idb_inf, nrb_hdrs, err);
2359         if (wdh == NULL)
2360                 return NULL;
2361
2362         /* In case "fopen()" fails but doesn't set "errno", set "errno"
2363            to a generic "the open failed" error. */
2364         errno = WTAP_ERR_CANT_OPEN;
2365         fh = wtap_dump_file_fdopen(wdh, fd);
2366         if (fh == NULL) {
2367                 *err = errno;
2368                 g_free(wdh);
2369                 return NULL;    /* can't create standard I/O stream */
2370         }
2371         wdh->fh = fh;
2372
2373         if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2374                 wtap_dump_file_close(wdh);
2375                 g_free(wdh);
2376                 return NULL;
2377         }
2378         return wdh;
2379 }
2380
2381 wtap_dumper *
2382 wtap_dump_open_stdout(int file_type_subtype, int encap, int snaplen,
2383                       gboolean compressed, int *err)
2384 {
2385         return wtap_dump_open_stdout_ng(file_type_subtype, encap, snaplen, compressed, NULL, NULL, NULL, err);
2386 }
2387
2388 wtap_dumper *
2389 wtap_dump_open_stdout_ng(int file_type_subtype, int encap, int snaplen,
2390                          gboolean compressed, GArray* shb_hdrs,
2391                          wtapng_iface_descriptions_t *idb_inf,
2392                          GArray* nrb_hdrs, int *err)
2393 {
2394         wtap_dumper *wdh;
2395         WFILE_T fh;
2396
2397         /* Allocate and initialize a data structure for the output stream. */
2398         wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2399             shb_hdrs, idb_inf, nrb_hdrs, err);
2400         if (wdh == NULL)
2401                 return NULL;
2402
2403 #ifdef _WIN32
2404         /*
2405          * Put the standard output into binary mode.
2406          *
2407          * XXX - even if the file format we're writing is a text
2408          * format?
2409          */
2410         if (_setmode(1, O_BINARY) == -1) {
2411                 /* "Should not happen" */
2412                 *err = errno;
2413                 g_free(wdh);
2414                 return NULL;    /* couldn't put standard output in binary mode */
2415         }
2416 #endif
2417
2418         /* In case "fopen()" fails but doesn't set "errno", set "errno"
2419            to a generic "the open failed" error. */
2420         errno = WTAP_ERR_CANT_OPEN;
2421         fh = wtap_dump_file_fdopen(wdh, 1);
2422         if (fh == NULL) {
2423                 *err = errno;
2424                 g_free(wdh);
2425                 return NULL;    /* can't create standard I/O stream */
2426         }
2427         wdh->fh = fh;
2428         wdh->is_stdout = TRUE;
2429
2430         if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2431                 wtap_dump_file_close(wdh);
2432                 g_free(wdh);
2433                 return NULL;
2434         }
2435         return wdh;
2436 }
2437
2438 static gboolean
2439 wtap_dump_open_check(int file_type_subtype, int encap, gboolean compressed, int *err)
2440 {
2441         if (!wtap_dump_can_open(file_type_subtype)) {
2442                 /* Invalid type, or type we don't know how to write. */
2443                 *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
2444                 return FALSE;
2445         }
2446
2447         /* OK, we know how to write that type; can we write the specified
2448            encapsulation type? */
2449         *err = (*dump_open_table[file_type_subtype].can_write_encap)(encap);
2450         /* if the err said to check wslua's can_write_encap, try that */
2451         if (*err == WTAP_ERR_CHECK_WSLUA
2452                 && dump_open_table[file_type_subtype].wslua_info != NULL
2453                 && dump_open_table[file_type_subtype].wslua_info->wslua_can_write_encap != NULL) {
2454
2455                 *err = (*dump_open_table[file_type_subtype].wslua_info->wslua_can_write_encap)(encap, dump_open_table[file_type_subtype].wslua_info->wslua_data);
2456
2457         }
2458
2459         if (*err != 0)
2460                 return FALSE;
2461
2462         /* if compression is wanted, do we support this for this file_type_subtype? */
2463         if(compressed && !wtap_dump_can_compress(file_type_subtype)) {
2464                 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
2465                 return FALSE;
2466         }
2467
2468         /* All systems go! */
2469         return TRUE;
2470 }
2471
2472 static wtap_dumper *
2473 wtap_dump_alloc_wdh(int file_type_subtype, int encap, int snaplen, gboolean compressed, int *err)
2474 {
2475         wtap_dumper *wdh;
2476
2477         wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
2478         if (wdh == NULL) {
2479                 *err = errno;
2480                 return NULL;
2481         }
2482
2483         wdh->file_type_subtype = file_type_subtype;
2484         wdh->snaplen = snaplen;
2485         wdh->encap = encap;
2486         wdh->compressed = compressed;
2487         wdh->wslua_data = NULL;
2488         return wdh;
2489 }
2490
2491 static gboolean
2492 wtap_dump_open_finish(wtap_dumper *wdh, int file_type_subtype, gboolean compressed, int *err)
2493 {
2494         int fd;
2495         gboolean cant_seek;
2496
2497         /* Can we do a seek on the file descriptor?
2498            If not, note that fact. */
2499         if(compressed) {
2500                 cant_seek = TRUE;
2501         } else {
2502                 fd = ws_fileno((FILE *)wdh->fh);
2503                 if (ws_lseek64(fd, 1, SEEK_CUR) == (off_t) -1)
2504                         cant_seek = TRUE;
2505                 else {
2506                         /* Undo the seek. */
2507                         ws_lseek64(fd, 0, SEEK_SET);
2508                         cant_seek = FALSE;
2509                 }
2510         }
2511
2512         /* If this file type requires seeking, and we can't seek, fail. */
2513         if (dump_open_table[file_type_subtype].writing_must_seek && cant_seek) {
2514                 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
2515                 return FALSE;
2516         }
2517
2518         /* Set wdh with wslua data if any - this is how we pass the data
2519          * to the file writer.
2520          */
2521         if (dump_open_table[file_type_subtype].wslua_info)
2522                 wdh->wslua_data = dump_open_table[file_type_subtype].wslua_info->wslua_data;
2523
2524         /* Now try to open the file for writing. */
2525         if (!(*dump_open_table[file_type_subtype].dump_open)(wdh, err)) {
2526                 return FALSE;
2527         }
2528
2529         return TRUE;    /* success! */
2530 }
2531
2532 gboolean
2533 wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
2534           const guint8 *pd, int *err, gchar **err_info)
2535 {
2536         *err = 0;
2537         *err_info = NULL;
2538         return (wdh->subtype_write)(wdh, phdr, pd, err, err_info);
2539 }
2540
2541 void
2542 wtap_dump_flush(wtap_dumper *wdh)
2543 {
2544 #ifdef HAVE_ZLIB
2545         if(wdh->compressed) {
2546                 gzwfile_flush((GZWFILE_T)wdh->fh);
2547         } else
2548 #endif
2549         {
2550                 fflush((FILE *)wdh->fh);
2551         }
2552 }
2553
2554 gboolean
2555 wtap_dump_close(wtap_dumper *wdh, int *err)
2556 {
2557         gboolean ret = TRUE;
2558
2559         if (wdh->subtype_finish != NULL) {
2560                 /* There's a finish routine for this dump stream. */
2561                 if (!(wdh->subtype_finish)(wdh, err))
2562                         ret = FALSE;
2563         }
2564         errno = WTAP_ERR_CANT_CLOSE;
2565         if (wtap_dump_file_close(wdh) == EOF) {
2566                 if (ret) {
2567                         /* The per-format finish function succeeded,
2568                            but the stream close didn't.  Save the
2569                            reason why, if our caller asked for it. */
2570                         if (err != NULL)
2571                                 *err = errno;
2572                 }
2573                 ret = FALSE;
2574         }
2575         if (wdh->priv != NULL)
2576                 g_free(wdh->priv);
2577         g_free(wdh);
2578         return ret;
2579 }
2580
2581 gint64
2582 wtap_get_bytes_dumped(wtap_dumper *wdh)
2583 {
2584         return wdh->bytes_dumped;
2585 }
2586
2587 void
2588 wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
2589 {
2590         wdh->bytes_dumped = bytes_dumped;
2591 }
2592
2593 gboolean
2594 wtap_dump_set_addrinfo_list(wtap_dumper *wdh, addrinfo_lists_t *addrinfo_lists)
2595 {
2596         if (!wdh || wdh->file_type_subtype < 0 || wdh->file_type_subtype >= wtap_num_file_types_subtypes
2597                 || dump_open_table[wdh->file_type_subtype].has_name_resolution == FALSE)
2598                         return FALSE;
2599         wdh->addrinfo_lists = addrinfo_lists;
2600         return TRUE;
2601 }
2602
2603 /* internally open a file for writing (compressed or not) */
2604 #ifdef HAVE_ZLIB
2605 static WFILE_T
2606 wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
2607 {
2608         if(wdh->compressed) {
2609                 return gzwfile_open(filename);
2610         } else {
2611                 return ws_fopen(filename, "wb");
2612         }
2613 }
2614 #else
2615 static WFILE_T
2616 wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
2617 {
2618         return ws_fopen(filename, "wb");
2619 }
2620 #endif
2621
2622 /* internally open a file for writing (compressed or not) */
2623 #ifdef HAVE_ZLIB
2624 static WFILE_T
2625 wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
2626 {
2627         if(wdh->compressed) {
2628                 return gzwfile_fdopen(fd);
2629         } else {
2630                 return ws_fdopen(fd, "wb");
2631         }
2632 }
2633 #else
2634 static WFILE_T
2635 wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
2636 {
2637         return ws_fdopen(fd, "wb");
2638 }
2639 #endif
2640
2641 /* internally writing raw bytes (compressed or not) */
2642 gboolean
2643 wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize, int *err)
2644 {
2645         size_t nwritten;
2646
2647 #ifdef HAVE_ZLIB
2648         if (wdh->compressed) {
2649                 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned int) bufsize);
2650                 /*
2651                  * gzwfile_write() returns 0 on error.
2652                  */
2653                 if (nwritten == 0) {
2654                         *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
2655                         return FALSE;
2656                 }
2657         } else
2658 #endif
2659         {
2660                 errno = WTAP_ERR_CANT_WRITE;
2661                 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
2662                 /*
2663                  * At least according to the Mac OS X man page,
2664                  * this can return a short count on an error.
2665                  */
2666                 if (nwritten != bufsize) {
2667                         if (ferror((FILE *)wdh->fh))
2668                                 *err = errno;
2669                         else
2670                                 *err = WTAP_ERR_SHORT_WRITE;
2671                         return FALSE;
2672                 }
2673         }
2674         return TRUE;
2675 }
2676
2677 /* internally close a file for writing (compressed or not) */
2678 static int
2679 wtap_dump_file_close(wtap_dumper *wdh)
2680 {
2681 #ifdef HAVE_ZLIB
2682         if(wdh->compressed) {
2683                 /*
2684                  * Tell gzwfile_close() whether to close the descriptor
2685                  * or not.
2686                  */
2687                 return gzwfile_close((GZWFILE_T)wdh->fh, wdh->is_stdout);
2688         } else
2689 #endif
2690         {
2691                 /*
2692                  * Don't close the standard output.
2693                  *
2694                  * XXX - this really should do everything fclose() does,
2695                  * including freeing all allocated data structures,
2696                  * *except* for actually closing the file descriptor.
2697                  */
2698                 return wdh->is_stdout ? fflush((FILE *)wdh->fh) : fclose((FILE *)wdh->fh);
2699         }
2700 }
2701
2702 gint64
2703 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
2704 {
2705 #ifdef HAVE_ZLIB
2706         if(wdh->compressed) {
2707                 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2708                 return -1;
2709         } else
2710 #endif
2711         {
2712                 if (-1 == fseek((FILE *)wdh->fh, (long)offset, whence)) {
2713                         *err = errno;
2714                         return -1;
2715                 } else
2716                 {
2717                         return 0;
2718                 }
2719         }
2720 }
2721
2722 gint64
2723 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
2724 {
2725         gint64 rval;
2726 #ifdef HAVE_ZLIB
2727         if(wdh->compressed) {
2728                 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2729                 return -1;
2730         } else
2731 #endif
2732         {
2733                 if (-1 == (rval = ftell((FILE *)wdh->fh))) {
2734                         *err = errno;
2735                         return -1;
2736                 } else
2737                 {
2738                         return rval;
2739                 }
2740         }
2741 }
2742
2743 /*
2744  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
2745  *
2746  * Local variables:
2747  * c-basic-offset: 8
2748  * tab-width: 8
2749  * indent-tabs-mode: t
2750  * End:
2751  *
2752  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2753  * :indentSize=8:tabSize=8:noTabs=false:
2754  */