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