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