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