Fix shadow variable warnings.
[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_block_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_block_t));
838         shb = wtap_block_create(WTAP_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_block_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_block_t descr = wtap_block_create(WTAP_BLOCK_IF_DESCR);
1107                 wtapng_if_descr_mandatory_t* descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_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_block_add_uint8_option(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                         /* No need to add an option, this is the default */
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_block_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_block_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_block_t, itf_count);
2194                         file_int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(file_int_data);
2195                         descr = wtap_block_create(WTAP_BLOCK_IF_DESCR);
2196                         wtap_block_copy(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_block_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_block_create(WTAP_BLOCK_IF_DESCR);
2206                 descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_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                 descr_mand->num_stat_entries = 0;          /* Number of ISB:s */
2212                 descr_mand->interface_statistics = NULL;
2213                 wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
2214                 g_array_append_val(wdh->interface_data, descr);
2215         }
2216         return wdh;
2217 }
2218
2219 wtap_dumper *
2220 wtap_dump_open(const char *filename, int file_type_subtype, int encap,
2221                int snaplen, gboolean compressed, int *err)
2222 {
2223         return wtap_dump_open_ng(filename, file_type_subtype, encap,snaplen, compressed, NULL, NULL, NULL, err);
2224 }
2225
2226 wtap_dumper *
2227 wtap_dump_open_ng(const char *filename, int file_type_subtype, int encap,
2228                   int snaplen, gboolean compressed, GArray* shb_hdrs, wtapng_iface_descriptions_t *idb_inf,
2229                   GArray* nrb_hdrs, int *err)
2230 {
2231         wtap_dumper *wdh;
2232         WFILE_T fh;
2233
2234         /* Allocate and initialize a data structure for the output stream. */
2235         wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2236             shb_hdrs, idb_inf, nrb_hdrs, err);
2237         if (wdh == NULL)
2238                 return NULL;
2239
2240         /* In case "fopen()" fails but doesn't set "errno", set "errno"
2241            to a generic "the open failed" error. */
2242         errno = WTAP_ERR_CANT_OPEN;
2243         fh = wtap_dump_file_open(wdh, filename);
2244         if (fh == NULL) {
2245                 *err = errno;
2246                 g_free(wdh);
2247                 return NULL;    /* can't create file */
2248         }
2249         wdh->fh = fh;
2250
2251         if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2252                 /* Get rid of the file we created; we couldn't finish
2253                    opening it. */
2254                 wtap_dump_file_close(wdh);
2255                 ws_unlink(filename);
2256                 g_free(wdh);
2257                 return NULL;
2258         }
2259         return wdh;
2260 }
2261
2262 wtap_dumper *
2263 wtap_dump_open_tempfile(char **filenamep, const char *pfx,
2264                         int file_type_subtype, int encap,
2265                         int snaplen, gboolean compressed, int *err)
2266 {
2267         return wtap_dump_open_tempfile_ng(filenamep, pfx, file_type_subtype, encap,snaplen, compressed, NULL, NULL, NULL, err);
2268 }
2269
2270 wtap_dumper *
2271 wtap_dump_open_tempfile_ng(char **filenamep, const char *pfx,
2272                            int file_type_subtype, int encap,
2273                            int snaplen, gboolean compressed,
2274                            GArray* shb_hdrs,
2275                            wtapng_iface_descriptions_t *idb_inf,
2276                            GArray* nrb_hdrs, int *err)
2277 {
2278         int fd;
2279         char *tmpname;
2280         wtap_dumper *wdh;
2281         WFILE_T fh;
2282
2283         /* No path name for the temporary file yet. */
2284         *filenamep = NULL;
2285
2286         /* Allocate and initialize a data structure for the output stream. */
2287         wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2288             shb_hdrs, idb_inf, nrb_hdrs, err);
2289         if (wdh == NULL)
2290                 return NULL;
2291
2292         /* Choose a random name for the file */
2293         fd = create_tempfile(&tmpname, pfx, ".pcapng");
2294         if (fd == -1) {
2295                 *err = errno;
2296                 g_free(wdh);
2297                 return NULL;    /* can't create file */
2298         }
2299         *filenamep = tmpname;
2300
2301         /* In case "fopen()" fails but doesn't set "errno", set "errno"
2302            to a generic "the open failed" error. */
2303         errno = WTAP_ERR_CANT_OPEN;
2304         fh = wtap_dump_file_fdopen(wdh, fd);
2305         if (fh == NULL) {
2306                 *err = errno;
2307                 ws_close(fd);
2308                 g_free(wdh);
2309                 return NULL;    /* can't create file */
2310         }
2311         wdh->fh = fh;
2312
2313         if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2314                 /* Get rid of the file we created; we couldn't finish
2315                    opening it. */
2316                 wtap_dump_file_close(wdh);
2317                 ws_unlink(tmpname);
2318                 g_free(wdh);
2319                 return NULL;
2320         }
2321         return wdh;
2322 }
2323
2324 wtap_dumper *
2325 wtap_dump_fdopen(int fd, int file_type_subtype, int encap, int snaplen,
2326                  gboolean compressed, int *err)
2327 {
2328         return wtap_dump_fdopen_ng(fd, file_type_subtype, encap, snaplen, compressed, NULL, NULL, NULL, err);
2329 }
2330
2331 wtap_dumper *
2332 wtap_dump_fdopen_ng(int fd, int file_type_subtype, int encap, int snaplen,
2333                     gboolean compressed, GArray* shb_hdrs, wtapng_iface_descriptions_t *idb_inf,
2334                     GArray* nrb_hdrs, int *err)
2335 {
2336         wtap_dumper *wdh;
2337         WFILE_T fh;
2338
2339         /* Allocate and initialize a data structure for the output stream. */
2340         wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2341             shb_hdrs, idb_inf, nrb_hdrs, err);
2342         if (wdh == NULL)
2343                 return NULL;
2344
2345         /* In case "fopen()" fails but doesn't set "errno", set "errno"
2346            to a generic "the open failed" error. */
2347         errno = WTAP_ERR_CANT_OPEN;
2348         fh = wtap_dump_file_fdopen(wdh, fd);
2349         if (fh == NULL) {
2350                 *err = errno;
2351                 g_free(wdh);
2352                 return NULL;    /* can't create standard I/O stream */
2353         }
2354         wdh->fh = fh;
2355
2356         if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2357                 wtap_dump_file_close(wdh);
2358                 g_free(wdh);
2359                 return NULL;
2360         }
2361         return wdh;
2362 }
2363
2364 wtap_dumper *
2365 wtap_dump_open_stdout(int file_type_subtype, int encap, int snaplen,
2366                       gboolean compressed, int *err)
2367 {
2368         return wtap_dump_open_stdout_ng(file_type_subtype, encap, snaplen, compressed, NULL, NULL, NULL, err);
2369 }
2370
2371 wtap_dumper *
2372 wtap_dump_open_stdout_ng(int file_type_subtype, int encap, int snaplen,
2373                          gboolean compressed, GArray* shb_hdrs,
2374                          wtapng_iface_descriptions_t *idb_inf,
2375                          GArray* nrb_hdrs, int *err)
2376 {
2377         wtap_dumper *wdh;
2378         WFILE_T fh;
2379
2380         /* Allocate and initialize a data structure for the output stream. */
2381         wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2382             shb_hdrs, idb_inf, nrb_hdrs, err);
2383         if (wdh == NULL)
2384                 return NULL;
2385
2386 #ifdef _WIN32
2387         /*
2388          * Put the standard output into binary mode.
2389          *
2390          * XXX - even if the file format we're writing is a text
2391          * format?
2392          */
2393         if (_setmode(1, O_BINARY) == -1) {
2394                 /* "Should not happen" */
2395                 *err = errno;
2396                 g_free(wdh);
2397                 return NULL;    /* couldn't put standard output in binary mode */
2398         }
2399 #endif
2400
2401         /* In case "fopen()" fails but doesn't set "errno", set "errno"
2402            to a generic "the open failed" error. */
2403         errno = WTAP_ERR_CANT_OPEN;
2404         fh = wtap_dump_file_fdopen(wdh, 1);
2405         if (fh == NULL) {
2406                 *err = errno;
2407                 g_free(wdh);
2408                 return NULL;    /* can't create standard I/O stream */
2409         }
2410         wdh->fh = fh;
2411         wdh->is_stdout = TRUE;
2412
2413         if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2414                 wtap_dump_file_close(wdh);
2415                 g_free(wdh);
2416                 return NULL;
2417         }
2418         return wdh;
2419 }
2420
2421 static gboolean
2422 wtap_dump_open_check(int file_type_subtype, int encap, gboolean compressed, int *err)
2423 {
2424         if (!wtap_dump_can_open(file_type_subtype)) {
2425                 /* Invalid type, or type we don't know how to write. */
2426                 *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
2427                 return FALSE;
2428         }
2429
2430         /* OK, we know how to write that type; can we write the specified
2431            encapsulation type? */
2432         *err = (*dump_open_table[file_type_subtype].can_write_encap)(encap);
2433         /* if the err said to check wslua's can_write_encap, try that */
2434         if (*err == WTAP_ERR_CHECK_WSLUA
2435                 && dump_open_table[file_type_subtype].wslua_info != NULL
2436                 && dump_open_table[file_type_subtype].wslua_info->wslua_can_write_encap != NULL) {
2437
2438                 *err = (*dump_open_table[file_type_subtype].wslua_info->wslua_can_write_encap)(encap, dump_open_table[file_type_subtype].wslua_info->wslua_data);
2439
2440         }
2441
2442         if (*err != 0)
2443                 return FALSE;
2444
2445         /* if compression is wanted, do we support this for this file_type_subtype? */
2446         if(compressed && !wtap_dump_can_compress(file_type_subtype)) {
2447                 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
2448                 return FALSE;
2449         }
2450
2451         /* All systems go! */
2452         return TRUE;
2453 }
2454
2455 static wtap_dumper *
2456 wtap_dump_alloc_wdh(int file_type_subtype, int encap, int snaplen, gboolean compressed, int *err)
2457 {
2458         wtap_dumper *wdh;
2459
2460         wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
2461         if (wdh == NULL) {
2462                 *err = errno;
2463                 return NULL;
2464         }
2465
2466         wdh->file_type_subtype = file_type_subtype;
2467         wdh->snaplen = snaplen;
2468         wdh->encap = encap;
2469         wdh->compressed = compressed;
2470         wdh->wslua_data = NULL;
2471         return wdh;
2472 }
2473
2474 static gboolean
2475 wtap_dump_open_finish(wtap_dumper *wdh, int file_type_subtype, gboolean compressed, int *err)
2476 {
2477         int fd;
2478         gboolean cant_seek;
2479
2480         /* Can we do a seek on the file descriptor?
2481            If not, note that fact. */
2482         if(compressed) {
2483                 cant_seek = TRUE;
2484         } else {
2485                 fd = ws_fileno((FILE *)wdh->fh);
2486                 if (ws_lseek64(fd, 1, SEEK_CUR) == (off_t) -1)
2487                         cant_seek = TRUE;
2488                 else {
2489                         /* Undo the seek. */
2490                         ws_lseek64(fd, 0, SEEK_SET);
2491                         cant_seek = FALSE;
2492                 }
2493         }
2494
2495         /* If this file type requires seeking, and we can't seek, fail. */
2496         if (dump_open_table[file_type_subtype].writing_must_seek && cant_seek) {
2497                 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
2498                 return FALSE;
2499         }
2500
2501         /* Set wdh with wslua data if any - this is how we pass the data
2502          * to the file writer.
2503          */
2504         if (dump_open_table[file_type_subtype].wslua_info)
2505                 wdh->wslua_data = dump_open_table[file_type_subtype].wslua_info->wslua_data;
2506
2507         /* Now try to open the file for writing. */
2508         if (!(*dump_open_table[file_type_subtype].dump_open)(wdh, err)) {
2509                 return FALSE;
2510         }
2511
2512         return TRUE;    /* success! */
2513 }
2514
2515 gboolean
2516 wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
2517           const guint8 *pd, int *err, gchar **err_info)
2518 {
2519         *err = 0;
2520         *err_info = NULL;
2521         return (wdh->subtype_write)(wdh, phdr, pd, err, err_info);
2522 }
2523
2524 void
2525 wtap_dump_flush(wtap_dumper *wdh)
2526 {
2527 #ifdef HAVE_ZLIB
2528         if(wdh->compressed) {
2529                 gzwfile_flush((GZWFILE_T)wdh->fh);
2530         } else
2531 #endif
2532         {
2533                 fflush((FILE *)wdh->fh);
2534         }
2535 }
2536
2537 gboolean
2538 wtap_dump_close(wtap_dumper *wdh, int *err)
2539 {
2540         gboolean ret = TRUE;
2541
2542         if (wdh->subtype_finish != NULL) {
2543                 /* There's a finish routine for this dump stream. */
2544                 if (!(wdh->subtype_finish)(wdh, err))
2545                         ret = FALSE;
2546         }
2547         errno = WTAP_ERR_CANT_CLOSE;
2548         if (wtap_dump_file_close(wdh) == EOF) {
2549                 if (ret) {
2550                         /* The per-format finish function succeeded,
2551                            but the stream close didn't.  Save the
2552                            reason why, if our caller asked for it. */
2553                         if (err != NULL)
2554                                 *err = errno;
2555                 }
2556                 ret = FALSE;
2557         }
2558         if (wdh->priv != NULL)
2559                 g_free(wdh->priv);
2560         g_free(wdh);
2561         return ret;
2562 }
2563
2564 gint64
2565 wtap_get_bytes_dumped(wtap_dumper *wdh)
2566 {
2567         return wdh->bytes_dumped;
2568 }
2569
2570 void
2571 wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
2572 {
2573         wdh->bytes_dumped = bytes_dumped;
2574 }
2575
2576 gboolean
2577 wtap_dump_set_addrinfo_list(wtap_dumper *wdh, addrinfo_lists_t *addrinfo_lists)
2578 {
2579         if (!wdh || wdh->file_type_subtype < 0 || wdh->file_type_subtype >= wtap_num_file_types_subtypes
2580                 || dump_open_table[wdh->file_type_subtype].has_name_resolution == FALSE)
2581                         return FALSE;
2582         wdh->addrinfo_lists = addrinfo_lists;
2583         return TRUE;
2584 }
2585
2586 /* internally open a file for writing (compressed or not) */
2587 #ifdef HAVE_ZLIB
2588 static WFILE_T
2589 wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
2590 {
2591         if(wdh->compressed) {
2592                 return gzwfile_open(filename);
2593         } else {
2594                 return ws_fopen(filename, "wb");
2595         }
2596 }
2597 #else
2598 static WFILE_T
2599 wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
2600 {
2601         return ws_fopen(filename, "wb");
2602 }
2603 #endif
2604
2605 /* internally open a file for writing (compressed or not) */
2606 #ifdef HAVE_ZLIB
2607 static WFILE_T
2608 wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
2609 {
2610         if(wdh->compressed) {
2611                 return gzwfile_fdopen(fd);
2612         } else {
2613                 return ws_fdopen(fd, "wb");
2614         }
2615 }
2616 #else
2617 static WFILE_T
2618 wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
2619 {
2620         return ws_fdopen(fd, "wb");
2621 }
2622 #endif
2623
2624 /* internally writing raw bytes (compressed or not) */
2625 gboolean
2626 wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize, int *err)
2627 {
2628         size_t nwritten;
2629
2630 #ifdef HAVE_ZLIB
2631         if (wdh->compressed) {
2632                 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned int) bufsize);
2633                 /*
2634                  * gzwfile_write() returns 0 on error.
2635                  */
2636                 if (nwritten == 0) {
2637                         *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
2638                         return FALSE;
2639                 }
2640         } else
2641 #endif
2642         {
2643                 errno = WTAP_ERR_CANT_WRITE;
2644                 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
2645                 /*
2646                  * At least according to the Mac OS X man page,
2647                  * this can return a short count on an error.
2648                  */
2649                 if (nwritten != bufsize) {
2650                         if (ferror((FILE *)wdh->fh))
2651                                 *err = errno;
2652                         else
2653                                 *err = WTAP_ERR_SHORT_WRITE;
2654                         return FALSE;
2655                 }
2656         }
2657         return TRUE;
2658 }
2659
2660 /* internally close a file for writing (compressed or not) */
2661 static int
2662 wtap_dump_file_close(wtap_dumper *wdh)
2663 {
2664 #ifdef HAVE_ZLIB
2665         if(wdh->compressed) {
2666                 /*
2667                  * Tell gzwfile_close() whether to close the descriptor
2668                  * or not.
2669                  */
2670                 return gzwfile_close((GZWFILE_T)wdh->fh, wdh->is_stdout);
2671         } else
2672 #endif
2673         {
2674                 /*
2675                  * Don't close the standard output.
2676                  *
2677                  * XXX - this really should do everything fclose() does,
2678                  * including freeing all allocated data structures,
2679                  * *except* for actually closing the file descriptor.
2680                  */
2681                 return wdh->is_stdout ? fflush((FILE *)wdh->fh) : fclose((FILE *)wdh->fh);
2682         }
2683 }
2684
2685 gint64
2686 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
2687 {
2688 #ifdef HAVE_ZLIB
2689         if(wdh->compressed) {
2690                 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2691                 return -1;
2692         } else
2693 #endif
2694         {
2695                 if (-1 == fseek((FILE *)wdh->fh, (long)offset, whence)) {
2696                         *err = errno;
2697                         return -1;
2698                 } else
2699                 {
2700                         return 0;
2701                 }
2702         }
2703 }
2704
2705 gint64
2706 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
2707 {
2708         gint64 rval;
2709 #ifdef HAVE_ZLIB
2710         if(wdh->compressed) {
2711                 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2712                 return -1;
2713         } else
2714 #endif
2715         {
2716                 if (-1 == (rval = ftell((FILE *)wdh->fh))) {
2717                         *err = errno;
2718                         return -1;
2719                 } else
2720                 {
2721                         return rval;
2722                 }
2723         }
2724 }
2725
2726 /*
2727  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
2728  *
2729  * Local variables:
2730  * c-basic-offset: 8
2731  * tab-width: 8
2732  * indent-tabs-mode: t
2733  * End:
2734  *
2735  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2736  * :indentSize=8:tabSize=8:noTabs=false:
2737  */