91fcf718b0050e62e5f3cf2acb54410d33f06f88
[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->snap_len = wth->snapshot_length;
1129
1130                 descr_mand->num_stat_entries = 0;          /* Number of ISB:s */
1131                 descr_mand->interface_statistics = NULL;
1132                 g_array_append_val(wth->interface_data, descr);
1133
1134         }
1135         return wth;
1136 }
1137
1138 /*
1139  * Given the pathname of the file we just closed with wtap_fdclose(), attempt
1140  * to reopen that file and assign the new file descriptor(s) to the sequential
1141  * stream and, if do_random is TRUE, to the random stream.  Used on Windows
1142  * after the rename of a file we had open was done or if the rename of a
1143  * file on top of a file we had open failed.
1144  *
1145  * This is only required by Wireshark, not TShark, and, at the point that
1146  * Wireshark is doing this, the sequential stream is closed, and the
1147  * random stream is open, so this refuses to open pipes, and only
1148  * reopens the random stream.
1149  */
1150 gboolean
1151 wtap_fdreopen(wtap *wth, const char *filename, int *err)
1152 {
1153         ws_statb64 statb;
1154
1155         /*
1156          * We need two independent descriptors for random access, so
1157          * they have different file positions.  If we're opening the
1158          * standard input, we can only dup it to get additional
1159          * descriptors, so we can't have two independent descriptors,
1160          * and thus can't do random access.
1161          */
1162         if (strcmp(filename, "-") == 0) {
1163                 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
1164                 return FALSE;
1165         }
1166
1167         /* First, make sure the file is valid */
1168         if (ws_stat64(filename, &statb) < 0) {
1169                 *err = errno;
1170                 return FALSE;
1171         }
1172         if (S_ISFIFO(statb.st_mode)) {
1173                 /*
1174                  * Opens of FIFOs are not allowed; see above.
1175                  */
1176                 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
1177                 return FALSE;
1178         } else if (S_ISDIR(statb.st_mode)) {
1179                 /*
1180                  * Return different errors for "this is a directory"
1181                  * and "this is some random special file type", so
1182                  * the user can get a potentially more helpful error.
1183                  */
1184                 *err = EISDIR;
1185                 return FALSE;
1186         } else if (! S_ISREG(statb.st_mode)) {
1187                 *err = WTAP_ERR_NOT_REGULAR_FILE;
1188                 return FALSE;
1189         }
1190
1191         /* Open the file */
1192         errno = WTAP_ERR_CANT_OPEN;
1193         if (!file_fdreopen(wth->random_fh, filename)) {
1194                 *err = errno;
1195                 return FALSE;
1196         }
1197         return TRUE;
1198 }
1199
1200 /* Table of the file types and subtypes for which we have built-in support.
1201    Entries must be sorted by WTAP_FILE_TYPE_SUBTYPE_xxx values in ascending
1202    order.
1203
1204    These are used to report what type and subtype a given file is and
1205    to let the user select a format when writing out packets.
1206
1207    This table is what we start with, but it can be modified.
1208    If we need to modify it, we allocate a GArray, copy the entries
1209    in the above table to that GArray, use the copy as the table, and
1210    make all changes to the copy. */
1211 static const struct file_type_subtype_info dump_open_table_base[] = {
1212         /* WTAP_FILE_TYPE_SUBTYPE_UNKNOWN (only used internally for initialization) */
1213         { NULL, NULL, NULL, NULL,
1214           FALSE, FALSE, 0,
1215           NULL, NULL, NULL },
1216
1217         /* WTAP_FILE_TYPE_SUBTYPE_PCAP */
1218         /* Gianluca Varenni suggests that we add "deprecated" to the description. */
1219         { "Wireshark/tcpdump/... - pcap", "pcap", "pcap", "cap;dmp",
1220           FALSE, FALSE, 0,
1221           libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1222
1223         /* WTAP_FILE_TYPE_SUBTYPE_PCAPNG */
1224         { "Wireshark/... - pcapng", "pcapng", "pcapng", "ntar",
1225           FALSE, TRUE, WTAP_COMMENT_PER_SECTION|WTAP_COMMENT_PER_INTERFACE|WTAP_COMMENT_PER_PACKET,
1226           pcapng_dump_can_write_encap, pcapng_dump_open, NULL },
1227
1228         /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC */
1229         { "Wireshark/tcpdump/... - nanosecond pcap", "nsecpcap", "pcap", "cap;dmp",
1230           FALSE, FALSE, 0,
1231           libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1232
1233         /* WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX */
1234         { "AIX tcpdump - pcap", "aixpcap", "pcap", "cap;dmp",
1235           FALSE, FALSE, 0,
1236           NULL, NULL, NULL },
1237
1238         /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029 */
1239         { "Modified tcpdump - pcap", "modpcap", "pcap", "cap;dmp",
1240           FALSE, FALSE, 0,
1241           libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1242
1243         /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA */
1244         { "Nokia tcpdump - pcap ", "nokiapcap", "pcap", "cap;dmp",
1245           FALSE, FALSE, 0,
1246           libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1247
1248         /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417 */
1249         { "RedHat 6.1 tcpdump - pcap", "rh6_1pcap", "pcap", "cap;dmp",
1250           FALSE, FALSE, 0,
1251           libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1252
1253         /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915 */
1254         { "SuSE 6.3 tcpdump - pcap", "suse6_3pcap", "pcap", "cap;dmp",
1255           FALSE, FALSE, 0,
1256           libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1257
1258         /* WTAP_FILE_TYPE_SUBTYPE_5VIEWS */
1259         { "InfoVista 5View capture", "5views", "5vw", NULL,
1260            TRUE, FALSE, 0,
1261           _5views_dump_can_write_encap, _5views_dump_open, NULL },
1262
1263         /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_1_0 */
1264         { "AIX iptrace 1.0", "iptrace_1", NULL, NULL,
1265           FALSE, FALSE, 0,
1266           NULL, NULL, NULL },
1267
1268         /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_2_0 */
1269         { "AIX iptrace 2.0", "iptrace_2", NULL, NULL,
1270           FALSE, FALSE, 0,
1271           NULL, NULL, NULL },
1272
1273         /* WTAP_FILE_TYPE_SUBTYPE_BER */
1274         { "ASN.1 Basic Encoding Rules", "ber", NULL, NULL,
1275           FALSE, FALSE, 0,
1276           NULL, NULL, NULL },
1277
1278         /* WTAP_FILE_TYPE_SUBTYPE_HCIDUMP */
1279         { "Bluetooth HCI dump", "hcidump", NULL, NULL,
1280           FALSE, FALSE, 0,
1281           NULL, NULL, NULL },
1282
1283         /* WTAP_FILE_TYPE_SUBTYPE_CATAPULT_DCT2000 */
1284         { "Catapult DCT2000 trace (.out format)", "dct2000", "out", NULL,
1285           FALSE, FALSE, 0,
1286           catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open, NULL },
1287
1288         /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_OLD */
1289         { "Cinco Networks NetXRay 1.x", "netxray1", "cap", NULL,
1290           TRUE, FALSE, 0,
1291           NULL, NULL, NULL },
1292
1293         /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_0 */
1294         { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL,
1295           TRUE, FALSE, 0,
1296           NULL, NULL, NULL },
1297
1298         /* WTAP_FILE_TYPE_SUBTYPE_COSINE */
1299         { "CoSine IPSX L2 capture", "cosine", "txt", NULL,
1300           FALSE, FALSE, 0,
1301           NULL, NULL, NULL },
1302
1303         /* WTAP_FILE_TYPE_SUBTYPE_CSIDS */
1304         { "CSIDS IPLog", "csids", NULL, NULL,
1305           FALSE, FALSE, 0,
1306           NULL, NULL, NULL },
1307
1308         /* WTAP_FILE_TYPE_SUBTYPE_DBS_ETHERWATCH */
1309         { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL,
1310           FALSE, FALSE, 0,
1311           NULL, NULL, NULL },
1312
1313         /* WTAP_FILE_TYPE_SUBTYPE_ERF */
1314         { "Endace ERF capture", "erf", "erf", NULL,
1315           FALSE, FALSE, 0,
1316           erf_dump_can_write_encap, erf_dump_open, NULL },
1317
1318         /* WTAP_FILE_TYPE_SUBTYPE_EYESDN */
1319         { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "trc", NULL,
1320            FALSE, FALSE, 0,
1321            eyesdn_dump_can_write_encap, eyesdn_dump_open, NULL },
1322
1323         /* WTAP_FILE_TYPE_SUBTYPE_NETTL */
1324         { "HP-UX nettl trace", "nettl", "trc0", "trc1",
1325           FALSE, FALSE, 0,
1326           nettl_dump_can_write_encap, nettl_dump_open, NULL },
1327
1328         /* WTAP_FILE_TYPE_SUBTYPE_ISERIES */
1329         { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "txt", NULL,
1330           FALSE, FALSE, 0,
1331           NULL, NULL, NULL },
1332
1333         /* WTAP_FILE_TYPE_SUBTYPE_ISERIES_UNICODE */
1334         { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL,
1335           FALSE, FALSE, 0,
1336           NULL, NULL, NULL },
1337
1338         /* WTAP_FILE_TYPE_SUBTYPE_I4BTRACE */
1339         { "I4B ISDN trace", "i4btrace", NULL, NULL,
1340           FALSE, FALSE, 0,
1341           NULL, NULL, NULL },
1342
1343         /* WTAP_FILE_TYPE_SUBTYPE_ASCEND */
1344         { "Lucent/Ascend access server trace", "ascend", "txt", NULL,
1345           FALSE, FALSE, 0,
1346           NULL, NULL, NULL },
1347
1348         /* WTAP_FILE_TYPE_SUBTYPE_NETMON_1_x */
1349         { "Microsoft NetMon 1.x", "netmon1", "cap", NULL,
1350           TRUE, FALSE, 0,
1351           netmon_dump_can_write_encap_1_x, netmon_dump_open, NULL },
1352
1353         /* WTAP_FILE_TYPE_SUBTYPE_NETMON_2_x */
1354         { "Microsoft NetMon 2.x", "netmon2", "cap", NULL,
1355           TRUE, FALSE, 0,
1356           netmon_dump_can_write_encap_2_x, netmon_dump_open, NULL },
1357
1358         /* WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_UNCOMPRESSED */
1359         { "Sniffer (DOS)", "ngsniffer", "cap", "enc;trc;fdc;syc",
1360           FALSE, FALSE, 0,
1361           ngsniffer_dump_can_write_encap, ngsniffer_dump_open, NULL },
1362
1363         /* WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_COMPRESSED */
1364         { "Sniffer (DOS), compressed", "ngsniffer_comp", "cap", "enc;trc;fdc;syc",
1365           FALSE, FALSE, 0,
1366           NULL, NULL, NULL },
1367
1368         /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_1 */
1369         { "NetXray, Sniffer (Windows) 1.1", "ngwsniffer_1_1", "cap", NULL,
1370           TRUE, FALSE, 0,
1371           netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1, NULL },
1372
1373         /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_2_00x */
1374         { "Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "cap", "caz",
1375           TRUE, FALSE, 0,
1376           netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0, NULL },
1377
1378         /* WTAP_FILE_TYPE_SUBTYPE_NETWORK_INSTRUMENTS */
1379         { "Network Instruments Observer", "niobserver", "bfr", NULL,
1380           FALSE, FALSE, 0,
1381           network_instruments_dump_can_write_encap, network_instruments_dump_open, NULL },
1382
1383         /* WTAP_FILE_TYPE_SUBTYPE_LANALYZER */
1384         { "Novell LANalyzer","lanalyzer", "tr1", NULL,
1385           TRUE, FALSE, 0,
1386           lanalyzer_dump_can_write_encap, lanalyzer_dump_open, NULL },
1387
1388         /* WTAP_FILE_TYPE_SUBTYPE_PPPDUMP */
1389         { "pppd log (pppdump format)", "pppd", NULL, NULL,
1390           FALSE, FALSE, 0,
1391           NULL, NULL, NULL },
1392
1393         /* WTAP_FILE_TYPE_SUBTYPE_RADCOM */
1394         { "RADCOM WAN/LAN analyzer", "radcom", NULL, NULL,
1395           FALSE, FALSE, 0,
1396           NULL, NULL, NULL },
1397
1398         /* WTAP_FILE_TYPE_SUBTYPE_SNOOP */
1399         { "Sun snoop", "snoop", "snoop", "cap",
1400           FALSE, FALSE, 0,
1401           snoop_dump_can_write_encap, snoop_dump_open, NULL },
1402
1403         /* WTAP_FILE_TYPE_SUBTYPE_SHOMITI */
1404         { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL,
1405           FALSE, FALSE, 0,
1406           NULL, NULL, NULL },
1407
1408         /* WTAP_FILE_TYPE_SUBTYPE_VMS */
1409         { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL,
1410           FALSE, FALSE, 0,
1411           NULL, NULL, NULL },
1412
1413         /* WTAP_FILE_TYPE_SUBTYPE_K12 */
1414         { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL,
1415            TRUE, FALSE, 0,
1416            k12_dump_can_write_encap, k12_dump_open, NULL },
1417
1418         /* WTAP_FILE_TYPE_SUBTYPE_TOSHIBA */
1419         { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL,
1420           FALSE, FALSE, 0,
1421           NULL, NULL, NULL },
1422
1423         /* WTAP_FILE_TYPE_SUBTYPE_VISUAL_NETWORKS */
1424         { "Visual Networks traffic capture", "visual", NULL, NULL,
1425           TRUE, FALSE, 0,
1426           visual_dump_can_write_encap, visual_dump_open, NULL },
1427
1428         /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V56 */
1429         { "Savvius classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz",
1430           FALSE, FALSE, 0,
1431           NULL, NULL, NULL },
1432
1433         /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V7 */
1434         { "Savvius classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz",
1435           FALSE, FALSE, 0,
1436           NULL, NULL, NULL },
1437
1438         /* WTAP_FILE_TYPE_SUBTYPE_PEEKTAGGED */
1439         { "Savvius tagged", "peektagged", "pkt", "tpc;apc;wpz",
1440           FALSE, FALSE, 0,
1441           NULL, NULL, NULL },
1442
1443         /* WTAP_FILE_TYPE_SUBTYPE_MPEG */
1444         { "MPEG", "mpeg", "mpeg", "mpg;mp3",
1445           FALSE, FALSE, 0,
1446           NULL, NULL, NULL },
1447
1448         /* WTAP_FILE_TYPE_SUBTYPE_K12TEXT  */
1449         { "K12 text file", "k12text", "txt", NULL,
1450           FALSE, FALSE, 0,
1451           k12text_dump_can_write_encap, k12text_dump_open, NULL },
1452
1453         /* WTAP_FILE_TYPE_SUBTYPE_NETSCREEN */
1454         { "NetScreen snoop text file", "netscreen", "txt", NULL,
1455           FALSE, FALSE, 0,
1456           NULL, NULL, NULL },
1457
1458         /* WTAP_FILE_TYPE_SUBTYPE_COMMVIEW */
1459         { "TamoSoft CommView", "commview", "ncf", NULL,
1460           FALSE, FALSE, 0,
1461           commview_dump_can_write_encap, commview_dump_open, NULL },
1462
1463         /* WTAP_FILE_TYPE_SUBTYPE_BTSNOOP */
1464         { "Symbian OS btsnoop", "btsnoop", "log", NULL,
1465           FALSE, FALSE, 0,
1466           btsnoop_dump_can_write_encap, btsnoop_dump_open_h4, NULL },
1467
1468         /* WTAP_FILE_TYPE_SUBTYPE_TNEF */
1469         { "Transport-Neutral Encapsulation Format", "tnef", NULL, NULL,
1470           FALSE, FALSE, 0,
1471           NULL, NULL, NULL },
1472
1473         /* WTAP_FILE_TYPE_SUBTYPE_DCT3TRACE */
1474         { "Gammu DCT3 trace", "dct3trace", "xml", NULL,
1475           FALSE, FALSE, 0,
1476           NULL, NULL, NULL },
1477
1478         /* WTAP_FILE_TYPE_SUBTYPE_PACKETLOGGER */
1479         { "macOS PacketLogger", "pklg", "pklg", NULL,
1480           FALSE, FALSE, 0,
1481           NULL, NULL, NULL },
1482
1483         /* WTAP_FILE_TYPE_SUBTYPE_DAINTREE_SNA */
1484         { "Daintree SNA", "dsna", "dcf", NULL,
1485           FALSE, FALSE, 0,
1486           NULL, NULL, NULL },
1487
1488         /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0 */
1489         { "NetScaler Trace (Version 1.0)", "nstrace10", NULL, NULL,
1490           TRUE, FALSE, 0,
1491           nstrace_10_dump_can_write_encap, nstrace_dump_open, NULL },
1492
1493         /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0 */
1494         { "NetScaler Trace (Version 2.0)", "nstrace20", "cap", NULL,
1495           TRUE, FALSE, 0,
1496           nstrace_20_dump_can_write_encap, nstrace_dump_open, NULL },
1497
1498         /* WTAP_FILE_TYPE_SUBTYPE_JPEG_JFIF */
1499         { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif",
1500           FALSE, FALSE, 0,
1501           NULL, NULL, NULL },
1502
1503         /* WTAP_FILE_TYPE_SUBTYPE_IPFIX */
1504         { "IPFIX File Format", "ipfix", "pfx", "ipfix",
1505           FALSE, FALSE, 0,
1506           NULL, NULL, NULL },
1507
1508         /* WTAP_ENCAP_MIME */
1509         { "MIME File Format", "mime", NULL, NULL,
1510            FALSE, FALSE, 0,
1511            NULL, NULL, NULL },
1512
1513         /* WTAP_FILE_TYPE_SUBTYPE_AETHRA */
1514         { "Aethra .aps file", "aethra", "aps", NULL,
1515           FALSE, FALSE, 0,
1516           NULL, NULL, NULL },
1517
1518         /* WTAP_FILE_TYPE_SUBTYPE_MPEG_2_TS */
1519         { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg",
1520           FALSE, FALSE, 0,
1521           NULL, NULL, NULL },
1522
1523         /* WTAP_FILE_TYPE_SUBTYPE_VWR_80211 */
1524         { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL,
1525           FALSE, FALSE, 0,
1526           NULL, NULL, NULL },
1527
1528         /* WTAP_FILE_TYPE_SUBTYPE_VWR_ETH */
1529         { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL,
1530           FALSE, FALSE, 0,
1531           NULL, NULL, NULL },
1532
1533         /* WTAP_FILE_TYPE_SUBTYPE_CAMINS */
1534         { "CAM Inspector file", "camins", "camins", NULL,
1535           FALSE, FALSE, 0,
1536           NULL, NULL, NULL },
1537
1538         /* WTAP_FILE_TYPE_SUBTYPE_STANAG_4607 */
1539         { "STANAG 4607 Format", "stanag4607", NULL, NULL,
1540           FALSE, FALSE, 0,
1541           NULL, NULL, NULL },
1542
1543         /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0 */
1544         { "NetScaler Trace (Version 3.0)", "nstrace30", "cap", NULL,
1545           TRUE, FALSE, 0,
1546           nstrace_30_dump_can_write_encap, nstrace_dump_open, NULL },
1547
1548         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT */
1549         { "Android Logcat Binary format", "logcat", "logcat", NULL,
1550           FALSE, FALSE, 0,
1551           logcat_dump_can_write_encap, logcat_binary_dump_open, NULL },
1552
1553         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_BRIEF */
1554         { "Android Logcat Brief text format", "logcat-brief", NULL, NULL,
1555           FALSE, FALSE, 0,
1556           logcat_text_brief_dump_can_write_encap, logcat_text_brief_dump_open, NULL },
1557
1558         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_PROCESS */
1559         { "Android Logcat Process text format", "logcat-process", NULL, NULL,
1560           FALSE, FALSE, 0,
1561           logcat_text_process_dump_can_write_encap, logcat_text_process_dump_open, NULL },
1562
1563         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_TAG */
1564         { "Android Logcat Tag text format", "logcat-tag", NULL, NULL,
1565           FALSE, FALSE, 0,
1566           logcat_text_tag_dump_can_write_encap, logcat_text_tag_dump_open, NULL },
1567
1568         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_THREAD */
1569         { "Android Logcat Thread text format", "logcat-thread", NULL, NULL,
1570            FALSE, FALSE, 0,
1571            logcat_text_thread_dump_can_write_encap, logcat_text_thread_dump_open, NULL },
1572
1573         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_TIME */
1574         { "Android Logcat Time text format", "logcat-time", NULL, NULL,
1575           FALSE, FALSE, 0,
1576           logcat_text_time_dump_can_write_encap, logcat_text_time_dump_open, NULL },
1577
1578         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_THREADTIME */
1579         { "Android Logcat Threadtime text format", "logcat-threadtime", NULL, NULL,
1580           FALSE, FALSE, 0,
1581           logcat_text_threadtime_dump_can_write_encap, logcat_text_threadtime_dump_open, NULL },
1582
1583         /* WTAP_FILE_TYPE_SUBTYPE_LOGCAT_LONG */
1584         { "Android Logcat Long text format", "logcat-long", NULL, NULL,
1585           FALSE, FALSE, 0,
1586           logcat_text_long_dump_can_write_encap, logcat_text_long_dump_open, NULL },
1587
1588         /* WTAP_FILE_TYPE_SUBTYPE_COLASOFT_CAPSA */
1589         { "Colasoft Capsa format", "capsa", "cscpkt", NULL,
1590           FALSE, FALSE, 0,
1591           NULL, NULL, NULL },
1592
1593         /* WTAP_FILE_TYPE_SUBTYPE_COLASOFT_PACKET_BUILDER */
1594         { "Colasoft Packet Builder format", "colasoft-pb", "cscpkt", NULL,
1595           FALSE, FALSE, 0,
1596           NULL, NULL, NULL },
1597
1598         /* WTAP_FILE_TYPE_SUBTYPE_JSON */
1599         { "JavaScript Object Notation", "json", "json", NULL,
1600           FALSE, FALSE, 0,
1601           NULL, NULL, NULL },
1602
1603         /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_5 */
1604         { "NetScaler Trace (Version 3.5)", "nstrace35", "cap", NULL,
1605           TRUE, FALSE, 0,
1606           nstrace_35_dump_can_write_encap, nstrace_dump_open, NULL },
1607
1608         /* WTAP_FILE_TYPE_SUBTYPE_NETTRACE_3GPP_32_423 */
1609         { "3GPP TS 32.423 Trace", "3gpp32423", NULL, NULL,
1610           FALSE, FALSE, 0,
1611           NULL, NULL, NULL },
1612
1613         /* WTAP_FILE_TYPE_MPLOG */
1614         { "Micropross mplog file", "mplog", "mplog", NULL,
1615           FALSE, FALSE, 0,
1616           NULL, NULL, NULL }
1617 };
1618
1619 /*
1620  * Pointer to the table we're currently using.  It's initialized to point
1621  * to the static table, but, if we have to allocate the GArray, it's
1622  * changed to point to the data in the GArray.
1623  */
1624 static const struct file_type_subtype_info* dump_open_table = dump_open_table_base;
1625
1626 /*
1627  * Number of elements in the table we're currently using.  It's initialized
1628  * to the number of elements in the static table, but, if we have to
1629  * allocate the GArray, it's changed to have the size of the GArray.
1630  */
1631 gint wtap_num_file_types_subtypes = sizeof(dump_open_table_base) / sizeof(struct file_type_subtype_info);
1632
1633 /*
1634  * Pointer to the GArray; NULL until it's needed.
1635  */
1636 static GArray*  dump_open_table_arr = NULL;
1637
1638 /*
1639  * Create the GArray from the static table if it hasn't already been created.
1640  */
1641 static void
1642 init_file_types_subtypes_garray(void)
1643 {
1644         if (dump_open_table_arr) return;
1645
1646         dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_subtype_info));
1647
1648         g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types_subtypes);
1649
1650         dump_open_table = (const struct file_type_subtype_info*)(void *)dump_open_table_arr->data;
1651 }
1652
1653 /* if subtype is WTAP_FILE_TYPE_SUBTYPE_UNKNOWN, then create a new subtype as well as register it, else replace the
1654    existing entry in that spot */
1655 int
1656 wtap_register_file_type_subtypes(const struct file_type_subtype_info* fi, const int subtype)
1657 {
1658         struct file_type_subtype_info* finfo;
1659
1660         if (!fi || !fi->name || !fi->short_name || subtype > wtap_num_file_types_subtypes) {
1661                 g_error("no file type info or invalid file type to register");
1662                 return subtype;
1663         }
1664
1665         /* do we want a new registration? */
1666         if (subtype == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) {
1667                 /* register a new one; first verify there isn't one named this already */
1668                 if (wtap_short_string_to_file_type_subtype(fi->short_name) > -1 ) {
1669                         g_error("file type short name already exists");
1670                         return subtype;
1671                 }
1672
1673                 /*
1674                  * Create the GArray if it hasn't already been created.
1675                  */
1676                 init_file_types_subtypes_garray();
1677
1678                 g_array_append_val(dump_open_table_arr,*fi);
1679
1680                 dump_open_table = (const struct file_type_subtype_info*)(void *)dump_open_table_arr->data;
1681
1682                 return wtap_num_file_types_subtypes++;
1683         }
1684
1685         /* re-register an existing one - verify the short names do match (sanity check really) */
1686         if (!dump_open_table[subtype].short_name || strcmp(dump_open_table[subtype].short_name,fi->short_name) != 0) {
1687                 g_error("invalid file type name given to register");
1688                 return subtype;
1689         }
1690
1691         /*
1692          * Create the GArray if it hasn't already been created.
1693          */
1694         init_file_types_subtypes_garray();
1695
1696         /*
1697          * Get the pointer from the GArray, so that we get a non-const
1698          * pointer.
1699          */
1700         finfo = &g_array_index(dump_open_table_arr, struct file_type_subtype_info, subtype);
1701         /*finfo->name = fi->name;*/
1702         /*finfo->short_name = fi->short_name;*/
1703         finfo->default_file_extension     = fi->default_file_extension;
1704         finfo->additional_file_extensions = fi->additional_file_extensions;
1705         finfo->writing_must_seek          = fi->writing_must_seek;
1706         finfo->has_name_resolution        = fi->has_name_resolution;
1707         finfo->supported_comment_types    = fi->supported_comment_types;
1708         finfo->can_write_encap            = fi->can_write_encap;
1709         finfo->dump_open                  = fi->dump_open;
1710         finfo->wslua_info                 = fi->wslua_info;
1711
1712         return subtype;
1713 }
1714
1715 /* De-registers a file writer - they can never be removed from the GArray, but we can "clear" an entry.
1716  */
1717 void
1718 wtap_deregister_file_type_subtype(const int subtype)
1719 {
1720         struct file_type_subtype_info* finfo;
1721
1722         if (subtype < 0 || subtype >= wtap_num_file_types_subtypes) {
1723                 g_error("invalid file type to de-register");
1724                 return;
1725         }
1726
1727         /*
1728          * Create the GArray if it hasn't already been created.
1729          */
1730         init_file_types_subtypes_garray();
1731
1732         /*
1733          * Get the pointer from the GArray, so that we get a non-const
1734          * pointer.
1735          */
1736         finfo = &g_array_index(dump_open_table_arr, struct file_type_subtype_info, subtype);
1737         /* unfortunately, it's not safe to null-out the name or short_name; bunch of other code doesn't guard aainst that, afaict */
1738         /*finfo->name = NULL;*/
1739         /*finfo->short_name = NULL;*/
1740         finfo->default_file_extension = NULL;
1741         finfo->additional_file_extensions = NULL;
1742         finfo->writing_must_seek = FALSE;
1743         finfo->has_name_resolution = FALSE;
1744         finfo->supported_comment_types = 0;
1745         finfo->can_write_encap = NULL;
1746         finfo->dump_open = NULL;
1747         finfo->wslua_info = NULL;
1748 }
1749
1750 int
1751 wtap_get_num_file_types_subtypes(void)
1752 {
1753         return wtap_num_file_types_subtypes;
1754 }
1755
1756 /*
1757  * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
1758  * type that would be needed to write out a file with those types.  If
1759  * there's only one type, it's that type, otherwise it's
1760  * WTAP_ENCAP_PER_PACKET.
1761  */
1762 int
1763 wtap_dump_file_encap_type(const GArray *file_encaps)
1764 {
1765         int encap;
1766
1767         encap = WTAP_ENCAP_PER_PACKET;
1768         if (file_encaps->len == 1) {
1769                 /* OK, use the one-and-only encapsulation type. */
1770                 encap = g_array_index(file_encaps, gint, 0);
1771         }
1772         return encap;
1773 }
1774
1775 static gboolean
1776 wtap_dump_can_write_encap(int filetype, int encap)
1777 {
1778         int result = 0;
1779
1780         if (filetype < 0 || filetype >= wtap_num_file_types_subtypes
1781             || dump_open_table[filetype].can_write_encap == NULL)
1782                 return FALSE;
1783
1784         result = (*dump_open_table[filetype].can_write_encap)(encap);
1785
1786         if (result != 0) {
1787                 /* if the err said to check wslua's can_write_encap, try that */
1788                 if (result == WTAP_ERR_CHECK_WSLUA
1789                         && dump_open_table[filetype].wslua_info != NULL
1790                         && dump_open_table[filetype].wslua_info->wslua_can_write_encap != NULL) {
1791
1792                         result = (*dump_open_table[filetype].wslua_info->wslua_can_write_encap)(encap, dump_open_table[filetype].wslua_info->wslua_data);
1793
1794                 }
1795
1796                 if (result != 0)
1797                         return FALSE;
1798         }
1799
1800         return TRUE;
1801 }
1802
1803 /*
1804  * Return TRUE if a capture with a given GArray of encapsulation types
1805  * and a given bitset of comment types can be written in a specified
1806  * format, and FALSE if it can't.
1807  */
1808 static gboolean
1809 wtap_dump_can_write_format(int ft, const GArray *file_encaps,
1810     guint32 required_comment_types)
1811 {
1812         guint i;
1813
1814         /*
1815          * Can we write in this format?
1816          */
1817         if (!wtap_dump_can_open(ft)) {
1818                 /* No. */
1819                 return FALSE;
1820         }
1821
1822         /*
1823          * Yes.  Can we write out all the required comments in this
1824          * format?
1825          */
1826         if (!wtap_dump_supports_comment_types(ft, required_comment_types)) {
1827                 /* No. */
1828                 return FALSE;
1829         }
1830
1831         /*
1832          * Yes.  Is the required per-file encapsulation type supported?
1833          * This might be WTAP_ENCAP_PER_PACKET.
1834          */
1835         if (!wtap_dump_can_write_encap(ft, wtap_dump_file_encap_type(file_encaps))) {
1836                 /* No. */
1837                 return FALSE;
1838         }
1839
1840         /*
1841          * Yes.  Are all the individual encapsulation types supported?
1842          */
1843         for (i = 0; i < file_encaps->len; i++) {
1844                 if (!wtap_dump_can_write_encap(ft,
1845                     g_array_index(file_encaps, int, i))) {
1846                         /* No - one of them isn't. */
1847                         return FALSE;
1848                 }
1849         }
1850
1851         /* Yes - we're OK. */
1852         return TRUE;
1853 }
1854
1855 /**
1856  * Return TRUE if we can write a file with the given GArray of
1857  * encapsulation types and the given bitmask of comment types.
1858  */
1859 gboolean
1860 wtap_dump_can_write(const GArray *file_encaps, guint32 required_comment_types)
1861 {
1862         int ft;
1863
1864         for (ft = 0; ft < WTAP_NUM_FILE_TYPES_SUBTYPES; ft++) {
1865                 /* To save a file with Wiretap, Wiretap has to handle that format,
1866                  * and its code to handle that format must be able to write a file
1867                  * with this file's encapsulation types.
1868                  */
1869                 if (wtap_dump_can_write_format(ft, file_encaps, required_comment_types)) {
1870                         /* OK, we can write it out in this type. */
1871                         return TRUE;
1872                 }
1873         }
1874
1875         /* No, we couldn't save it in any format. */
1876         return FALSE;
1877 }
1878
1879 /**
1880  * Get a GArray of WTAP_FILE_TYPE_SUBTYPE_ values for file types/subtypes
1881  * that can be used to save a file of a given type/subtype with a given
1882  * GArray of encapsulation types and the given bitmask of comment types.
1883  */
1884 GArray *
1885 wtap_get_savable_file_types_subtypes(int file_type_subtype,
1886     const GArray *file_encaps, guint32 required_comment_types)
1887 {
1888         GArray *savable_file_types_subtypes;
1889         int ft;
1890         int default_file_type_subtype = -1;
1891         int other_file_type_subtype = -1;
1892
1893         /* Can we save this file in its own file type/subtype? */
1894         if (wtap_dump_can_write_format(file_type_subtype, file_encaps,
1895                                        required_comment_types)) {
1896                 /* Yes - make that the default file type/subtype. */
1897                 default_file_type_subtype = file_type_subtype;
1898         } else {
1899                 /* OK, find the first file type/subtype we *can* save it as. */
1900                 default_file_type_subtype = -1;
1901                 for (ft = 0; ft < WTAP_NUM_FILE_TYPES_SUBTYPES; ft++) {
1902                         if (wtap_dump_can_write_format(ft, file_encaps,
1903                                                        required_comment_types)) {
1904                                 /* OK, got it. */
1905                                 default_file_type_subtype = ft;
1906                         }
1907                 }
1908         }
1909
1910         if (default_file_type_subtype == -1) {
1911                 /* We don't support writing this file as any file type/subtype. */
1912                 return NULL;
1913         }
1914
1915         /* Allocate the array. */
1916         savable_file_types_subtypes = g_array_new(FALSE, FALSE, (guint)sizeof (int));
1917
1918         /* Put the default file type/subtype first in the list. */
1919         g_array_append_val(savable_file_types_subtypes, default_file_type_subtype);
1920
1921         /* If the default is pcap, put pcap-NG right after it if we can
1922            also write it in pcap-NG format; otherwise, if the default is
1923            pcap-NG, put pcap right after it if we can also write it in
1924            pcap format. */
1925         if (default_file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP) {
1926                 if (wtap_dump_can_write_format(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, file_encaps,
1927                                                required_comment_types))
1928                         other_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
1929         } else if (default_file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAPNG) {
1930                 if (wtap_dump_can_write_format(WTAP_FILE_TYPE_SUBTYPE_PCAP, file_encaps,
1931                                                required_comment_types))
1932                         other_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAP;
1933         }
1934         if (other_file_type_subtype != -1)
1935                 g_array_append_val(savable_file_types_subtypes, other_file_type_subtype);
1936
1937         /* Add all the other file types/subtypes that work. */
1938         for (ft = 0; ft < WTAP_NUM_FILE_TYPES_SUBTYPES; ft++) {
1939                 if (ft == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN)
1940                         continue;       /* not a real file type */
1941                 if (ft == default_file_type_subtype || ft == other_file_type_subtype)
1942                         continue;       /* we've already done this one */
1943                 if (wtap_dump_can_write_format(ft, file_encaps,
1944                                                required_comment_types)) {
1945                         /* OK, we can write it out in this type. */
1946                         g_array_append_val(savable_file_types_subtypes, ft);
1947                 }
1948         }
1949
1950         return savable_file_types_subtypes;
1951 }
1952
1953 /* Name that should be somewhat descriptive. */
1954 const char *
1955 wtap_file_type_subtype_string(int file_type_subtype)
1956 {
1957         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes) {
1958                 g_error("Unknown capture file type %d", file_type_subtype);
1959                 /** g_error() does an abort() and thus never returns **/
1960                 return "";
1961         } else
1962                 return dump_open_table[file_type_subtype].name;
1963 }
1964
1965 /* Name to use in, say, a command-line flag specifying the type/subtype. */
1966 const char *
1967 wtap_file_type_subtype_short_string(int file_type_subtype)
1968 {
1969         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
1970                 return NULL;
1971         else
1972                 return dump_open_table[file_type_subtype].short_name;
1973 }
1974
1975 /* Translate a short name to a capture file type/subtype. */
1976 int
1977 wtap_short_string_to_file_type_subtype(const char *short_name)
1978 {
1979         int file_type_subtype;
1980
1981         for (file_type_subtype = 0; file_type_subtype < wtap_num_file_types_subtypes; file_type_subtype++) {
1982                 if (dump_open_table[file_type_subtype].short_name != NULL &&
1983                     strcmp(short_name, dump_open_table[file_type_subtype].short_name) == 0)
1984                         return file_type_subtype;
1985         }
1986
1987         /*
1988          * We now call the libpcap file format just pcap, but we allow
1989          * the various variants of it to be specified using names
1990          * containing "libpcap" as well as "pcap", for backwards
1991          * compatibility.
1992          */
1993         if (strcmp(short_name, "libpcap") == 0)
1994                 return WTAP_FILE_TYPE_SUBTYPE_PCAP;
1995         else if (strcmp(short_name, "nseclibpcap") == 0)
1996                 return WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC;
1997         else if (strcmp(short_name, "aixlibpcap") == 0)
1998                 return WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX;
1999         else if (strcmp(short_name, "modlibpcap") == 0)
2000                 return WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029;
2001         else if (strcmp(short_name, "nokialibpcap") == 0)
2002                 return WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA;
2003         else if (strcmp(short_name, "rh6_1libpcap") == 0)
2004                 return WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417;
2005         else if (strcmp(short_name, "suse6_3libpcap") == 0)
2006                 return WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915;
2007
2008         return -1;      /* no such file type, or we can't write it */
2009 }
2010
2011 static GSList *
2012 add_extensions_for_file_type_subtype(int file_type_subtype, GSList *extensions,
2013     const char **compressed_file_extensions)
2014 {
2015         gchar **extensions_set, **extensionp;
2016         gchar *extension;
2017
2018         /*
2019          * Add the default extension, and all compressed variants of
2020          * it.
2021          */
2022         extensions = add_extensions(extensions,
2023             dump_open_table[file_type_subtype].default_file_extension,
2024             compressed_file_extensions);
2025
2026         if (dump_open_table[file_type_subtype].additional_file_extensions != NULL) {
2027                 /*
2028                  * We have additional extensions; add them.
2029                  *
2030                  * First, split the extension-list string into a set of
2031                  * extensions.
2032                  */
2033                 extensions_set = g_strsplit(dump_open_table[file_type_subtype].additional_file_extensions,
2034                     ";", 0);
2035
2036                 /*
2037                  * Add each of those extensions to the list.
2038                  */
2039                 for (extensionp = extensions_set; *extensionp != NULL;
2040                     extensionp++) {
2041                         extension = *extensionp;
2042
2043                         /*
2044                          * Add the extension, and all compressed variants
2045                          * of it.
2046                          */
2047                         extensions = add_extensions(extensions, extension,
2048                             compressed_file_extensions);
2049                 }
2050
2051                 g_strfreev(extensions_set);
2052         }
2053         return extensions;
2054 }
2055
2056 /* Return a list of file extensions that are used by the specified file type.
2057
2058    If include_compressed is TRUE, the list will include compressed
2059    extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
2060    gzipped files.
2061
2062    All strings in the list are allocated with g_malloc() and must be freed
2063    with g_free(). */
2064 GSList *
2065 wtap_get_file_extensions_list(int file_type_subtype, gboolean include_compressed)
2066 {
2067         GSList *extensions;
2068         static const char *no_compressed_extensions[] = {
2069                 NULL
2070         };
2071
2072         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
2073                 return NULL;    /* not a valid file type */
2074
2075         if (dump_open_table[file_type_subtype].default_file_extension == NULL)
2076                 return NULL;    /* valid, but no extensions known */
2077
2078         extensions = NULL;      /* empty list, to start with */
2079
2080         /*
2081          * Add all this file type's extensions, with compressed
2082          * variants if include_compressed is true.
2083          */
2084         extensions = add_extensions_for_file_type_subtype(file_type_subtype, extensions,
2085             include_compressed ? compressed_file_extension_table : no_compressed_extensions);
2086
2087         return extensions;
2088 }
2089
2090 /*
2091  * Free a list returned by wtap_get_file_extension_type_extensions(),
2092  * wtap_get_all_capture_file_extensions_list, or
2093  * wtap_get_file_extensions_list().
2094  */
2095 void
2096 wtap_free_extensions_list(GSList *extensions)
2097 {
2098         GSList *extension;
2099
2100         for (extension = extensions; extension != NULL;
2101             extension = g_slist_next(extension)) {
2102                 g_free(extension->data);
2103         }
2104         g_slist_free(extensions);
2105 }
2106
2107 /* Return the default file extension to use with the specified file type;
2108    that's just the extension, without any ".". */
2109 const char *
2110 wtap_default_file_extension(int file_type_subtype)
2111 {
2112         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
2113                 return NULL;
2114         else
2115                 return dump_open_table[file_type_subtype].default_file_extension;
2116 }
2117
2118 gboolean
2119 wtap_dump_can_open(int file_type_subtype)
2120 {
2121         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
2122             || dump_open_table[file_type_subtype].dump_open == NULL)
2123                 return FALSE;
2124
2125         return TRUE;
2126 }
2127
2128 #ifdef HAVE_ZLIB
2129 gboolean
2130 wtap_dump_can_compress(int file_type_subtype)
2131 {
2132         /*
2133          * If this is an unknown file type, or if we have to
2134          * seek when writing out a file with this file type,
2135          * return FALSE.
2136          */
2137         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
2138             || dump_open_table[file_type_subtype].writing_must_seek)
2139                 return FALSE;
2140
2141         return TRUE;
2142 }
2143 #else
2144 gboolean
2145 wtap_dump_can_compress(int file_type_subtype _U_)
2146 {
2147         return FALSE;
2148 }
2149 #endif
2150
2151 gboolean
2152 wtap_dump_has_name_resolution(int file_type_subtype)
2153 {
2154         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
2155             || dump_open_table[file_type_subtype].has_name_resolution == FALSE)
2156                 return FALSE;
2157
2158         return TRUE;
2159 }
2160
2161 gboolean
2162 wtap_dump_supports_comment_types(int file_type_subtype, guint32 comment_types)
2163 {
2164         guint32 supported_comment_types;
2165
2166         if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
2167                 return FALSE;
2168
2169         supported_comment_types = dump_open_table[file_type_subtype].supported_comment_types;
2170
2171         if ((comment_types & supported_comment_types) == comment_types)
2172                 return TRUE;
2173         return FALSE;
2174 }
2175
2176 static gboolean wtap_dump_open_check(int file_type_subtype, int encap, gboolean comressed, int *err);
2177 static wtap_dumper* wtap_dump_alloc_wdh(int file_type_subtype, int encap, int snaplen,
2178                                         gboolean compressed, int *err);
2179 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int file_type_subtype, gboolean compressed, int *err);
2180
2181 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
2182 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
2183 static int wtap_dump_file_close(wtap_dumper *wdh);
2184
2185 static wtap_dumper *
2186 wtap_dump_init_dumper(int file_type_subtype, int encap, int snaplen, gboolean compressed,
2187                       GArray* shb_hdrs, wtapng_iface_descriptions_t *idb_inf,
2188                       GArray* nrb_hdrs, int *err)
2189 {
2190         wtap_dumper *wdh;
2191         wtap_block_t descr, file_int_data;
2192         wtapng_if_descr_mandatory_t *descr_mand, *file_int_data_mand;
2193
2194         /* Check whether we can open a capture file with that file type
2195            and that encapsulation. */
2196         if (!wtap_dump_open_check(file_type_subtype, encap, compressed, err))
2197                 return NULL;
2198
2199         /* Allocate a data structure for the output stream. */
2200         wdh = wtap_dump_alloc_wdh(file_type_subtype, encap, snaplen, compressed, err);
2201         if (wdh == NULL)
2202                 return NULL;    /* couldn't allocate it */
2203
2204         /* Set Section Header Block data */
2205         wdh->shb_hdrs = shb_hdrs;
2206         /* Set Name Resolution Block data */
2207         wdh->nrb_hdrs = nrb_hdrs;
2208         /* Set Interface Description Block data */
2209         if ((idb_inf != NULL) && (idb_inf->interface_data->len > 0)) {
2210                 guint itf_count;
2211
2212                 /* Note: this memory is owned by wtap_dumper and will become
2213                  * invalid after wtap_dump_close. */
2214                 wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
2215                 for (itf_count = 0; itf_count < idb_inf->interface_data->len; itf_count++) {
2216                         file_int_data = g_array_index(idb_inf->interface_data, wtap_block_t, itf_count);
2217                         file_int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(file_int_data);
2218                         descr = wtap_block_create(WTAP_BLOCK_IF_DESCR);
2219                         wtap_block_copy(descr, file_int_data);
2220                         if ((encap != WTAP_ENCAP_PER_PACKET) && (encap != file_int_data_mand->wtap_encap)) {
2221                                 descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(descr);
2222                                 descr_mand->wtap_encap = encap;
2223                         }
2224                         g_array_append_val(wdh->interface_data, descr);
2225                 }
2226         } else {
2227                 descr = wtap_block_create(WTAP_BLOCK_IF_DESCR);
2228                 descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(descr);
2229                 descr_mand->wtap_encap = encap;
2230                 descr_mand->time_units_per_second = 1000000; /* default microsecond resolution */
2231                 descr_mand->snap_len = snaplen;
2232                 descr_mand->num_stat_entries = 0;          /* Number of ISB:s */
2233                 descr_mand->interface_statistics = NULL;
2234                 wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
2235                 g_array_append_val(wdh->interface_data, descr);
2236         }
2237         return wdh;
2238 }
2239
2240 wtap_dumper *
2241 wtap_dump_open(const char *filename, int file_type_subtype, int encap,
2242                int snaplen, gboolean compressed, int *err)
2243 {
2244         return wtap_dump_open_ng(filename, file_type_subtype, encap,snaplen, compressed, NULL, NULL, NULL, err);
2245 }
2246
2247 wtap_dumper *
2248 wtap_dump_open_ng(const char *filename, int file_type_subtype, int encap,
2249                   int snaplen, gboolean compressed, GArray* shb_hdrs, wtapng_iface_descriptions_t *idb_inf,
2250                   GArray* nrb_hdrs, int *err)
2251 {
2252         wtap_dumper *wdh;
2253         WFILE_T fh;
2254
2255         /* Allocate and initialize a data structure for the output stream. */
2256         wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2257             shb_hdrs, idb_inf, nrb_hdrs, err);
2258         if (wdh == NULL)
2259                 return NULL;
2260
2261         /* In case "fopen()" fails but doesn't set "errno", set "errno"
2262            to a generic "the open failed" error. */
2263         errno = WTAP_ERR_CANT_OPEN;
2264         fh = wtap_dump_file_open(wdh, filename);
2265         if (fh == NULL) {
2266                 *err = errno;
2267                 g_free(wdh);
2268                 return NULL;    /* can't create file */
2269         }
2270         wdh->fh = fh;
2271
2272         if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2273                 /* Get rid of the file we created; we couldn't finish
2274                    opening it. */
2275                 wtap_dump_file_close(wdh);
2276                 ws_unlink(filename);
2277                 g_free(wdh);
2278                 return NULL;
2279         }
2280         return wdh;
2281 }
2282
2283 wtap_dumper *
2284 wtap_dump_open_tempfile(char **filenamep, const char *pfx,
2285                         int file_type_subtype, int encap,
2286                         int snaplen, gboolean compressed, int *err)
2287 {
2288         return wtap_dump_open_tempfile_ng(filenamep, pfx, file_type_subtype, encap,snaplen, compressed, NULL, NULL, NULL, err);
2289 }
2290
2291 wtap_dumper *
2292 wtap_dump_open_tempfile_ng(char **filenamep, const char *pfx,
2293                            int file_type_subtype, int encap,
2294                            int snaplen, gboolean compressed,
2295                            GArray* shb_hdrs,
2296                            wtapng_iface_descriptions_t *idb_inf,
2297                            GArray* nrb_hdrs, int *err)
2298 {
2299         int fd;
2300         char *tmpname;
2301         wtap_dumper *wdh;
2302         WFILE_T fh;
2303
2304         /* No path name for the temporary file yet. */
2305         *filenamep = NULL;
2306
2307         /* Allocate and initialize a data structure for the output stream. */
2308         wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2309             shb_hdrs, idb_inf, nrb_hdrs, err);
2310         if (wdh == NULL)
2311                 return NULL;
2312
2313         /* Choose a random name for the file */
2314         fd = create_tempfile(&tmpname, pfx, ".pcapng");
2315         if (fd == -1) {
2316                 *err = errno;
2317                 g_free(wdh);
2318                 return NULL;    /* can't create file */
2319         }
2320         *filenamep = tmpname;
2321
2322         /* In case "fopen()" fails but doesn't set "errno", set "errno"
2323            to a generic "the open failed" error. */
2324         errno = WTAP_ERR_CANT_OPEN;
2325         fh = wtap_dump_file_fdopen(wdh, fd);
2326         if (fh == NULL) {
2327                 *err = errno;
2328                 ws_close(fd);
2329                 g_free(wdh);
2330                 return NULL;    /* can't create file */
2331         }
2332         wdh->fh = fh;
2333
2334         if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2335                 /* Get rid of the file we created; we couldn't finish
2336                    opening it. */
2337                 wtap_dump_file_close(wdh);
2338                 ws_unlink(tmpname);
2339                 g_free(wdh);
2340                 return NULL;
2341         }
2342         return wdh;
2343 }
2344
2345 wtap_dumper *
2346 wtap_dump_fdopen(int fd, int file_type_subtype, int encap, int snaplen,
2347                  gboolean compressed, int *err)
2348 {
2349         return wtap_dump_fdopen_ng(fd, file_type_subtype, encap, snaplen, compressed, NULL, NULL, NULL, err);
2350 }
2351
2352 wtap_dumper *
2353 wtap_dump_fdopen_ng(int fd, int file_type_subtype, int encap, int snaplen,
2354                     gboolean compressed, GArray* shb_hdrs, wtapng_iface_descriptions_t *idb_inf,
2355                     GArray* nrb_hdrs, int *err)
2356 {
2357         wtap_dumper *wdh;
2358         WFILE_T fh;
2359
2360         /* Allocate and initialize a data structure for the output stream. */
2361         wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2362             shb_hdrs, idb_inf, nrb_hdrs, err);
2363         if (wdh == NULL)
2364                 return NULL;
2365
2366         /* In case "fopen()" fails but doesn't set "errno", set "errno"
2367            to a generic "the open failed" error. */
2368         errno = WTAP_ERR_CANT_OPEN;
2369         fh = wtap_dump_file_fdopen(wdh, fd);
2370         if (fh == NULL) {
2371                 *err = errno;
2372                 g_free(wdh);
2373                 return NULL;    /* can't create standard I/O stream */
2374         }
2375         wdh->fh = fh;
2376
2377         if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2378                 wtap_dump_file_close(wdh);
2379                 g_free(wdh);
2380                 return NULL;
2381         }
2382         return wdh;
2383 }
2384
2385 wtap_dumper *
2386 wtap_dump_open_stdout(int file_type_subtype, int encap, int snaplen,
2387                       gboolean compressed, int *err)
2388 {
2389         return wtap_dump_open_stdout_ng(file_type_subtype, encap, snaplen, compressed, NULL, NULL, NULL, err);
2390 }
2391
2392 wtap_dumper *
2393 wtap_dump_open_stdout_ng(int file_type_subtype, int encap, int snaplen,
2394                          gboolean compressed, GArray* shb_hdrs,
2395                          wtapng_iface_descriptions_t *idb_inf,
2396                          GArray* nrb_hdrs, int *err)
2397 {
2398         int new_fd;
2399         wtap_dumper *wdh;
2400
2401         /*
2402          * Duplicate the file descriptor, so that we can close the
2403          * wtap_dumper handle the same way we close any other
2404          * wtap_dumper handle, without closing the standard output.
2405          */
2406         new_fd = ws_dup(1);
2407         if (new_fd == -1) {
2408                 /* dup failed */
2409                 *err = errno;
2410                 return NULL;
2411         }
2412 #ifdef _WIN32
2413         /*
2414          * Put the new descriptor into binary mode.
2415          *
2416          * XXX - even if the file format we're writing is a text
2417          * format?
2418          */
2419         if (_setmode(new_fd, O_BINARY) == -1) {
2420                 /* "Should not happen" */
2421                 *err = errno;
2422                 ws_close(new_fd);
2423                 return NULL;
2424         }
2425 #endif
2426
2427         wdh = wtap_dump_fdopen_ng(new_fd, file_type_subtype, encap, snaplen,
2428             compressed, shb_hdrs, idb_inf, nrb_hdrs, err);
2429         if (wdh == NULL) {
2430                 /* Failed; close the new FD */
2431                 ws_close(new_fd);
2432                 return NULL;
2433         }
2434         return wdh;
2435 }
2436
2437 static gboolean
2438 wtap_dump_open_check(int file_type_subtype, int encap, gboolean compressed, int *err)
2439 {
2440         if (!wtap_dump_can_open(file_type_subtype)) {
2441                 /* Invalid type, or type we don't know how to write. */
2442                 *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
2443                 return FALSE;
2444         }
2445
2446         /* OK, we know how to write that type; can we write the specified
2447            encapsulation type? */
2448         *err = (*dump_open_table[file_type_subtype].can_write_encap)(encap);
2449         /* if the err said to check wslua's can_write_encap, try that */
2450         if (*err == WTAP_ERR_CHECK_WSLUA
2451                 && dump_open_table[file_type_subtype].wslua_info != NULL
2452                 && dump_open_table[file_type_subtype].wslua_info->wslua_can_write_encap != NULL) {
2453
2454                 *err = (*dump_open_table[file_type_subtype].wslua_info->wslua_can_write_encap)(encap, dump_open_table[file_type_subtype].wslua_info->wslua_data);
2455
2456         }
2457
2458         if (*err != 0)
2459                 return FALSE;
2460
2461         /* if compression is wanted, do we support this for this file_type_subtype? */
2462         if(compressed && !wtap_dump_can_compress(file_type_subtype)) {
2463                 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
2464                 return FALSE;
2465         }
2466
2467         /* All systems go! */
2468         return TRUE;
2469 }
2470
2471 static wtap_dumper *
2472 wtap_dump_alloc_wdh(int file_type_subtype, int encap, int snaplen, gboolean compressed, int *err)
2473 {
2474         wtap_dumper *wdh;
2475
2476         wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
2477         if (wdh == NULL) {
2478                 *err = errno;
2479                 return NULL;
2480         }
2481
2482         wdh->file_type_subtype = file_type_subtype;
2483         wdh->snaplen = snaplen;
2484         wdh->encap = encap;
2485         wdh->compressed = compressed;
2486         wdh->wslua_data = NULL;
2487         return wdh;
2488 }
2489
2490 static gboolean
2491 wtap_dump_open_finish(wtap_dumper *wdh, int file_type_subtype, gboolean compressed, int *err)
2492 {
2493         int fd;
2494         gboolean cant_seek;
2495
2496         /* Can we do a seek on the file descriptor?
2497            If not, note that fact. */
2498         if(compressed) {
2499                 cant_seek = TRUE;
2500         } else {
2501                 fd = ws_fileno((FILE *)wdh->fh);
2502                 if (ws_lseek64(fd, 1, SEEK_CUR) == (off_t) -1)
2503                         cant_seek = TRUE;
2504                 else {
2505                         /* Undo the seek. */
2506                         ws_lseek64(fd, 0, SEEK_SET);
2507                         cant_seek = FALSE;
2508                 }
2509         }
2510
2511         /* If this file type requires seeking, and we can't seek, fail. */
2512         if (dump_open_table[file_type_subtype].writing_must_seek && cant_seek) {
2513                 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
2514                 return FALSE;
2515         }
2516
2517         /* Set wdh with wslua data if any - this is how we pass the data
2518          * to the file writer.
2519          */
2520         if (dump_open_table[file_type_subtype].wslua_info)
2521                 wdh->wslua_data = dump_open_table[file_type_subtype].wslua_info->wslua_data;
2522
2523         /* Now try to open the file for writing. */
2524         if (!(*dump_open_table[file_type_subtype].dump_open)(wdh, err)) {
2525                 return FALSE;
2526         }
2527
2528         return TRUE;    /* success! */
2529 }
2530
2531 gboolean
2532 wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
2533           const guint8 *pd, int *err, gchar **err_info)
2534 {
2535         *err = 0;
2536         *err_info = NULL;
2537         return (wdh->subtype_write)(wdh, phdr, pd, err, err_info);
2538 }
2539
2540 void
2541 wtap_dump_flush(wtap_dumper *wdh)
2542 {
2543 #ifdef HAVE_ZLIB
2544         if(wdh->compressed) {
2545                 gzwfile_flush((GZWFILE_T)wdh->fh);
2546         } else
2547 #endif
2548         {
2549                 fflush((FILE *)wdh->fh);
2550         }
2551 }
2552
2553 gboolean
2554 wtap_dump_close(wtap_dumper *wdh, int *err)
2555 {
2556         gboolean ret = TRUE;
2557
2558         if (wdh->subtype_finish != NULL) {
2559                 /* There's a finish routine for this dump stream. */
2560                 if (!(wdh->subtype_finish)(wdh, err))
2561                         ret = FALSE;
2562         }
2563         errno = WTAP_ERR_CANT_CLOSE;
2564         if (wtap_dump_file_close(wdh) == EOF) {
2565                 if (ret) {
2566                         /* The per-format finish function succeeded,
2567                            but the stream close didn't.  Save the
2568                            reason why, if our caller asked for it. */
2569                         if (err != NULL)
2570                                 *err = errno;
2571                 }
2572                 ret = FALSE;
2573         }
2574         if (wdh->priv != NULL)
2575                 g_free(wdh->priv);
2576         wtap_block_array_free(wdh->interface_data);
2577         g_free(wdh);
2578         return ret;
2579 }
2580
2581 gint64
2582 wtap_get_bytes_dumped(wtap_dumper *wdh)
2583 {
2584         return wdh->bytes_dumped;
2585 }
2586
2587 void
2588 wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
2589 {
2590         wdh->bytes_dumped = bytes_dumped;
2591 }
2592
2593 gboolean
2594 wtap_dump_set_addrinfo_list(wtap_dumper *wdh, addrinfo_lists_t *addrinfo_lists)
2595 {
2596         if (!wdh || wdh->file_type_subtype < 0 || wdh->file_type_subtype >= wtap_num_file_types_subtypes
2597                 || dump_open_table[wdh->file_type_subtype].has_name_resolution == FALSE)
2598                         return FALSE;
2599         wdh->addrinfo_lists = addrinfo_lists;
2600         return TRUE;
2601 }
2602
2603 /* internally open a file for writing (compressed or not) */
2604 #ifdef HAVE_ZLIB
2605 static WFILE_T
2606 wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
2607 {
2608         if(wdh->compressed) {
2609                 return gzwfile_open(filename);
2610         } else {
2611                 return ws_fopen(filename, "wb");
2612         }
2613 }
2614 #else
2615 static WFILE_T
2616 wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
2617 {
2618         return ws_fopen(filename, "wb");
2619 }
2620 #endif
2621
2622 /* internally open a file for writing (compressed or not) */
2623 #ifdef HAVE_ZLIB
2624 static WFILE_T
2625 wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
2626 {
2627         if(wdh->compressed) {
2628                 return gzwfile_fdopen(fd);
2629         } else {
2630                 return ws_fdopen(fd, "wb");
2631         }
2632 }
2633 #else
2634 static WFILE_T
2635 wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
2636 {
2637         return ws_fdopen(fd, "wb");
2638 }
2639 #endif
2640
2641 /* internally writing raw bytes (compressed or not) */
2642 gboolean
2643 wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize, int *err)
2644 {
2645         size_t nwritten;
2646
2647 #ifdef HAVE_ZLIB
2648         if (wdh->compressed) {
2649                 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned int) bufsize);
2650                 /*
2651                  * gzwfile_write() returns 0 on error.
2652                  */
2653                 if (nwritten == 0) {
2654                         *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
2655                         return FALSE;
2656                 }
2657         } else
2658 #endif
2659         {
2660                 errno = WTAP_ERR_CANT_WRITE;
2661                 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
2662                 /*
2663                  * At least according to the macOS man page,
2664                  * this can return a short count on an error.
2665                  */
2666                 if (nwritten != bufsize) {
2667                         if (ferror((FILE *)wdh->fh))
2668                                 *err = errno;
2669                         else
2670                                 *err = WTAP_ERR_SHORT_WRITE;
2671                         return FALSE;
2672                 }
2673         }
2674         return TRUE;
2675 }
2676
2677 /* internally close a file for writing (compressed or not) */
2678 static int
2679 wtap_dump_file_close(wtap_dumper *wdh)
2680 {
2681 #ifdef HAVE_ZLIB
2682         if(wdh->compressed)
2683                 return gzwfile_close((GZWFILE_T)wdh->fh);
2684         else
2685 #endif
2686                 return fclose((FILE *)wdh->fh);
2687 }
2688
2689 gint64
2690 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
2691 {
2692 #ifdef HAVE_ZLIB
2693         if(wdh->compressed) {
2694                 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2695                 return -1;
2696         } else
2697 #endif
2698         {
2699                 if (-1 == fseek((FILE *)wdh->fh, (long)offset, whence)) {
2700                         *err = errno;
2701                         return -1;
2702                 } else
2703                 {
2704                         return 0;
2705                 }
2706         }
2707 }
2708
2709 gint64
2710 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
2711 {
2712         gint64 rval;
2713 #ifdef HAVE_ZLIB
2714         if(wdh->compressed) {
2715                 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2716                 return -1;
2717         } else
2718 #endif
2719         {
2720                 if (-1 == (rval = ftell((FILE *)wdh->fh))) {
2721                         *err = errno;
2722                         return -1;
2723                 } else
2724                 {
2725                         return rval;
2726                 }
2727         }
2728 }
2729
2730 void
2731 cleanup_open_routines(void)
2732 {
2733         guint i;
2734         struct open_info *i_open;
2735
2736         if (open_routines != NULL && open_info_arr) {
2737                 for (i = 0, i_open = open_routines; i < open_info_arr->len; i++, i_open++) {
2738                         if (i_open->extensions != NULL)
2739                                 g_strfreev(i_open->extensions_set);
2740                 }
2741
2742                 g_array_free(open_info_arr, TRUE);
2743                 open_info_arr = NULL;
2744         }
2745 }
2746
2747 /*
2748  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
2749  *
2750  * Local variables:
2751  * c-basic-offset: 8
2752  * tab-width: 8
2753  * indent-tabs-mode: t
2754  * End:
2755  *
2756  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2757  * :indentSize=8:tabSize=8:noTabs=false:
2758  */