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