4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
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.
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.
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.
37 #include <wsutil/file_util.h>
40 #include "file_wrappers.h"
42 #include "lanalyzer.h"
43 #include "ngsniffer.h"
45 #include "ascendtext.h"
58 #include "peekclassic.h"
59 #include "peektagged.h"
61 #include "dbs-etherwatch.h"
68 #include "network_instruments.h"
71 #include "catapult_dct2000.h"
74 #include "netscreen.h"
80 #include "dct3trace.h"
81 #include "packetlogger.h"
82 #include "daintree-sna.h"
83 #include "netscaler.h"
84 #include "mime_file.h"
88 #include "stanag4607.h"
89 #include "pcap-encap.h"
92 * Add an extension, and all compressed versions thereof, to a GSList
95 static GSList *add_extensions(GSList *extensions, const gchar *extension,
96 GSList *compressed_file_extensions)
98 GSList *compressed_file_extension;
101 * Add the specified extension.
103 extensions = g_slist_append(extensions, g_strdup(extension));
106 * Now add the extensions for compressed-file versions of
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));
121 * File types that can be identified by file extensions.
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" },
153 #define N_FILE_TYPE_EXTENSIONS (sizeof file_type_extensions_base / sizeof file_type_extensions_base[0])
155 static const struct file_extension_info* file_type_extensions = NULL;
157 static GArray* file_type_extensions_arr = NULL;
159 /* initialize the extensions array if it has not been initialized yet */
160 static void init_file_type_extensions(void) {
162 if (file_type_extensions_arr) return;
164 file_type_extensions_arr = g_array_new(FALSE,TRUE,sizeof(struct file_extension_info));
166 g_array_append_vals(file_type_extensions_arr,file_type_extensions_base,N_FILE_TYPE_EXTENSIONS);
168 file_type_extensions = (struct file_extension_info*)(void *)file_type_extensions_arr->data;
171 void wtap_register_file_type_extension(const struct file_extension_info *ei) {
172 init_file_type_extensions();
174 g_array_append_val(file_type_extensions_arr,*ei);
176 file_type_extensions = (const struct file_extension_info*)(void *)file_type_extensions_arr->data;
179 int wtap_get_num_file_type_extensions(void)
181 return file_type_extensions_arr->len;
184 const char *wtap_get_file_extension_type_name(int extension_type)
186 return file_type_extensions[extension_type].name;
189 static GSList *add_extensions_for_file_extensions_type(int extension_type,
190 GSList *extensions, GSList *compressed_file_extensions)
192 gchar **extensions_set, **extensionp, *extension;
195 * Split the extension-list string into a set of extensions.
197 extensions_set = g_strsplit(file_type_extensions[extension_type].extensions,
201 * Add each of those extensions to the list.
203 for (extensionp = extensions_set; *extensionp != NULL; extensionp++) {
204 extension = *extensionp;
207 * Add the extension, and all compressed variants
210 extensions = add_extensions(extensions, extension,
211 compressed_file_extensions);
214 g_strfreev(extensions_set);
218 /* Return a list of file extensions that are used by the specified file
221 All strings in the list are allocated with g_malloc() and must be freed
223 GSList *wtap_get_file_extension_type_extensions(guint extension_type)
225 GSList *compressed_file_extensions;
228 if (extension_type >= file_type_extensions_arr->len)
229 return NULL; /* not a valid extension type */
231 extensions = NULL; /* empty list, to start with */
234 * Get the list of compressed-file extensions.
236 compressed_file_extensions = wtap_get_compressed_file_extensions();
239 * Add all this file extension type's extensions, with compressed
242 extensions = add_extensions_for_file_extensions_type(extension_type,
243 extensions, compressed_file_extensions);
245 g_slist_free(compressed_file_extensions);
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.
253 All strings in the list are allocated with g_malloc() and must be freed
255 GSList *wtap_get_all_file_extensions_list(void)
257 GSList *compressed_file_extensions;
261 init_file_type_extensions();
263 extensions = NULL; /* empty list, to start with */
266 * Get the list of compressed-file extensions.
268 compressed_file_extensions = wtap_get_compressed_file_extensions();
270 for (i = 0; i < file_type_extensions_arr->len; i++) {
272 * Add all this file extension type's extensions, with
273 * compressed variants.
275 extensions = add_extensions_for_file_extensions_type(i,
276 extensions, compressed_file_extensions);
279 g_slist_free(compressed_file_extensions);
283 /* The open_file_* routines should return:
285 * -1 on an I/O error;
287 * 1 if the file they're reading is one of the types it handles;
289 * 0 if the file they're reading isn't the type they're checking for.
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.
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)
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.
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 },
327 * PacketLogger must come before MPEG, because its files
328 * are sometimes grabbed by mpeg_open.
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)
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)
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)
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 },
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.
377 #define N_OPEN_INFO_ROUTINES ((sizeof open_info_base / sizeof open_info_base[0]))
379 static GArray *open_info_arr = NULL;
381 /* this always points to the top of the created array */
382 struct open_info *open_routines = NULL;
384 /* this points to the first OPEN_INFO_HEURISTIC type in the array */
385 static guint heuristic_open_routine_idx = 0;
387 static void set_heuristic_routine(void) {
389 g_assert(open_info_arr != NULL);
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;
397 g_assert(open_routines[i].type == OPEN_INFO_MAGIC);
400 g_assert(heuristic_open_routine_idx > 0);
403 void init_open_routines(void) {
405 struct open_info *i_open;
410 open_info_arr = g_array_new(TRUE,TRUE,sizeof(struct open_info));
412 g_array_append_vals(open_info_arr, open_info_base, N_OPEN_INFO_ROUTINES);
414 open_routines = (struct open_info *)(void*) open_info_arr->data;
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);
422 set_heuristic_routine();
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.
430 void wtap_register_open_info(struct open_info *oi, const gboolean first_routine) {
431 init_open_routines();
433 if (!oi || !oi->name) {
434 g_error("No open_info name given to register");
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");
444 if (oi->extensions != NULL)
445 oi->extensions_set = g_strsplit(oi->extensions, ";", 0);
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);
454 g_array_insert_val(open_info_arr, heuristic_open_routine_idx, *oi);
457 open_routines = (struct open_info *)(void*) open_info_arr->data;
458 set_heuristic_routine();
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.
466 void wtap_deregister_open_info(const gchar *name) {
468 init_open_routines();
471 g_error("Missing open_info name to de-register");
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();
485 g_error("deregister_open_info: name not found");
488 /* Determines if a open routine short name already exists
490 gboolean wtap_has_open_info(const gchar *name) {
492 init_open_routines();
495 g_error("No name given to wtap_has_open_info!");
500 for (i = 0; i < open_info_arr->len; i++) {
501 if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) {
510 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
511 * define them either.)
513 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
516 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
519 #define S_IFIFO _S_IFIFO
522 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
525 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
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)
535 init_open_routines();
538 return WTAP_TYPE_AUTO;
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)
546 return WTAP_TYPE_AUTO; /* no such file type */
549 static char *get_file_extension(const char *pathname)
554 GSList *compressed_file_extensions, *compressed_file_extension;
558 * Is the pathname empty?
560 if (strcmp(pathname, "") == 0)
561 return NULL; /* no extension */
564 * Find the last component of the pathname.
566 filename = g_path_get_basename(pathname);
569 * Does it have an extension?
571 if (strchr(filename, '.') == NULL) {
573 return NULL; /* no extension whatsoever */
577 * Yes. Split it into components separated by ".".
579 components = g_strsplit(filename, ".", 0);
583 * Count the components.
585 for (ncomponents = 0; components[ncomponents] != NULL; ncomponents++)
588 if (ncomponents == 0) {
589 g_strfreev(components);
590 return NULL; /* no components */
592 if (ncomponents == 1) {
593 g_strfreev(components);
594 return NULL; /* only one component, with no "." */
598 * Is the last component one of the extensions used for compressed
601 compressed_file_extensions = wtap_get_compressed_file_extensions();
602 if (compressed_file_extensions == NULL) {
604 * We don't support reading compressed files, so just
605 * return a copy of whatever extension we did find.
607 extensionp = g_strdup(components[ncomponents - 1]);
608 g_strfreev(components);
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) {
617 * Yes, it's one of the compressed-file extensions.
618 * Is there an extension before that?
620 if (ncomponents == 2) {
621 g_strfreev(components);
622 return NULL; /* no, only two components */
626 * Yes, return that extension.
628 extensionp = g_strdup(components[ncomponents - 2]);
629 g_strfreev(components);
635 * The extension isn't one of the compressed-file extensions;
638 extensionp = g_strdup(extensionp);
639 g_strfreev(components);
644 * Check if file extension is used in this heuristic
646 static gboolean heuristic_uses_extension(unsigned int i, const char *extension)
651 * Does this file type *have* any extensions?
653 if (open_routines[i].extensions == NULL)
654 return FALSE; /* no */
657 * Check each of them against the specified extension.
659 for (extensionp = open_routines[i].extensions_set; *extensionp != NULL;
661 if (strcmp(extension, *extensionp) == 0) {
662 return TRUE; /* it's one of them */
666 return FALSE; /* it's not one of them */
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,
683 gboolean use_stdin = FALSE;
686 init_open_routines();
688 /* open standard input if filename is '-' */
689 if (strcmp(filename, "-") == 0)
692 /* First, make sure the file is valid */
694 if (ws_fstat64(0, &statb) < 0) {
699 if (ws_stat64(filename, &statb) < 0) {
704 if (S_ISFIFO(statb.st_mode)) {
706 * Opens of FIFOs are allowed only when not opening
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
718 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
721 } else if (S_ISDIR(statb.st_mode)) {
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.
729 } else if (! S_ISREG(statb.st_mode)) {
730 *err = WTAP_ERR_NOT_REGULAR_FILE;
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.
741 if (use_stdin && do_random) {
742 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
747 wth = (wtap *)g_malloc0(sizeof(wtap));
750 errno = WTAP_ERR_CANT_OPEN;
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.
764 if (_setmode(fd, O_BINARY) == -1) {
765 /* "Shouldn't happen" */
771 if (!(wth->fh = file_fdopen(fd))) {
778 if (!(wth->fh = file_open(filename))) {
786 if (!(wth->random_fh = file_open(filename))) {
793 wth->random_fh = NULL;
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;
801 wth->wslua_data = NULL;
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));
808 if (wth->random_fh) {
809 wth->fast_seek = g_ptr_array_new();
811 file_set_random_access(wth->fh, FALSE, wth->fast_seek);
812 file_set_random_access(wth->random_fh, TRUE, wth->fast_seek);
815 /* 'type' is 1 greater than the array index */
816 if (type != WTAP_TYPE_AUTO && type <= open_info_arr->len) {
819 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
820 /* I/O error - give up */
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.
829 wth->wslua_data = open_routines[type - 1].wslua_data;
831 result = (*open_routines[type - 1].open_routine)(wth, err, err_info);
835 /* I/O error - give up */
840 /* No I/O error, but not that type of file */
844 /* We found the file type */
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.
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 */
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.
868 wth->wslua_data = open_routines[i].wslua_data;
870 switch ((*open_routines[i].open_routine)(wth, err, err_info)) {
873 /* I/O error - give up */
878 /* No I/O error, but not that type of file */
882 /* We found the file type */
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)) {
896 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
897 /* I/O error - give up */
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.
906 wth->wslua_data = open_routines[i].wslua_data;
908 switch ((*open_routines[i].open_routine)(wth,
912 /* I/O error - give up */
918 /* No I/O error, but not that type of file */
922 /* We found the file type */
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)) {
934 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
935 /* I/O error - give up */
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.
944 wth->wslua_data = open_routines[i].wslua_data;
946 switch ((*open_routines[i].open_routine)(wth,
950 /* I/O error - give up */
956 /* No I/O error, but not that type of file */
960 /* We found the file type */
968 /* No - try all the heuristics types in order. */
969 for (i = heuristic_open_routine_idx; i < open_info_arr->len; i++) {
971 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
972 /* I/O error - give up */
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.
980 wth->wslua_data = open_routines[i].wslua_data;
982 switch ((*open_routines[i].open_routine)(wth, err, err_info)) {
985 /* I/O error - give up */
990 /* No I/O error, but not that type of file */
994 /* We found the file type */
1002 /* Well, it's not one of the types of file we know about. */
1004 *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
1008 wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
1009 buffer_init(wth->frame_buffer, 1500);
1011 if(wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP){
1013 wtapng_if_descr_t descr;
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;
1023 descr.if_tsresol = 6;
1024 descr.if_filter_str= NULL;
1025 descr.bpf_filter_len= 0;
1026 descr.if_filter_bpf_bytes= 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);
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.
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.
1050 wtap_fdreopen(wtap *wth, const char *filename, int *err)
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.
1061 if (strcmp(filename, "-") == 0) {
1062 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
1066 /* First, make sure the file is valid */
1067 if (ws_stat64(filename, &statb) < 0) {
1071 if (S_ISFIFO(statb.st_mode)) {
1073 * Opens of FIFOs are not allowed; see above.
1075 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
1077 } else if (S_ISDIR(statb.st_mode)) {
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.
1085 } else if (! S_ISREG(statb.st_mode)) {
1086 *err = WTAP_ERR_NOT_REGULAR_FILE;
1091 errno = WTAP_ERR_CANT_OPEN;
1092 if (!file_fdreopen(wth->random_fh, filename)) {
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,
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",
1111 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
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 },
1118 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC */
1119 { "Wireshark - nanosecond libpcap", "nseclibpcap", "pcap", "cap;dmp",
1121 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1123 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX */
1124 { "AIX tcpdump - libpcap", "aixlibpcap", "pcap", "cap;dmp",
1128 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029 */
1129 { "Modified tcpdump - libpcap", "modlibpcap", "pcap", "cap;dmp",
1131 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1133 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA */
1134 { "Nokia tcpdump - libpcap ", "nokialibpcap", "pcap", "cap;dmp",
1136 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1138 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417 */
1139 { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "pcap", "cap;dmp",
1141 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1143 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915 */
1144 { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "pcap", "cap;dmp",
1146 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1148 /* WTAP_FILE_TYPE_SUBTYPE_5VIEWS */
1149 { "InfoVista 5View capture", "5views", "5vw", NULL,
1151 _5views_dump_can_write_encap, _5views_dump_open, NULL },
1153 /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_1_0 */
1154 { "AIX iptrace 1.0", "iptrace_1", NULL, NULL,
1158 /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_2_0 */
1159 { "AIX iptrace 2.0", "iptrace_2", NULL, NULL,
1163 /* WTAP_FILE_TYPE_SUBTYPE_BER */
1164 { "ASN.1 Basic Encoding Rules", "ber", NULL, NULL,
1168 /* WTAP_FILE_TYPE_SUBTYPE_HCIDUMP */
1169 { "Bluetooth HCI dump", "hcidump", NULL, NULL,
1173 /* WTAP_FILE_TYPE_SUBTYPE_CATAPULT_DCT2000 */
1174 { "Catapult DCT2000 trace (.out format)", "dct2000", "out", NULL,
1176 catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open, NULL },
1178 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_OLD */
1179 { "Cinco Networks NetXRay 1.x", "netxray1", "cap", NULL,
1183 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_0 */
1184 { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL,
1188 /* WTAP_FILE_TYPE_SUBTYPE_COSINE */
1189 { "CoSine IPSX L2 capture", "cosine", "txt", NULL,
1193 /* WTAP_FILE_TYPE_SUBTYPE_CSIDS */
1194 { "CSIDS IPLog", "csids", NULL, NULL,
1198 /* WTAP_FILE_TYPE_SUBTYPE_DBS_ETHERWATCH */
1199 { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL,
1203 /* WTAP_FILE_TYPE_SUBTYPE_ERF */
1204 { "Endace ERF capture", "erf", "erf", NULL,
1206 erf_dump_can_write_encap, erf_dump_open, NULL },
1208 /* WTAP_FILE_TYPE_SUBTYPE_EYESDN */
1209 { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "trc", NULL,
1211 eyesdn_dump_can_write_encap, eyesdn_dump_open, NULL },
1213 /* WTAP_FILE_TYPE_SUBTYPE_NETTL */
1214 { "HP-UX nettl trace", "nettl", "trc0", "trc1",
1216 nettl_dump_can_write_encap, nettl_dump_open, NULL },
1218 /* WTAP_FILE_TYPE_SUBTYPE_ISERIES */
1219 { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "txt", NULL,
1223 /* WTAP_FILE_TYPE_SUBTYPE_ISERIES_UNICODE */
1224 { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL,
1228 /* WTAP_FILE_TYPE_SUBTYPE_I4BTRACE */
1229 { "I4B ISDN trace", "i4btrace", NULL, NULL,
1233 /* WTAP_FILE_TYPE_SUBTYPE_ASCEND */
1234 { "Lucent/Ascend access server trace", "ascend", "txt", NULL,
1238 /* WTAP_FILE_TYPE_SUBTYPE_NETMON_1_x */
1239 { "Microsoft NetMon 1.x", "netmon1", "cap", NULL,
1241 netmon_dump_can_write_encap_1_x, netmon_dump_open, NULL },
1243 /* WTAP_FILE_TYPE_SUBTYPE_NETMON_2_x */
1244 { "Microsoft NetMon 2.x", "netmon2", "cap", NULL,
1246 netmon_dump_can_write_encap_2_x, netmon_dump_open, NULL },
1248 /* WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_UNCOMPRESSED */
1249 { "Sniffer (DOS)", "ngsniffer", "cap", "enc;trc;fdc;syc",
1251 ngsniffer_dump_can_write_encap, ngsniffer_dump_open, NULL },
1253 /* WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_COMPRESSED */
1254 { "Sniffer (DOS), compressed", "ngsniffer_comp", "cap", "enc;trc;fdc;syc",
1258 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_1 */
1259 { "NetXray, Sniffer (Windows) 1.1", "ngwsniffer_1_1", "cap", NULL,
1261 netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1, NULL },
1263 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_2_00x */
1264 { "Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "cap", "caz",
1266 netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0, NULL },
1268 /* WTAP_FILE_TYPE_SUBTYPE_NETWORK_INSTRUMENTS */
1269 { "Network Instruments Observer", "niobserver", "bfr", NULL,
1271 network_instruments_dump_can_write_encap, network_instruments_dump_open, NULL },
1273 /* WTAP_FILE_TYPE_SUBTYPE_LANALYZER */
1274 { "Novell LANalyzer","lanalyzer", "tr1", NULL,
1276 lanalyzer_dump_can_write_encap, lanalyzer_dump_open, NULL },
1278 /* WTAP_FILE_TYPE_SUBTYPE_PPPDUMP */
1279 { "pppd log (pppdump format)", "pppd", NULL, NULL,
1283 /* WTAP_FILE_TYPE_SUBTYPE_RADCOM */
1284 { "RADCOM WAN/LAN analyzer", "radcom", NULL, NULL,
1288 /* WTAP_FILE_TYPE_SUBTYPE_SNOOP */
1289 { "Sun snoop", "snoop", "snoop", "cap",
1291 snoop_dump_can_write_encap, snoop_dump_open, NULL },
1293 /* WTAP_FILE_TYPE_SUBTYPE_SHOMITI */
1294 { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL,
1298 /* WTAP_FILE_TYPE_SUBTYPE_VMS */
1299 { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL,
1303 /* WTAP_FILE_TYPE_SUBTYPE_K12 */
1304 { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL,
1306 k12_dump_can_write_encap, k12_dump_open, NULL },
1308 /* WTAP_FILE_TYPE_SUBTYPE_TOSHIBA */
1309 { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL,
1313 /* WTAP_FILE_TYPE_SUBTYPE_VISUAL_NETWORKS */
1314 { "Visual Networks traffic capture", "visual", NULL, NULL,
1316 visual_dump_can_write_encap, visual_dump_open, NULL },
1318 /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V56 */
1319 { "WildPackets classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz",
1323 /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V7 */
1324 { "WildPackets classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz",
1328 /* WTAP_FILE_TYPE_SUBTYPE_PEEKTAGGED */
1329 { "WildPackets tagged", "peektagged", "pkt", "tpc;apc;wpz",
1333 /* WTAP_FILE_TYPE_SUBTYPE_MPEG */
1334 { "MPEG", "mpeg", "mpeg", "mpg;mp3",
1338 /* WTAP_FILE_TYPE_SUBTYPE_K12TEXT */
1339 { "K12 text file", "k12text", "txt", NULL,
1341 k12text_dump_can_write_encap, k12text_dump_open, NULL },
1343 /* WTAP_FILE_TYPE_SUBTYPE_NETSCREEN */
1344 { "NetScreen snoop text file", "netscreen", "txt", NULL,
1348 /* WTAP_FILE_TYPE_SUBTYPE_COMMVIEW */
1349 { "TamoSoft CommView", "commview", "ncf", NULL,
1351 commview_dump_can_write_encap, commview_dump_open, NULL },
1353 /* WTAP_FILE_TYPE_SUBTYPE_BTSNOOP */
1354 { "Symbian OS btsnoop", "btsnoop", "log", NULL,
1356 btsnoop_dump_can_write_encap, btsnoop_dump_open_h4, NULL },
1358 /* WTAP_FILE_TYPE_SUBTYPE_TNEF */
1359 { "Transport-Neutral Encapsulation Format", "tnef", NULL, NULL,
1363 /* WTAP_FILE_TYPE_SUBTYPE_DCT3TRACE */
1364 { "Gammu DCT3 trace", "dct3trace", "xml", NULL,
1368 /* WTAP_FILE_TYPE_SUBTYPE_PACKETLOGGER */
1369 { "PacketLogger", "pklg", "pklg", NULL,
1373 /* WTAP_FILE_TYPE_SUBTYPE_DAINTREE_SNA */
1374 { "Daintree SNA", "dsna", "dcf", NULL,
1378 /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0 */
1379 { "NetScaler Trace (Version 1.0)", "nstrace10", NULL, NULL,
1381 nstrace_10_dump_can_write_encap, nstrace_dump_open, NULL },
1383 /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0 */
1384 { "NetScaler Trace (Version 2.0)", "nstrace20", "cap", NULL,
1386 nstrace_20_dump_can_write_encap, nstrace_dump_open, NULL },
1388 /* WTAP_FILE_TYPE_SUBTYPE_JPEG_JFIF */
1389 { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif",
1393 /* WTAP_FILE_TYPE_SUBTYPE_IPFIX */
1394 { "IPFIX File Format", "ipfix", "pfx", "ipfix",
1398 /* WTAP_ENCAP_MIME */
1399 { "MIME File Format", "mime", NULL, NULL,
1403 /* WTAP_FILE_TYPE_SUBTYPE_AETHRA */
1404 { "Aethra .aps file", "aethra", "aps", NULL,
1408 /* WTAP_FILE_TYPE_SUBTYPE_MPEG_2_TS */
1409 { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg",
1413 /* WTAP_FILE_TYPE_SUBTYPE_VWR_80211 */
1414 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL,
1418 /* WTAP_FILE_TYPE_SUBTYPE_VWR_ETH */
1419 { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL,
1423 /* WTAP_FILE_TYPE_SUBTYPE_CAMINS */
1424 { "CAM Inspector file", "camins", "camins", NULL,
1428 /* WTAP_FILE_TYPE_SUBTYPE_STANAG_4607 */
1429 { "STANAG 4607 Format", "stanag4607", NULL, NULL,
1433 /* WTAP_FILE_NETSCALER_3_0 */
1434 { "NetScaler Trace (Version 3.0)", "nstrace30", "cap", NULL,
1436 nstrace_30_dump_can_write_encap, nstrace_dump_open, NULL },
1438 /* WTAP_FILE_LOGCAT */
1439 { "Android Logcat Binary format", "logcat", "logcat", NULL,
1441 logcat_dump_can_write_encap, logcat_binary_dump_open, NULL },
1442 { "Android Logcat Brief text format", "logcat-brief", NULL, NULL,
1444 logcat_dump_can_write_encap, logcat_text_brief_dump_open, NULL },
1445 { "Android Logcat Process text format", "logcat-process", NULL, NULL,
1447 logcat_dump_can_write_encap, logcat_text_process_dump_open, NULL },
1448 { "Android Logcat Tag text format", "logcat-tag", NULL, NULL,
1450 logcat_dump_can_write_encap, logcat_text_tag_dump_open, NULL },
1451 { "Android Logcat Time text format", "logcat-time", NULL, NULL,
1453 logcat_dump_can_write_encap, logcat_text_time_dump_open, NULL },
1454 { "Android Logcat Thread text format", "logcat-thread", NULL, NULL,
1456 logcat_dump_can_write_encap, logcat_text_thread_dump_open, NULL },
1457 { "Android Logcat Threadtime text format", "logcat-threadtime", NULL, NULL,
1459 logcat_dump_can_write_encap, logcat_text_threadtime_dump_open, NULL },
1460 { "Android Logcat Long text format", "logcat-long", NULL, NULL,
1462 logcat_dump_can_write_encap, logcat_text_long_dump_open, NULL }
1466 gint wtap_num_file_types_subtypes = sizeof(dump_open_table_base) / sizeof(struct file_type_subtype_info);
1468 static GArray* dump_open_table_arr = NULL;
1469 static const struct file_type_subtype_info* dump_open_table = dump_open_table_base;
1471 /* initialize the file types array if it has not being initialized yet */
1472 static void init_file_types_subtypes(void) {
1474 if (dump_open_table_arr) return;
1476 dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_subtype_info));
1478 g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types_subtypes);
1480 dump_open_table = (const struct file_type_subtype_info*)(void *)dump_open_table_arr->data;
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();
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");
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");
1502 g_array_append_val(dump_open_table_arr,*fi);
1504 dump_open_table = (const struct file_type_subtype_info*)(void *)dump_open_table_arr->data;
1506 return wtap_num_file_types_subtypes++;
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");
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;
1531 /* De-registers a file writer - they can never be removed from the GArray, but we can "clear" an entry.
1533 void wtap_deregister_file_type_subtype(const int subtype) {
1534 struct file_type_subtype_info* finfo = NULL;
1536 if (subtype < 0 || subtype >= wtap_num_file_types_subtypes) {
1537 g_error("invalid file type to de-register");
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;
1556 int wtap_get_num_file_types_subtypes(void)
1558 return wtap_num_file_types_subtypes;
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.
1568 wtap_dump_file_encap_type(const GArray *file_encaps)
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);
1581 wtap_dump_can_write_encap(int filetype, int encap)
1585 if (filetype < 0 || filetype >= wtap_num_file_types_subtypes
1586 || dump_open_table[filetype].can_write_encap == NULL)
1589 result = (*dump_open_table[filetype].can_write_encap)(encap);
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) {
1597 result = (*dump_open_table[filetype].wslua_info->wslua_can_write_encap)(encap, dump_open_table[filetype].wslua_info->wslua_data);
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.
1614 wtap_dump_can_write_format(int ft, const GArray *file_encaps,
1615 guint32 required_comment_types)
1620 * Can we write in this format?
1622 if (!wtap_dump_can_open(ft)) {
1628 * Yes. Can we write out all the required comments in this
1631 if (!wtap_dump_supports_comment_types(ft, required_comment_types)) {
1637 * Yes. Is the required per-file encapsulation type supported?
1638 * This might be WTAP_ENCAP_PER_PACKET.
1640 if (!wtap_dump_can_write_encap(ft, wtap_dump_file_encap_type(file_encaps))) {
1646 * Yes. Are all the individual encapsulation types supported?
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. */
1656 /* Yes - we're OK. */
1661 * Return TRUE if we can write a file with the given GArray of
1662 * encapsulation types and the given bitmask of comment types.
1665 wtap_dump_can_write(const GArray *file_encaps, guint32 required_comment_types)
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. */
1679 /* No, we couldn't save it in any format. */
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.
1689 wtap_get_savable_file_types_subtypes(int file_type_subtype,
1690 const GArray *file_encaps, guint32 required_comment_types)
1692 GArray *savable_file_types_subtypes;
1694 int default_file_type_subtype = -1;
1695 int other_file_type_subtype = -1;
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;
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)) {
1709 default_file_type_subtype = ft;
1714 if (default_file_type_subtype == -1) {
1715 /* We don't support writing this file as any file type/subtype. */
1719 /* Allocate the array. */
1720 savable_file_types_subtypes = g_array_new(FALSE, FALSE, (guint)sizeof (int));
1722 /* Put the default file type/subtype first in the list. */
1723 g_array_append_val(savable_file_types_subtypes, default_file_type_subtype);
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
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;
1738 if (other_file_type_subtype != -1)
1739 g_array_append_val(savable_file_types_subtypes, other_file_type_subtype);
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);
1754 return savable_file_types_subtypes;
1757 /* Name that should be somewhat descriptive. */
1758 const char *wtap_file_type_subtype_string(int file_type_subtype)
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 **/
1765 return dump_open_table[file_type_subtype].name;
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)
1771 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
1774 return dump_open_table[file_type_subtype].short_name;
1777 /* Translate a short name to a capture file type/subtype. */
1778 int wtap_short_string_to_file_type_subtype(const char *short_name)
1780 int file_type_subtype;
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;
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.
1793 if (strcmp(short_name, "libpcap") == 0)
1794 return WTAP_FILE_TYPE_SUBTYPE_PCAP;
1796 return -1; /* no such file type, or we can't write it */
1800 add_extensions_for_file_type_subtype(int file_type_subtype, GSList *extensions,
1801 GSList *compressed_file_extensions)
1803 gchar **extensions_set, **extensionp;
1807 * Add the default extension, and all compressed variants of
1810 extensions = add_extensions(extensions,
1811 dump_open_table[file_type_subtype].default_file_extension,
1812 compressed_file_extensions);
1814 if (dump_open_table[file_type_subtype].additional_file_extensions != NULL) {
1816 * We have additional extensions; add them.
1818 * First, split the extension-list string into a set of
1821 extensions_set = g_strsplit(dump_open_table[file_type_subtype].additional_file_extensions,
1825 * Add each of those extensions to the list.
1827 for (extensionp = extensions_set; *extensionp != NULL;
1829 extension = *extensionp;
1832 * Add the extension, and all compressed variants
1835 extensions = add_extensions(extensions, extension,
1836 compressed_file_extensions);
1839 g_strfreev(extensions_set);
1844 /* Return a list of file extensions that are used by the specified file type.
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
1850 All strings in the list are allocated with g_malloc() and must be freed
1852 GSList *wtap_get_file_extensions_list(int file_type_subtype, gboolean include_compressed)
1854 GSList *compressed_file_extensions;
1857 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
1858 return NULL; /* not a valid file type */
1860 if (dump_open_table[file_type_subtype].default_file_extension == NULL)
1861 return NULL; /* valid, but no extensions known */
1863 extensions = NULL; /* empty list, to start with */
1866 * If include_compressions is true, get the list of compressed-file
1869 if (include_compressed)
1870 compressed_file_extensions = wtap_get_compressed_file_extensions();
1872 compressed_file_extensions = NULL;
1875 * Add all this file type's extensions, with compressed
1878 extensions = add_extensions_for_file_type_subtype(file_type_subtype, extensions,
1879 compressed_file_extensions);
1881 g_slist_free(compressed_file_extensions);
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().
1889 void wtap_free_extensions_list(GSList *extensions)
1893 for (extension = extensions; extension != NULL;
1894 extension = g_slist_next(extension)) {
1895 g_free(extension->data);
1897 g_slist_free(extensions);
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)
1904 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
1907 return dump_open_table[file_type_subtype].default_file_extension;
1910 gboolean wtap_dump_can_open(int file_type_subtype)
1912 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
1913 || dump_open_table[file_type_subtype].dump_open == NULL)
1920 gboolean wtap_dump_can_compress(int file_type_subtype)
1923 * If this is an unknown file type, or if we have to
1924 * seek when writing out a file with this file type,
1927 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
1928 || dump_open_table[file_type_subtype].writing_must_seek)
1934 gboolean wtap_dump_can_compress(int file_type_subtype _U_)
1940 gboolean wtap_dump_has_name_resolution(int file_type_subtype)
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)
1949 gboolean wtap_dump_supports_comment_types(int file_type_subtype, guint32 comment_types)
1951 guint32 supported_comment_types;
1953 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
1956 supported_comment_types = dump_open_table[file_type_subtype].supported_comment_types;
1958 if ((comment_types & supported_comment_types) == comment_types)
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);
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);
1972 wtap_dumper* wtap_dump_open(const char *filename, int file_type_subtype, int encap,
1973 int snaplen, gboolean compressed, int *err)
1975 return wtap_dump_open_ng(filename, file_type_subtype, encap,snaplen, compressed, NULL, NULL, err);
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)
1984 /* Allocate a data structure for the output stream. */
1985 wdh = wtap_dump_alloc_wdh(file_type_subtype, encap, snaplen, compressed, err);
1987 return NULL; /* couldn't allocate it */
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;
1995 wtapng_if_descr_t descr;
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;
2005 descr.if_tsresol = 6;
2006 descr.if_filter_str= NULL;
2007 descr.bpf_filter_len= 0;
2008 descr.if_filter_bpf_bytes= 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);
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)
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))
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);
2036 /* "-" means stdout */
2037 if (strcmp(filename, "-") == 0) {
2039 *err = EINVAL; /* XXX - return a Wiretap error code for this */
2041 return NULL; /* compress won't work on stdout */
2044 if (_setmode(fileno(stdout), O_BINARY) == -1) {
2045 /* "Should not happen" */
2048 return NULL; /* couldn't put standard output in binary mode */
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);
2060 return NULL; /* can't create file */
2065 if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2066 /* Get rid of the file we created; we couldn't finish
2068 if (wdh->fh != stdout) {
2069 wtap_dump_file_close(wdh);
2070 ws_unlink(filename);
2078 wtap_dumper* wtap_dump_fdopen(int fd, int file_type_subtype, int encap, int snaplen,
2079 gboolean compressed, int *err)
2081 return wtap_dump_fdopen_ng(fd, file_type_subtype, encap, snaplen, compressed, NULL, NULL, err);
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)
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))
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);
2103 if (_setmode(fileno(stdout), O_BINARY) == -1) {
2104 /* "Should not happen" */
2107 return NULL; /* couldn't put standard output in binary mode */
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);
2119 return NULL; /* can't create standard I/O stream */
2123 if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2124 wtap_dump_file_close(wdh);
2131 static gboolean wtap_dump_open_check(int file_type_subtype, int encap, gboolean compressed, int *err)
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;
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) {
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);
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;
2160 /* All systems go! */
2164 static wtap_dumper* wtap_dump_alloc_wdh(int file_type_subtype, int encap, int snaplen,
2165 gboolean compressed, int *err)
2169 wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
2175 wdh->file_type_subtype = file_type_subtype;
2176 wdh->snaplen = snaplen;
2178 wdh->compressed = compressed;
2179 wdh->wslua_data = NULL;
2183 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int file_type_subtype, gboolean compressed, int *err)
2188 /* Can we do a seek on the file descriptor?
2189 If not, note that fact. */
2193 fd = fileno((FILE *)wdh->fh);
2194 if (lseek(fd, 1, SEEK_CUR) == -1)
2197 /* Undo the seek. */
2198 lseek(fd, 0, SEEK_SET);
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;
2209 /* Set wdh with wslua data if any - this is how we pass the data
2210 * to the file writer.
2212 if (dump_open_table[file_type_subtype].wslua_info)
2213 wdh->wslua_data = dump_open_table[file_type_subtype].wslua_info->wslua_data;
2215 /* Now try to open the file for writing. */
2216 if (!(*dump_open_table[file_type_subtype].dump_open)(wdh, err)) {
2220 return TRUE; /* success! */
2223 gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
2224 const guint8 *pd, int *err)
2226 return (wdh->subtype_write)(wdh, phdr, pd, err);
2229 void wtap_dump_flush(wtap_dumper *wdh)
2232 if(wdh->compressed) {
2233 gzwfile_flush((GZWFILE_T)wdh->fh);
2237 fflush((FILE *)wdh->fh);
2241 gboolean wtap_dump_close(wtap_dumper *wdh, int *err)
2243 gboolean ret = TRUE;
2245 if (wdh->subtype_close != NULL) {
2246 /* There's a close routine for this dump stream. */
2247 if (!(wdh->subtype_close)(wdh, err))
2250 errno = WTAP_ERR_CANT_CLOSE;
2251 /* Don't close stdout */
2252 if (wdh->fh != stdout) {
2253 if (wtap_dump_file_close(wdh) == EOF) {
2255 /* The per-format close function succeeded,
2256 but the fclose didn't. Save the reason
2257 why, if our caller asked for it. */
2264 /* as we don't close stdout, at least try to flush it */
2265 wtap_dump_flush(wdh);
2267 if (wdh->priv != NULL)
2273 gint64 wtap_get_bytes_dumped(wtap_dumper *wdh)
2275 return wdh->bytes_dumped;
2278 void wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
2280 wdh->bytes_dumped = bytes_dumped;
2283 gboolean wtap_dump_set_addrinfo_list(wtap_dumper *wdh, addrinfo_lists_t *addrinfo_lists)
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)
2288 wdh->addrinfo_lists = addrinfo_lists;
2292 /* internally open a file for writing (compressed or not) */
2294 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
2296 if(wdh->compressed) {
2297 return gzwfile_open(filename);
2299 return ws_fopen(filename, "wb");
2303 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
2305 return ws_fopen(filename, "wb");
2309 /* internally open a file for writing (compressed or not) */
2311 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
2313 if(wdh->compressed) {
2314 return gzwfile_fdopen(fd);
2316 return fdopen(fd, "wb");
2320 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
2322 return fdopen(fd, "wb");
2326 /* internally writing raw bytes (compressed or not) */
2327 gboolean wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize,
2333 if (wdh->compressed) {
2334 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned int) bufsize);
2336 * gzwfile_write() returns 0 on error.
2338 if (nwritten == 0) {
2339 *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
2345 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
2347 * At least according to the Mac OS X man page,
2348 * this can return a short count on an error.
2350 if (nwritten != bufsize) {
2351 if (ferror((FILE *)wdh->fh))
2354 *err = WTAP_ERR_SHORT_WRITE;
2361 /* internally close a file for writing (compressed or not) */
2362 static int wtap_dump_file_close(wtap_dumper *wdh)
2365 if(wdh->compressed) {
2366 return gzwfile_close((GZWFILE_T)wdh->fh);
2370 return fclose((FILE *)wdh->fh);
2374 gint64 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
2377 if(wdh->compressed) {
2378 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2383 if (-1 == fseek((FILE *)wdh->fh, (long)offset, whence)) {
2392 gint64 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
2396 if(wdh->compressed) {
2397 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2402 if (-1 == (rval = ftell((FILE *)wdh->fh))) {