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