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