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"
41 #include <wsutil/buffer.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 "logcat_text.h"
69 #include "network_instruments.h"
72 #include "catapult_dct2000.h"
75 #include "netscreen.h"
81 #include "dct3trace.h"
82 #include "packetlogger.h"
83 #include "daintree-sna.h"
84 #include "netscaler.h"
85 #include "mime_file.h"
89 #include "stanag4607.h"
90 #include "pcap-encap.h"
93 * Add an extension, and all compressed versions thereof, to a GSList
97 add_extensions(GSList *extensions, const gchar *extension,
98 GSList *compressed_file_extensions)
100 GSList *compressed_file_extension;
103 * Add the specified extension.
105 extensions = g_slist_append(extensions, g_strdup(extension));
108 * Now add the extensions for compressed-file versions of
111 for (compressed_file_extension = compressed_file_extensions;
112 compressed_file_extension != NULL;
113 compressed_file_extension = g_slist_next(compressed_file_extension)) {
114 extensions = g_slist_append(extensions,
115 g_strdup_printf("%s.%s", extension,
116 (gchar *)compressed_file_extension->data));
123 * File types that can be identified by file extensions.
125 static const struct file_extension_info file_type_extensions_base[] = {
126 { "Wireshark/tcpdump/... - pcap", "pcap;cap;dmp" },
127 { "Wireshark/... - pcapng", "pcapng;ntar" },
128 { "Network Monitor, Surveyor, NetScaler", "cap" },
129 { "InfoVista 5View capture", "5vw" },
130 { "Sniffer (DOS)", "cap;enc;trc;fdc;syc" },
131 { "NetXRay, Sniffer (Windows)", "cap;caz" },
132 { "Endace ERF capture", "erf" },
133 { "EyeSDN USB S0/E1 ISDN trace format", "trc" },
134 { "HP-UX nettl trace", "trc0;trc1" },
135 { "Network Instruments Observer", "bfr" },
136 { "Novell LANalyzer", "tr1" },
137 { "Tektronix K12xx 32-bit .rf5 format", "rf5" },
138 { "WildPackets *Peek", "pkt;tpc;apc;wpz" },
139 { "Catapult DCT2000 trace (.out format)", "out" },
140 { "MPEG files", "mpg;mp3" },
141 { "CommView", "ncf" },
142 { "Symbian OS btsnoop", "log" },
143 { "Transport-Neutral Encapsulation Format", "tnef" },
144 { "XML files (including Gammu DCT3 traces)", "xml" },
145 { "OS X PacketLogger", "pklg" },
146 { "Daintree SNA", "dcf" },
147 { "JPEG/JFIF files", "jpg;jpeg;jfif" },
148 { "IPFIX File Format", "pfx;ipfix" },
149 { "Aethra .aps file", "aps" },
150 { "MPEG2 transport stream", "mp2t;ts;mpg" },
151 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr" },
152 { "CAM Inspector file", "camins" },
155 #define N_FILE_TYPE_EXTENSIONS (sizeof file_type_extensions_base / sizeof file_type_extensions_base[0])
157 static const struct file_extension_info* file_type_extensions = NULL;
159 static GArray* file_type_extensions_arr = NULL;
161 /* initialize the extensions array if it has not been initialized yet */
163 init_file_type_extensions(void)
166 if (file_type_extensions_arr) return;
168 file_type_extensions_arr = g_array_new(FALSE,TRUE,sizeof(struct file_extension_info));
170 g_array_append_vals(file_type_extensions_arr,file_type_extensions_base,N_FILE_TYPE_EXTENSIONS);
172 file_type_extensions = (struct file_extension_info*)(void *)file_type_extensions_arr->data;
176 wtap_register_file_type_extension(const struct file_extension_info *ei)
178 init_file_type_extensions();
180 g_array_append_val(file_type_extensions_arr,*ei);
182 file_type_extensions = (const struct file_extension_info*)(void *)file_type_extensions_arr->data;
186 wtap_get_num_file_type_extensions(void)
188 return file_type_extensions_arr->len;
192 wtap_get_file_extension_type_name(int extension_type)
194 return file_type_extensions[extension_type].name;
198 add_extensions_for_file_extensions_type(int extension_type,
199 GSList *extensions, GSList *compressed_file_extensions)
201 gchar **extensions_set, **extensionp, *extension;
204 * Split the extension-list string into a set of extensions.
206 extensions_set = g_strsplit(file_type_extensions[extension_type].extensions,
210 * Add each of those extensions to the list.
212 for (extensionp = extensions_set; *extensionp != NULL; extensionp++) {
213 extension = *extensionp;
216 * Add the extension, and all compressed variants
219 extensions = add_extensions(extensions, extension,
220 compressed_file_extensions);
223 g_strfreev(extensions_set);
227 /* Return a list of file extensions that are used by the specified file
230 All strings in the list are allocated with g_malloc() and must be freed
233 wtap_get_file_extension_type_extensions(guint extension_type)
235 GSList *compressed_file_extensions;
238 if (extension_type >= file_type_extensions_arr->len)
239 return NULL; /* not a valid extension type */
241 extensions = NULL; /* empty list, to start with */
244 * Get the list of compressed-file extensions.
246 compressed_file_extensions = wtap_get_compressed_file_extensions();
249 * Add all this file extension type's extensions, with compressed
252 extensions = add_extensions_for_file_extensions_type(extension_type,
253 extensions, compressed_file_extensions);
255 g_slist_free(compressed_file_extensions);
259 /* Return a list of all extensions that are used by all file types,
260 including compressed extensions, e.g. not just "pcap" but also
261 "pcap.gz" if we can read gzipped files.
263 All strings in the list are allocated with g_malloc() and must be freed
266 wtap_get_all_file_extensions_list(void)
268 GSList *compressed_file_extensions;
272 init_file_type_extensions();
274 extensions = NULL; /* empty list, to start with */
277 * Get the list of compressed-file extensions.
279 compressed_file_extensions = wtap_get_compressed_file_extensions();
281 for (i = 0; i < file_type_extensions_arr->len; i++) {
283 * Add all this file extension type's extensions, with
284 * compressed variants.
286 extensions = add_extensions_for_file_extensions_type(i,
287 extensions, compressed_file_extensions);
290 g_slist_free(compressed_file_extensions);
295 * The open_file_* routines should return:
297 * -1 on an I/O error;
299 * 1 if the file they're reading is one of the types it handles;
301 * 0 if the file they're reading isn't the type they're checking for.
303 * If the routine handles this type of file, it should set the "file_type"
304 * field in the "struct wtap" to the type of the file.
306 * Note that the routine does not have to free the private data pointer on
307 * error. The caller takes care of that by calling wtap_close on error.
308 * (See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8518)
310 * However, the caller does have to free the private data pointer when
311 * returning 0, since the next file type will be called and will likely
312 * just overwrite the pointer.
314 static struct open_info open_info_base[] = {
315 { "Pcap", OPEN_INFO_MAGIC, libpcap_open, "pcap", NULL, NULL },
316 { "PcapNG", OPEN_INFO_MAGIC, pcapng_open, "pcapng", NULL, NULL },
317 { "NgSniffer", OPEN_INFO_MAGIC, ngsniffer_open, NULL, NULL, NULL },
318 { "Snoop", OPEN_INFO_MAGIC, snoop_open, NULL, NULL, NULL },
319 { "IP Trace", OPEN_INFO_MAGIC, iptrace_open, NULL, NULL, NULL },
320 { "Netmon", OPEN_INFO_MAGIC, netmon_open, NULL, NULL, NULL },
321 { "Netxray", OPEN_INFO_MAGIC, netxray_open, NULL, NULL, NULL },
322 { "Radcom", OPEN_INFO_MAGIC, radcom_open, NULL, NULL, NULL },
323 { "Nettl", OPEN_INFO_MAGIC, nettl_open, NULL, NULL, NULL },
324 { "Visual", OPEN_INFO_MAGIC, visual_open, NULL, NULL, NULL },
325 { "5 Views", OPEN_INFO_MAGIC, _5views_open, NULL, NULL, NULL },
326 { "Network Instruments", OPEN_INFO_MAGIC, network_instruments_open, NULL, NULL, NULL },
327 { "Peek Tagged", OPEN_INFO_MAGIC, peektagged_open, NULL, NULL, NULL },
328 { "DBS Etherwatch", OPEN_INFO_MAGIC, dbs_etherwatch_open, NULL, NULL, NULL },
329 { "K12", OPEN_INFO_MAGIC, k12_open, NULL, NULL, NULL },
330 { "Catapult DCT 2000", OPEN_INFO_MAGIC, catapult_dct2000_open, NULL, NULL, NULL },
331 { "Aethra", OPEN_INFO_MAGIC, aethra_open, NULL, NULL, NULL },
332 { "BTSNOOP", OPEN_INFO_MAGIC, btsnoop_open, "log", NULL, NULL },
333 { "EYESDN", OPEN_INFO_MAGIC, eyesdn_open, NULL, NULL, NULL },
334 { "TNEF", OPEN_INFO_MAGIC, tnef_open, NULL, NULL, NULL },
335 { "MIME Files with Magic Bytes", OPEN_INFO_MAGIC, mime_file_open, NULL, NULL, NULL },
336 { "Lanalyzer", OPEN_INFO_HEURISTIC, lanalyzer_open, "tr1", NULL, NULL },
338 * PacketLogger must come before MPEG, because its files
339 * are sometimes grabbed by mpeg_open.
341 { "Packet Logger", OPEN_INFO_HEURISTIC, packetlogger_open, "pklg", NULL, NULL },
342 /* Some MPEG files have magic numbers, others just have heuristics. */
343 { "Mpeg", OPEN_INFO_HEURISTIC, mpeg_open, "mpg;mp3", NULL, NULL },
344 { "DCT3 Trace", OPEN_INFO_HEURISTIC, dct3trace_open, "xml", NULL, NULL },
345 { "Daintree SNA", OPEN_INFO_HEURISTIC, daintree_sna_open, "dcf", NULL, NULL },
346 { "Stanag 4607", OPEN_INFO_HEURISTIC, stanag4607_open, NULL, NULL, NULL },
347 { "BER", OPEN_INFO_HEURISTIC, ber_open, NULL, NULL, NULL },
349 * I put NetScreen *before* erf, because there were some
350 * false positives with my test-files (Sake Blok, July 2007)
352 * I put VWR *after* ERF, because there were some cases where
353 * ERF files were misidentified as vwr files (Stephen
354 * Donnelly, August 2013; see bug 9054)
356 * I put VWR *after* Peek Classic, CommView, iSeries text,
357 * Toshiba text, K12 text, VMS tcpiptrace text, and NetScaler,
358 * because there were some cases where files of those types were
359 * misidentified as vwr files (Guy Harris, December 2013)
361 { "Netscreen", OPEN_INFO_HEURISTIC, netscreen_open, "txt", NULL, NULL },
362 { "ERF", OPEN_INFO_HEURISTIC, erf_open, "erf", NULL, NULL },
363 { "IPfix", OPEN_INFO_HEURISTIC, ipfix_open, "pfx;ipfix",NULL, NULL },
364 { "K12 Text", OPEN_INFO_HEURISTIC, k12text_open, "txt", NULL, NULL },
365 { "Peek Classic", OPEN_INFO_HEURISTIC, peekclassic_open, "pkt;tpc;apc;wpz", NULL, NULL },
366 { "PPP Dump", OPEN_INFO_HEURISTIC, pppdump_open, NULL, NULL, NULL },
367 { "iSeries", OPEN_INFO_HEURISTIC, iseries_open, "txt", NULL, NULL },
368 { "i4btrace", OPEN_INFO_HEURISTIC, i4btrace_open, NULL, NULL, NULL },
369 { "Mp2t", OPEN_INFO_HEURISTIC, mp2t_open, "ts;mpg", NULL, NULL },
370 { "Csids", OPEN_INFO_HEURISTIC, csids_open, NULL, NULL, NULL },
371 { "VMS", OPEN_INFO_HEURISTIC, vms_open, "txt", NULL, NULL },
372 { "Cosine", OPEN_INFO_HEURISTIC, cosine_open, "txt", NULL, NULL },
373 { "Hcidump", OPEN_INFO_HEURISTIC, hcidump_open, NULL, NULL, NULL },
374 { "Commview", OPEN_INFO_HEURISTIC, commview_open, "ncf", NULL, NULL },
375 { "Nstrace", OPEN_INFO_HEURISTIC, nstrace_open, "cap", NULL, NULL },
376 { "Logcat ", OPEN_INFO_HEURISTIC, logcat_open, "logcat", NULL, NULL },
377 { "Logcat Text", OPEN_INFO_HEURISTIC, logcat_text_open, "txt", NULL, NULL },
378 /* ASCII trace files from Telnet sessions. */
379 { "Ascend", OPEN_INFO_HEURISTIC, ascend_open, "txt", NULL, NULL },
380 { "Toshiba", OPEN_INFO_HEURISTIC, toshiba_open, "txt", NULL, NULL },
381 /* Extremely weak heuristics - put them at the end. */
382 { "VWR", OPEN_INFO_HEURISTIC, vwr_open, "vwr", NULL, NULL },
383 { "Camins", OPEN_INFO_HEURISTIC, camins_open, "camins", NULL, NULL },
386 /* this is only used to build the dynamic array on load, do NOT use this
387 * for anything else, because the size of the actual array will change if
388 * Lua scripts register a new file reader.
390 #define N_OPEN_INFO_ROUTINES ((sizeof open_info_base / sizeof open_info_base[0]))
392 static GArray *open_info_arr = NULL;
394 /* this always points to the top of the created array */
395 struct open_info *open_routines = NULL;
397 /* this points to the first OPEN_INFO_HEURISTIC type in the array */
398 static guint heuristic_open_routine_idx = 0;
401 set_heuristic_routine(void)
404 g_assert(open_info_arr != NULL);
406 for (i = 0; i < open_info_arr->len; i++) {
407 if (open_routines[i].type == OPEN_INFO_HEURISTIC) {
408 heuristic_open_routine_idx = i;
412 g_assert(open_routines[i].type == OPEN_INFO_MAGIC);
415 g_assert(heuristic_open_routine_idx > 0);
419 init_open_routines(void)
422 struct open_info *i_open;
427 open_info_arr = g_array_new(TRUE,TRUE,sizeof(struct open_info));
429 g_array_append_vals(open_info_arr, open_info_base, N_OPEN_INFO_ROUTINES);
431 open_routines = (struct open_info *)(void*) open_info_arr->data;
433 /* Populate the extensions_set list now */
434 for (i = 0, i_open = open_routines; i < open_info_arr->len; i++, i_open++) {
435 if (i_open->extensions != NULL)
436 i_open->extensions_set = g_strsplit(i_open->extensions, ";", 0);
439 set_heuristic_routine();
443 * Registers a new file reader - currently only called by wslua code for Lua readers.
444 * If first_routine is true, it's added before other readers of its type (magic or heuristic).
445 * Also, it checks for an existing reader of the same name and errors if it finds one; if
446 * you want to handle that condition more gracefully, call wtap_has_open_info() first.
449 wtap_register_open_info(struct open_info *oi, const gboolean first_routine)
451 init_open_routines();
453 if (!oi || !oi->name) {
454 g_error("No open_info name given to register");
458 /* verify name doesn't already exist */
459 if (wtap_has_open_info(oi->name)) {
460 g_error("Name given to register_open_info already exists");
464 if (oi->extensions != NULL)
465 oi->extensions_set = g_strsplit(oi->extensions, ";", 0);
467 /* if it's magic and first, prepend it; if it's heuristic and not first,
468 append it; if it's anything else, stick it in the middle */
469 if (first_routine && oi->type == OPEN_INFO_MAGIC) {
470 g_array_prepend_val(open_info_arr, *oi);
471 } else if (!first_routine && oi->type == OPEN_INFO_HEURISTIC) {
472 g_array_append_val(open_info_arr, *oi);
474 g_array_insert_val(open_info_arr, heuristic_open_routine_idx, *oi);
477 open_routines = (struct open_info *)(void*) open_info_arr->data;
478 set_heuristic_routine();
481 /* De-registers a file reader by removign it from the GArray based on its name.
482 * This function must NOT be called during wtap_open_offline(), since it changes the array.
483 * Note: this function will error if it doesn't find the given name; if you want to handle
484 * that condition more gracefully, call wtap_has_open_info() first.
487 wtap_deregister_open_info(const gchar *name)
490 init_open_routines();
493 g_error("Missing open_info name to de-register");
497 for (i = 0; i < open_info_arr->len; i++) {
498 if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) {
499 if (open_routines[i].extensions_set != NULL)
500 g_strfreev(open_routines[i].extensions_set);
501 open_info_arr = g_array_remove_index(open_info_arr, i);
502 set_heuristic_routine();
507 g_error("deregister_open_info: name not found");
510 /* Determines if a open routine short name already exists
513 wtap_has_open_info(const gchar *name)
516 init_open_routines();
519 g_error("No name given to wtap_has_open_info!");
524 for (i = 0; i < open_info_arr->len; i++) {
525 if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) {
534 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
535 * define them either.)
537 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
540 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
543 #define S_IFIFO _S_IFIFO
546 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
549 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
552 /* returns the 'type' number to use for wtap_open_offline based on the
553 passed-in name (the name in the open_info struct). It returns WTAP_TYPE_AUTO
554 on failure, which is the number 0. The 'type' number is the entry's index+1,
555 because that's what wtap_open_offline() expects it to be. */
557 open_info_name_to_type(const char *name)
560 init_open_routines();
563 return WTAP_TYPE_AUTO;
565 for (i = 0; i < open_info_arr->len; i++) {
566 if (open_routines[i].name != NULL &&
567 strcmp(name, open_routines[i].name) == 0)
571 return WTAP_TYPE_AUTO; /* no such file type */
575 get_file_extension(const char *pathname)
580 GSList *compressed_file_extensions, *compressed_file_extension;
584 * Is the pathname empty?
586 if (strcmp(pathname, "") == 0)
587 return NULL; /* no extension */
590 * Find the last component of the pathname.
592 filename = g_path_get_basename(pathname);
595 * Does it have an extension?
597 if (strchr(filename, '.') == NULL) {
599 return NULL; /* no extension whatsoever */
603 * Yes. Split it into components separated by ".".
605 components = g_strsplit(filename, ".", 0);
609 * Count the components.
611 for (ncomponents = 0; components[ncomponents] != NULL; ncomponents++)
614 if (ncomponents == 0) {
615 g_strfreev(components);
616 return NULL; /* no components */
618 if (ncomponents == 1) {
619 g_strfreev(components);
620 return NULL; /* only one component, with no "." */
624 * Is the last component one of the extensions used for compressed
627 compressed_file_extensions = wtap_get_compressed_file_extensions();
628 if (compressed_file_extensions == NULL) {
630 * We don't support reading compressed files, so just
631 * return a copy of whatever extension we did find.
633 extensionp = g_strdup(components[ncomponents - 1]);
634 g_strfreev(components);
637 extensionp = components[ncomponents - 1];
638 for (compressed_file_extension = compressed_file_extensions;
639 compressed_file_extension != NULL;
640 compressed_file_extension = g_slist_next(compressed_file_extension)) {
641 if (strcmp(extensionp, (char *)compressed_file_extension->data) == 0) {
643 * Yes, it's one of the compressed-file extensions.
644 * Is there an extension before that?
646 if (ncomponents == 2) {
647 g_strfreev(components);
648 return NULL; /* no, only two components */
652 * Yes, return that extension.
654 extensionp = g_strdup(components[ncomponents - 2]);
655 g_strfreev(components);
661 * The extension isn't one of the compressed-file extensions;
664 extensionp = g_strdup(extensionp);
665 g_strfreev(components);
670 * Check if file extension is used in this heuristic
673 heuristic_uses_extension(unsigned int i, const char *extension)
678 * Does this file type *have* any extensions?
680 if (open_routines[i].extensions == NULL)
681 return FALSE; /* no */
684 * Check each of them against the specified extension.
686 for (extensionp = open_routines[i].extensions_set; *extensionp != NULL;
688 if (strcmp(extension, *extensionp) == 0) {
689 return TRUE; /* it's one of them */
693 return FALSE; /* it's not one of them */
696 /* Opens a file and prepares a wtap struct.
697 If "do_random" is TRUE, it opens the file twice; the second open
698 allows the application to do random-access I/O without moving
699 the seek offset for sequential I/O, which is used by Wireshark
700 so that it can do sequential I/O to a capture file that's being
701 written to as new packets arrive independently of random I/O done
702 to display protocol trees for packets when they're selected. */
704 wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_info,
711 gboolean use_stdin = FALSE;
714 init_open_routines();
716 /* open standard input if filename is '-' */
717 if (strcmp(filename, "-") == 0)
720 /* First, make sure the file is valid */
722 if (ws_fstat64(0, &statb) < 0) {
727 if (ws_stat64(filename, &statb) < 0) {
732 if (S_ISFIFO(statb.st_mode)) {
734 * Opens of FIFOs are allowed only when not opening
737 * XXX - currently, we do seeking when trying to find
738 * out the file type, so we don't actually support
739 * opening FIFOs. However, we may eventually
740 * do buffering that allows us to do at least some
741 * file type determination even on pipes, so we
742 * allow FIFO opens and let things fail later when
746 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
749 } else if (S_ISDIR(statb.st_mode)) {
751 * Return different errors for "this is a directory"
752 * and "this is some random special file type", so
753 * the user can get a potentially more helpful error.
757 } else if (! S_ISREG(statb.st_mode)) {
758 *err = WTAP_ERR_NOT_REGULAR_FILE;
763 * We need two independent descriptors for random access, so
764 * they have different file positions. If we're opening the
765 * standard input, we can only dup it to get additional
766 * descriptors, so we can't have two independent descriptors,
767 * and thus can't do random access.
769 if (use_stdin && do_random) {
770 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
775 wth = (wtap *)g_malloc0(sizeof(wtap));
778 errno = WTAP_ERR_CANT_OPEN;
781 * We dup FD 0, so that we don't have to worry about
782 * a file_close of wth->fh closing the standard
783 * input of the process.
792 if (_setmode(fd, O_BINARY) == -1) {
793 /* "Shouldn't happen" */
799 if (!(wth->fh = file_fdopen(fd))) {
806 if (!(wth->fh = file_open(filename))) {
814 if (!(wth->random_fh = file_open(filename))) {
821 wth->random_fh = NULL;
824 wth->file_encap = WTAP_ENCAP_UNKNOWN;
825 wth->subtype_sequential_close = NULL;
826 wth->subtype_close = NULL;
827 wth->file_tsprec = WTAP_TSPREC_USEC;
829 wth->wslua_data = NULL;
831 /* Initialize the array containing a list of interfaces. pcapng_open and
832 * erf_open needs this (and libpcap_open for ERF encapsulation types).
833 * Always initing it here saves checking for a NULL ptr later. */
834 wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
836 if (wth->random_fh) {
837 wth->fast_seek = g_ptr_array_new();
839 file_set_random_access(wth->fh, FALSE, wth->fast_seek);
840 file_set_random_access(wth->random_fh, TRUE, wth->fast_seek);
843 /* 'type' is 1 greater than the array index */
844 if (type != WTAP_TYPE_AUTO && type <= open_info_arr->len) {
847 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
848 /* I/O error - give up */
853 /* Set wth with wslua data if any - this is how we pass the data
854 * to the file reader, kinda like the priv member but not free'd later.
855 * It's ok for this to copy a NULL.
857 wth->wslua_data = open_routines[type - 1].wslua_data;
859 result = (*open_routines[type - 1].open_routine)(wth, err, err_info);
863 /* I/O error - give up */
868 /* No I/O error, but not that type of file */
872 /* We found the file type */
877 /* Try all file types that support magic numbers */
878 for (i = 0; i < heuristic_open_routine_idx; i++) {
879 /* Seek back to the beginning of the file; the open routine
880 for the previous file type may have left the file
881 position somewhere other than the beginning, and the
882 open routine for this file type will probably want
883 to start reading at the beginning.
885 Initialize the data offset while we're at it. */
886 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
887 /* I/O error - give up */
892 /* Set wth with wslua data if any - this is how we pass the data
893 * to the file reader, kinda like the priv member but not free'd later.
894 * It's ok for this to copy a NULL.
896 wth->wslua_data = open_routines[i].wslua_data;
898 switch ((*open_routines[i].open_routine)(wth, err, err_info)) {
901 /* I/O error - give up */
906 /* No I/O error, but not that type of file */
910 /* We found the file type */
916 /* Does this file's name have an extension? */
917 extension = get_file_extension(filename);
918 if (extension != NULL) {
919 /* Yes - try the heuristic types that use that extension first. */
920 for (i = heuristic_open_routine_idx; i < open_info_arr->len; i++) {
921 /* Does this type use that extension? */
922 if (heuristic_uses_extension(i, extension)) {
924 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
925 /* I/O error - give up */
931 /* Set wth with wslua data if any - this is how we pass the data
932 * to the file reader, kind of like priv but not free'd later.
934 wth->wslua_data = open_routines[i].wslua_data;
936 switch ((*open_routines[i].open_routine)(wth,
940 /* I/O error - give up */
946 /* No I/O error, but not that type of file */
950 /* We found the file type */
957 /* Now try the ones that don't use it. */
958 for (i = heuristic_open_routine_idx; i < open_info_arr->len; i++) {
959 /* Does this type use that extension? */
960 if (!heuristic_uses_extension(i, extension)) {
962 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
963 /* I/O error - give up */
969 /* Set wth with wslua data if any - this is how we pass the data
970 * to the file reader, kind of like priv but not free'd later.
972 wth->wslua_data = open_routines[i].wslua_data;
974 switch ((*open_routines[i].open_routine)(wth,
978 /* I/O error - give up */
984 /* No I/O error, but not that type of file */
988 /* We found the file type */
996 /* No - try all the heuristics types in order. */
997 for (i = heuristic_open_routine_idx; i < open_info_arr->len; i++) {
999 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
1000 /* I/O error - give up */
1005 /* Set wth with wslua data if any - this is how we pass the data
1006 * to the file reader, kind of like priv but not free'd later.
1008 wth->wslua_data = open_routines[i].wslua_data;
1010 switch ((*open_routines[i].open_routine)(wth, err, err_info)) {
1013 /* I/O error - give up */
1018 /* No I/O error, but not that type of file */
1022 /* We found the file type */
1030 /* Well, it's not one of the types of file we know about. */
1032 *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
1036 wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
1037 ws_buffer_init(wth->frame_buffer, 1500);
1039 if(wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP){
1041 wtapng_if_descr_t descr;
1043 descr.wtap_encap = wth->file_encap;
1044 descr.time_units_per_second = 1000000; /* default microsecond resolution */
1045 descr.link_type = wtap_wtap_encap_to_pcap_encap(wth->file_encap);
1046 descr.snap_len = wth->snapshot_length;
1047 descr.opt_comment = NULL;
1048 descr.if_name = NULL;
1049 descr.if_description = NULL;
1051 descr.if_tsresol = 6;
1052 descr.if_filter_str= NULL;
1053 descr.bpf_filter_len= 0;
1054 descr.if_filter_bpf_bytes= NULL;
1056 descr.if_fcslen = -1;
1057 descr.num_stat_entries = 0; /* Number of ISB:s */
1058 descr.interface_statistics = NULL;
1059 g_array_append_val(wth->interface_data, descr);
1066 * Given the pathname of the file we just closed with wtap_fdclose(), attempt
1067 * to reopen that file and assign the new file descriptor(s) to the sequential
1068 * stream and, if do_random is TRUE, to the random stream. Used on Windows
1069 * after the rename of a file we had open was done or if the rename of a
1070 * file on top of a file we had open failed.
1072 * This is only required by Wireshark, not TShark, and, at the point that
1073 * Wireshark is doing this, the sequential stream is closed, and the
1074 * random stream is open, so this refuses to open pipes, and only
1075 * reopens the random stream.
1078 wtap_fdreopen(wtap *wth, const char *filename, int *err)
1083 * We need two independent descriptors for random access, so
1084 * they have different file positions. If we're opening the
1085 * standard input, we can only dup it to get additional
1086 * descriptors, so we can't have two independent descriptors,
1087 * and thus can't do random access.
1089 if (strcmp(filename, "-") == 0) {
1090 *err = WTAP_ERR_RANDOM_OPEN_STDIN;
1094 /* First, make sure the file is valid */
1095 if (ws_stat64(filename, &statb) < 0) {
1099 if (S_ISFIFO(statb.st_mode)) {
1101 * Opens of FIFOs are not allowed; see above.
1103 *err = WTAP_ERR_RANDOM_OPEN_PIPE;
1105 } else if (S_ISDIR(statb.st_mode)) {
1107 * Return different errors for "this is a directory"
1108 * and "this is some random special file type", so
1109 * the user can get a potentially more helpful error.
1113 } else if (! S_ISREG(statb.st_mode)) {
1114 *err = WTAP_ERR_NOT_REGULAR_FILE;
1119 errno = WTAP_ERR_CANT_OPEN;
1120 if (!file_fdreopen(wth->random_fh, filename)) {
1127 /* Table of the file types we know about.
1128 Entries must be sorted by WTAP_FILE_TYPE_SUBTYPE_xxx values in ascending order */
1129 static const struct file_type_subtype_info dump_open_table_base[] = {
1130 /* WTAP_FILE_TYPE_SUBTYPE_UNKNOWN (only used internally for initialization) */
1131 { NULL, NULL, NULL, NULL,
1135 /* WTAP_FILE_TYPE_SUBTYPE_PCAP */
1136 /* Gianluca Varenni suggests that we add "deprecated" to the description. */
1137 { "Wireshark/tcpdump/... - pcap", "pcap", "pcap", "cap;dmp",
1139 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1141 /* WTAP_FILE_TYPE_SUBTYPE_PCAPNG */
1142 { "Wireshark/... - pcapng", "pcapng", "pcapng", "ntar",
1143 FALSE, TRUE, WTAP_COMMENT_PER_SECTION|WTAP_COMMENT_PER_INTERFACE|WTAP_COMMENT_PER_PACKET,
1144 pcapng_dump_can_write_encap, pcapng_dump_open, NULL },
1146 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC */
1147 { "Wireshark - nanosecond libpcap", "nseclibpcap", "pcap", "cap;dmp",
1149 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1151 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX */
1152 { "AIX tcpdump - libpcap", "aixlibpcap", "pcap", "cap;dmp",
1156 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS991029 */
1157 { "Modified tcpdump - libpcap", "modlibpcap", "pcap", "cap;dmp",
1159 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1161 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA */
1162 { "Nokia tcpdump - libpcap ", "nokialibpcap", "pcap", "cap;dmp",
1164 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1166 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990417 */
1167 { "RedHat 6.1 tcpdump - libpcap", "rh6_1libpcap", "pcap", "cap;dmp",
1169 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1171 /* WTAP_FILE_TYPE_SUBTYPE_PCAP_SS990915 */
1172 { "SuSE 6.3 tcpdump - libpcap", "suse6_3libpcap", "pcap", "cap;dmp",
1174 libpcap_dump_can_write_encap, libpcap_dump_open, NULL },
1176 /* WTAP_FILE_TYPE_SUBTYPE_5VIEWS */
1177 { "InfoVista 5View capture", "5views", "5vw", NULL,
1179 _5views_dump_can_write_encap, _5views_dump_open, NULL },
1181 /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_1_0 */
1182 { "AIX iptrace 1.0", "iptrace_1", NULL, NULL,
1186 /* WTAP_FILE_TYPE_SUBTYPE_IPTRACE_2_0 */
1187 { "AIX iptrace 2.0", "iptrace_2", NULL, NULL,
1191 /* WTAP_FILE_TYPE_SUBTYPE_BER */
1192 { "ASN.1 Basic Encoding Rules", "ber", NULL, NULL,
1196 /* WTAP_FILE_TYPE_SUBTYPE_HCIDUMP */
1197 { "Bluetooth HCI dump", "hcidump", NULL, NULL,
1201 /* WTAP_FILE_TYPE_SUBTYPE_CATAPULT_DCT2000 */
1202 { "Catapult DCT2000 trace (.out format)", "dct2000", "out", NULL,
1204 catapult_dct2000_dump_can_write_encap, catapult_dct2000_dump_open, NULL },
1206 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_OLD */
1207 { "Cinco Networks NetXRay 1.x", "netxray1", "cap", NULL,
1211 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_0 */
1212 { "Cinco Networks NetXRay 2.0 or later", "netxray2", "cap", NULL,
1216 /* WTAP_FILE_TYPE_SUBTYPE_COSINE */
1217 { "CoSine IPSX L2 capture", "cosine", "txt", NULL,
1221 /* WTAP_FILE_TYPE_SUBTYPE_CSIDS */
1222 { "CSIDS IPLog", "csids", NULL, NULL,
1226 /* WTAP_FILE_TYPE_SUBTYPE_DBS_ETHERWATCH */
1227 { "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL,
1231 /* WTAP_FILE_TYPE_SUBTYPE_ERF */
1232 { "Endace ERF capture", "erf", "erf", NULL,
1234 erf_dump_can_write_encap, erf_dump_open, NULL },
1236 /* WTAP_FILE_TYPE_SUBTYPE_EYESDN */
1237 { "EyeSDN USB S0/E1 ISDN trace format", "eyesdn", "trc", NULL,
1239 eyesdn_dump_can_write_encap, eyesdn_dump_open, NULL },
1241 /* WTAP_FILE_TYPE_SUBTYPE_NETTL */
1242 { "HP-UX nettl trace", "nettl", "trc0", "trc1",
1244 nettl_dump_can_write_encap, nettl_dump_open, NULL },
1246 /* WTAP_FILE_TYPE_SUBTYPE_ISERIES */
1247 { "IBM iSeries comm. trace (ASCII)", "iseries_ascii", "txt", NULL,
1251 /* WTAP_FILE_TYPE_SUBTYPE_ISERIES_UNICODE */
1252 { "IBM iSeries comm. trace (UNICODE)", "iseries_unicode", "txt", NULL,
1256 /* WTAP_FILE_TYPE_SUBTYPE_I4BTRACE */
1257 { "I4B ISDN trace", "i4btrace", NULL, NULL,
1261 /* WTAP_FILE_TYPE_SUBTYPE_ASCEND */
1262 { "Lucent/Ascend access server trace", "ascend", "txt", NULL,
1266 /* WTAP_FILE_TYPE_SUBTYPE_NETMON_1_x */
1267 { "Microsoft NetMon 1.x", "netmon1", "cap", NULL,
1269 netmon_dump_can_write_encap_1_x, netmon_dump_open, NULL },
1271 /* WTAP_FILE_TYPE_SUBTYPE_NETMON_2_x */
1272 { "Microsoft NetMon 2.x", "netmon2", "cap", NULL,
1274 netmon_dump_can_write_encap_2_x, netmon_dump_open, NULL },
1276 /* WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_UNCOMPRESSED */
1277 { "Sniffer (DOS)", "ngsniffer", "cap", "enc;trc;fdc;syc",
1279 ngsniffer_dump_can_write_encap, ngsniffer_dump_open, NULL },
1281 /* WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_COMPRESSED */
1282 { "Sniffer (DOS), compressed", "ngsniffer_comp", "cap", "enc;trc;fdc;syc",
1286 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_1_1 */
1287 { "NetXray, Sniffer (Windows) 1.1", "ngwsniffer_1_1", "cap", NULL,
1289 netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1, NULL },
1291 /* WTAP_FILE_TYPE_SUBTYPE_NETXRAY_2_00x */
1292 { "Sniffer (Windows) 2.00x", "ngwsniffer_2_0", "cap", "caz",
1294 netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0, NULL },
1296 /* WTAP_FILE_TYPE_SUBTYPE_NETWORK_INSTRUMENTS */
1297 { "Network Instruments Observer", "niobserver", "bfr", NULL,
1299 network_instruments_dump_can_write_encap, network_instruments_dump_open, NULL },
1301 /* WTAP_FILE_TYPE_SUBTYPE_LANALYZER */
1302 { "Novell LANalyzer","lanalyzer", "tr1", NULL,
1304 lanalyzer_dump_can_write_encap, lanalyzer_dump_open, NULL },
1306 /* WTAP_FILE_TYPE_SUBTYPE_PPPDUMP */
1307 { "pppd log (pppdump format)", "pppd", NULL, NULL,
1311 /* WTAP_FILE_TYPE_SUBTYPE_RADCOM */
1312 { "RADCOM WAN/LAN analyzer", "radcom", NULL, NULL,
1316 /* WTAP_FILE_TYPE_SUBTYPE_SNOOP */
1317 { "Sun snoop", "snoop", "snoop", "cap",
1319 snoop_dump_can_write_encap, snoop_dump_open, NULL },
1321 /* WTAP_FILE_TYPE_SUBTYPE_SHOMITI */
1322 { "Shomiti/Finisar Surveyor", "shomiti", "cap", NULL,
1326 /* WTAP_FILE_TYPE_SUBTYPE_VMS */
1327 { "TCPIPtrace (VMS)", "tcpiptrace", "txt", NULL,
1331 /* WTAP_FILE_TYPE_SUBTYPE_K12 */
1332 { "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL,
1334 k12_dump_can_write_encap, k12_dump_open, NULL },
1336 /* WTAP_FILE_TYPE_SUBTYPE_TOSHIBA */
1337 { "Toshiba Compact ISDN Router snoop", "toshiba", "txt", NULL,
1341 /* WTAP_FILE_TYPE_SUBTYPE_VISUAL_NETWORKS */
1342 { "Visual Networks traffic capture", "visual", NULL, NULL,
1344 visual_dump_can_write_encap, visual_dump_open, NULL },
1346 /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V56 */
1347 { "WildPackets classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz",
1351 /* WTAP_FILE_TYPE_SUBTYPE_PEEKCLASSIC_V7 */
1352 { "WildPackets classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz",
1356 /* WTAP_FILE_TYPE_SUBTYPE_PEEKTAGGED */
1357 { "WildPackets tagged", "peektagged", "pkt", "tpc;apc;wpz",
1361 /* WTAP_FILE_TYPE_SUBTYPE_MPEG */
1362 { "MPEG", "mpeg", "mpeg", "mpg;mp3",
1366 /* WTAP_FILE_TYPE_SUBTYPE_K12TEXT */
1367 { "K12 text file", "k12text", "txt", NULL,
1369 k12text_dump_can_write_encap, k12text_dump_open, NULL },
1371 /* WTAP_FILE_TYPE_SUBTYPE_NETSCREEN */
1372 { "NetScreen snoop text file", "netscreen", "txt", NULL,
1376 /* WTAP_FILE_TYPE_SUBTYPE_COMMVIEW */
1377 { "TamoSoft CommView", "commview", "ncf", NULL,
1379 commview_dump_can_write_encap, commview_dump_open, NULL },
1381 /* WTAP_FILE_TYPE_SUBTYPE_BTSNOOP */
1382 { "Symbian OS btsnoop", "btsnoop", "log", NULL,
1384 btsnoop_dump_can_write_encap, btsnoop_dump_open_h4, NULL },
1386 /* WTAP_FILE_TYPE_SUBTYPE_TNEF */
1387 { "Transport-Neutral Encapsulation Format", "tnef", NULL, NULL,
1391 /* WTAP_FILE_TYPE_SUBTYPE_DCT3TRACE */
1392 { "Gammu DCT3 trace", "dct3trace", "xml", NULL,
1396 /* WTAP_FILE_TYPE_SUBTYPE_PACKETLOGGER */
1397 { "PacketLogger", "pklg", "pklg", NULL,
1401 /* WTAP_FILE_TYPE_SUBTYPE_DAINTREE_SNA */
1402 { "Daintree SNA", "dsna", "dcf", NULL,
1406 /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0 */
1407 { "NetScaler Trace (Version 1.0)", "nstrace10", NULL, NULL,
1409 nstrace_10_dump_can_write_encap, nstrace_dump_open, NULL },
1411 /* WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0 */
1412 { "NetScaler Trace (Version 2.0)", "nstrace20", "cap", NULL,
1414 nstrace_20_dump_can_write_encap, nstrace_dump_open, NULL },
1416 /* WTAP_FILE_TYPE_SUBTYPE_JPEG_JFIF */
1417 { "JPEG/JFIF", "jpeg", "jpg", "jpeg;jfif",
1421 /* WTAP_FILE_TYPE_SUBTYPE_IPFIX */
1422 { "IPFIX File Format", "ipfix", "pfx", "ipfix",
1426 /* WTAP_ENCAP_MIME */
1427 { "MIME File Format", "mime", NULL, NULL,
1431 /* WTAP_FILE_TYPE_SUBTYPE_AETHRA */
1432 { "Aethra .aps file", "aethra", "aps", NULL,
1436 /* WTAP_FILE_TYPE_SUBTYPE_MPEG_2_TS */
1437 { "MPEG2 transport stream", "mp2t", "mp2t", "ts;mpg",
1441 /* WTAP_FILE_TYPE_SUBTYPE_VWR_80211 */
1442 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL,
1446 /* WTAP_FILE_TYPE_SUBTYPE_VWR_ETH */
1447 { "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL,
1451 /* WTAP_FILE_TYPE_SUBTYPE_CAMINS */
1452 { "CAM Inspector file", "camins", "camins", NULL,
1456 /* WTAP_FILE_TYPE_SUBTYPE_STANAG_4607 */
1457 { "STANAG 4607 Format", "stanag4607", NULL, NULL,
1461 /* WTAP_FILE_NETSCALER_3_0 */
1462 { "NetScaler Trace (Version 3.0)", "nstrace30", "cap", NULL,
1464 nstrace_30_dump_can_write_encap, nstrace_dump_open, NULL },
1466 /* WTAP_FILE_LOGCAT */
1467 { "Android Logcat Binary format", "logcat", "logcat", NULL,
1469 logcat_dump_can_write_encap, logcat_binary_dump_open, NULL },
1470 { "Android Logcat Brief text format", "logcat-brief", NULL, NULL,
1472 logcat_text_brief_dump_can_write_encap, logcat_text_brief_dump_open, NULL },
1473 { "Android Logcat Process text format", "logcat-process", NULL, NULL,
1475 logcat_text_process_dump_can_write_encap, logcat_text_process_dump_open, NULL },
1476 { "Android Logcat Tag text format", "logcat-tag", NULL, NULL,
1478 logcat_text_tag_dump_can_write_encap, logcat_text_tag_dump_open, NULL },
1479 { "Android Logcat Thread text format", "logcat-thread", NULL, NULL,
1481 logcat_text_thread_dump_can_write_encap, logcat_text_thread_dump_open, NULL },
1482 { "Android Logcat Time text format", "logcat-time", NULL, NULL,
1484 logcat_text_time_dump_can_write_encap, logcat_text_time_dump_open, NULL },
1485 { "Android Logcat Threadtime text format", "logcat-threadtime", NULL, NULL,
1487 logcat_text_threadtime_dump_can_write_encap, logcat_text_threadtime_dump_open, NULL },
1488 { "Android Logcat Long text format", "logcat-long", NULL, NULL,
1490 logcat_text_long_dump_can_write_encap, logcat_text_long_dump_open, NULL }
1494 gint wtap_num_file_types_subtypes = sizeof(dump_open_table_base) / sizeof(struct file_type_subtype_info);
1496 static GArray* dump_open_table_arr = NULL;
1497 static const struct file_type_subtype_info* dump_open_table = dump_open_table_base;
1499 /* initialize the file types array if it has not being initialized yet */
1501 init_file_types_subtypes(void)
1504 if (dump_open_table_arr) return;
1506 dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct file_type_subtype_info));
1508 g_array_append_vals(dump_open_table_arr,dump_open_table_base,wtap_num_file_types_subtypes);
1510 dump_open_table = (const struct file_type_subtype_info*)(void *)dump_open_table_arr->data;
1513 /* if subtype is WTAP_FILE_TYPE_SUBTYPE_UNKNOWN, then create a new subtype as well as register it, else replace the
1514 existing entry in that spot */
1516 wtap_register_file_type_subtypes(const struct file_type_subtype_info* fi, const int subtype)
1518 struct file_type_subtype_info* finfo;
1519 init_file_types_subtypes();
1521 if (!fi || !fi->name || !fi->short_name || subtype > wtap_num_file_types_subtypes) {
1522 g_error("no file type info or invalid file type to register");
1526 /* do we want a new registration? */
1527 if (subtype == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) {
1528 /* register a new one; first verify there isn't one named this already */
1529 if (wtap_short_string_to_file_type_subtype(fi->short_name) > -1 ) {
1530 g_error("file type short name already exists");
1534 g_array_append_val(dump_open_table_arr,*fi);
1536 dump_open_table = (const struct file_type_subtype_info*)(void *)dump_open_table_arr->data;
1538 return wtap_num_file_types_subtypes++;
1541 /* re-register an existing one - verify the short names do match (sanity check really) */
1542 if (!dump_open_table[subtype].short_name || strcmp(dump_open_table[subtype].short_name,fi->short_name) != 0) {
1543 g_error("invalid file type name given to register");
1547 /* yes, we're going to cast to change its const-ness */
1548 finfo = (struct file_type_subtype_info*)(&dump_open_table[subtype]);
1549 /*finfo->name = fi->name;*/
1550 /*finfo->short_name = fi->short_name;*/
1551 finfo->default_file_extension = fi->default_file_extension;
1552 finfo->additional_file_extensions = fi->additional_file_extensions;
1553 finfo->writing_must_seek = fi->writing_must_seek;
1554 finfo->has_name_resolution = fi->has_name_resolution;
1555 finfo->supported_comment_types = fi->supported_comment_types;
1556 finfo->can_write_encap = fi->can_write_encap;
1557 finfo->dump_open = fi->dump_open;
1558 finfo->wslua_info = fi->wslua_info;
1563 /* De-registers a file writer - they can never be removed from the GArray, but we can "clear" an entry.
1566 wtap_deregister_file_type_subtype(const int subtype)
1568 struct file_type_subtype_info* finfo;
1570 if (subtype < 0 || subtype >= wtap_num_file_types_subtypes) {
1571 g_error("invalid file type to de-register");
1575 /* yes, we're going to cast to change its const-ness */
1576 finfo = (struct file_type_subtype_info*)(&dump_open_table[subtype]);
1577 /* unfortunately, it's not safe to null-out the name or short_name; bunch of other code doesn't guard aainst that, afaict */
1578 /*finfo->name = NULL;*/
1579 /*finfo->short_name = NULL;*/
1580 finfo->default_file_extension = NULL;
1581 finfo->additional_file_extensions = NULL;
1582 finfo->writing_must_seek = FALSE;
1583 finfo->has_name_resolution = FALSE;
1584 finfo->supported_comment_types = 0;
1585 finfo->can_write_encap = NULL;
1586 finfo->dump_open = NULL;
1587 finfo->wslua_info = NULL;
1591 wtap_get_num_file_types_subtypes(void)
1593 return wtap_num_file_types_subtypes;
1597 * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
1598 * type that would be needed to write out a file with those types. If
1599 * there's only one type, it's that type, otherwise it's
1600 * WTAP_ENCAP_PER_PACKET.
1603 wtap_dump_file_encap_type(const GArray *file_encaps)
1607 encap = WTAP_ENCAP_PER_PACKET;
1608 if (file_encaps->len == 1) {
1609 /* OK, use the one-and-only encapsulation type. */
1610 encap = g_array_index(file_encaps, gint, 0);
1616 wtap_dump_can_write_encap(int filetype, int encap)
1620 if (filetype < 0 || filetype >= wtap_num_file_types_subtypes
1621 || dump_open_table[filetype].can_write_encap == NULL)
1624 result = (*dump_open_table[filetype].can_write_encap)(encap);
1627 /* if the err said to check wslua's can_write_encap, try that */
1628 if (result == WTAP_ERR_CHECK_WSLUA
1629 && dump_open_table[filetype].wslua_info != NULL
1630 && dump_open_table[filetype].wslua_info->wslua_can_write_encap != NULL) {
1632 result = (*dump_open_table[filetype].wslua_info->wslua_can_write_encap)(encap, dump_open_table[filetype].wslua_info->wslua_data);
1644 * Return TRUE if a capture with a given GArray of encapsulation types
1645 * and a given bitset of comment types can be written in a specified
1646 * format, and FALSE if it can't.
1649 wtap_dump_can_write_format(int ft, const GArray *file_encaps,
1650 guint32 required_comment_types)
1655 * Can we write in this format?
1657 if (!wtap_dump_can_open(ft)) {
1663 * Yes. Can we write out all the required comments in this
1666 if (!wtap_dump_supports_comment_types(ft, required_comment_types)) {
1672 * Yes. Is the required per-file encapsulation type supported?
1673 * This might be WTAP_ENCAP_PER_PACKET.
1675 if (!wtap_dump_can_write_encap(ft, wtap_dump_file_encap_type(file_encaps))) {
1681 * Yes. Are all the individual encapsulation types supported?
1683 for (i = 0; i < file_encaps->len; i++) {
1684 if (!wtap_dump_can_write_encap(ft,
1685 g_array_index(file_encaps, int, i))) {
1686 /* No - one of them isn't. */
1691 /* Yes - we're OK. */
1696 * Return TRUE if we can write a file with the given GArray of
1697 * encapsulation types and the given bitmask of comment types.
1700 wtap_dump_can_write(const GArray *file_encaps, guint32 required_comment_types)
1704 for (ft = 0; ft < WTAP_NUM_FILE_TYPES_SUBTYPES; ft++) {
1705 /* To save a file with Wiretap, Wiretap has to handle that format,
1706 * and its code to handle that format must be able to write a file
1707 * with this file's encapsulation types.
1709 if (wtap_dump_can_write_format(ft, file_encaps, required_comment_types)) {
1710 /* OK, we can write it out in this type. */
1715 /* No, we couldn't save it in any format. */
1720 * Get a GArray of WTAP_FILE_TYPE_SUBTYPE_ values for file types/subtypes
1721 * that can be used to save a file of a given type/subtype with a given
1722 * GArray of encapsulation types and the given bitmask of comment types.
1725 wtap_get_savable_file_types_subtypes(int file_type_subtype,
1726 const GArray *file_encaps, guint32 required_comment_types)
1728 GArray *savable_file_types_subtypes;
1730 int default_file_type_subtype = -1;
1731 int other_file_type_subtype = -1;
1733 /* Can we save this file in its own file type/subtype? */
1734 if (wtap_dump_can_write_format(file_type_subtype, file_encaps,
1735 required_comment_types)) {
1736 /* Yes - make that the default file type/subtype. */
1737 default_file_type_subtype = file_type_subtype;
1739 /* OK, find the first file type/subtype we *can* save it as. */
1740 default_file_type_subtype = -1;
1741 for (ft = 0; ft < WTAP_NUM_FILE_TYPES_SUBTYPES; ft++) {
1742 if (wtap_dump_can_write_format(ft, file_encaps,
1743 required_comment_types)) {
1745 default_file_type_subtype = ft;
1750 if (default_file_type_subtype == -1) {
1751 /* We don't support writing this file as any file type/subtype. */
1755 /* Allocate the array. */
1756 savable_file_types_subtypes = g_array_new(FALSE, FALSE, (guint)sizeof (int));
1758 /* Put the default file type/subtype first in the list. */
1759 g_array_append_val(savable_file_types_subtypes, default_file_type_subtype);
1761 /* If the default is pcap, put pcap-NG right after it if we can
1762 also write it in pcap-NG format; otherwise, if the default is
1763 pcap-NG, put pcap right after it if we can also write it in
1765 if (default_file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP) {
1766 if (wtap_dump_can_write_format(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, file_encaps,
1767 required_comment_types))
1768 other_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
1769 } else if (default_file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAPNG) {
1770 if (wtap_dump_can_write_format(WTAP_FILE_TYPE_SUBTYPE_PCAP, file_encaps,
1771 required_comment_types))
1772 other_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAP;
1774 if (other_file_type_subtype != -1)
1775 g_array_append_val(savable_file_types_subtypes, other_file_type_subtype);
1777 /* Add all the other file types/subtypes that work. */
1778 for (ft = 0; ft < WTAP_NUM_FILE_TYPES_SUBTYPES; ft++) {
1779 if (ft == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN)
1780 continue; /* not a real file type */
1781 if (ft == default_file_type_subtype || ft == other_file_type_subtype)
1782 continue; /* we've already done this one */
1783 if (wtap_dump_can_write_format(ft, file_encaps,
1784 required_comment_types)) {
1785 /* OK, we can write it out in this type. */
1786 g_array_append_val(savable_file_types_subtypes, ft);
1790 return savable_file_types_subtypes;
1793 /* Name that should be somewhat descriptive. */
1795 wtap_file_type_subtype_string(int file_type_subtype)
1797 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes) {
1798 g_error("Unknown capture file type %d", file_type_subtype);
1799 /** g_error() does an abort() and thus never returns **/
1802 return dump_open_table[file_type_subtype].name;
1805 /* Name to use in, say, a command-line flag specifying the type/subtype. */
1807 wtap_file_type_subtype_short_string(int file_type_subtype)
1809 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
1812 return dump_open_table[file_type_subtype].short_name;
1815 /* Translate a short name to a capture file type/subtype. */
1817 wtap_short_string_to_file_type_subtype(const char *short_name)
1819 int file_type_subtype;
1821 for (file_type_subtype = 0; file_type_subtype < wtap_num_file_types_subtypes; file_type_subtype++) {
1822 if (dump_open_table[file_type_subtype].short_name != NULL &&
1823 strcmp(short_name, dump_open_table[file_type_subtype].short_name) == 0)
1824 return file_type_subtype;
1828 * We now call the "libpcap" file format just "pcap", but we
1829 * allow it to be specified as "libpcap" as well, for
1830 * backwards compatibility.
1832 if (strcmp(short_name, "libpcap") == 0)
1833 return WTAP_FILE_TYPE_SUBTYPE_PCAP;
1835 return -1; /* no such file type, or we can't write it */
1839 add_extensions_for_file_type_subtype(int file_type_subtype, GSList *extensions,
1840 GSList *compressed_file_extensions)
1842 gchar **extensions_set, **extensionp;
1846 * Add the default extension, and all compressed variants of
1849 extensions = add_extensions(extensions,
1850 dump_open_table[file_type_subtype].default_file_extension,
1851 compressed_file_extensions);
1853 if (dump_open_table[file_type_subtype].additional_file_extensions != NULL) {
1855 * We have additional extensions; add them.
1857 * First, split the extension-list string into a set of
1860 extensions_set = g_strsplit(dump_open_table[file_type_subtype].additional_file_extensions,
1864 * Add each of those extensions to the list.
1866 for (extensionp = extensions_set; *extensionp != NULL;
1868 extension = *extensionp;
1871 * Add the extension, and all compressed variants
1874 extensions = add_extensions(extensions, extension,
1875 compressed_file_extensions);
1878 g_strfreev(extensions_set);
1883 /* Return a list of file extensions that are used by the specified file type.
1885 If include_compressed is TRUE, the list will include compressed
1886 extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
1889 All strings in the list are allocated with g_malloc() and must be freed
1892 wtap_get_file_extensions_list(int file_type_subtype, gboolean include_compressed)
1894 GSList *compressed_file_extensions;
1897 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
1898 return NULL; /* not a valid file type */
1900 if (dump_open_table[file_type_subtype].default_file_extension == NULL)
1901 return NULL; /* valid, but no extensions known */
1903 extensions = NULL; /* empty list, to start with */
1906 * If include_compressions is true, get the list of compressed-file
1909 if (include_compressed)
1910 compressed_file_extensions = wtap_get_compressed_file_extensions();
1912 compressed_file_extensions = NULL;
1915 * Add all this file type's extensions, with compressed
1918 extensions = add_extensions_for_file_type_subtype(file_type_subtype, extensions,
1919 compressed_file_extensions);
1921 g_slist_free(compressed_file_extensions);
1926 * Free a list returned by wtap_get_file_extension_type_extensions(),
1927 * wtap_get_all_file_extensions_list, or wtap_get_file_extensions_list().
1930 wtap_free_extensions_list(GSList *extensions)
1934 for (extension = extensions; extension != NULL;
1935 extension = g_slist_next(extension)) {
1936 g_free(extension->data);
1938 g_slist_free(extensions);
1941 /* Return the default file extension to use with the specified file type;
1942 that's just the extension, without any ".". */
1944 wtap_default_file_extension(int file_type_subtype)
1946 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
1949 return dump_open_table[file_type_subtype].default_file_extension;
1953 wtap_dump_can_open(int file_type_subtype)
1955 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
1956 || dump_open_table[file_type_subtype].dump_open == NULL)
1964 wtap_dump_can_compress(int file_type_subtype)
1967 * If this is an unknown file type, or if we have to
1968 * seek when writing out a file with this file type,
1971 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
1972 || dump_open_table[file_type_subtype].writing_must_seek)
1979 wtap_dump_can_compress(int file_type_subtype _U_)
1986 wtap_dump_has_name_resolution(int file_type_subtype)
1988 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes
1989 || dump_open_table[file_type_subtype].has_name_resolution == FALSE)
1996 wtap_dump_supports_comment_types(int file_type_subtype, guint32 comment_types)
1998 guint32 supported_comment_types;
2000 if (file_type_subtype < 0 || file_type_subtype >= wtap_num_file_types_subtypes)
2003 supported_comment_types = dump_open_table[file_type_subtype].supported_comment_types;
2005 if ((comment_types & supported_comment_types) == comment_types)
2010 static gboolean wtap_dump_open_check(int file_type_subtype, int encap, gboolean comressed, int *err);
2011 static wtap_dumper* wtap_dump_alloc_wdh(int file_type_subtype, int encap, int snaplen,
2012 gboolean compressed, int *err);
2013 static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int file_type_subtype, gboolean compressed, int *err);
2015 static WFILE_T wtap_dump_file_open(wtap_dumper *wdh, const char *filename);
2016 static WFILE_T wtap_dump_file_fdopen(wtap_dumper *wdh, int fd);
2017 static int wtap_dump_file_close(wtap_dumper *wdh);
2020 wtap_dump_open(const char *filename, int file_type_subtype, int encap,
2021 int snaplen, gboolean compressed, int *err)
2023 return wtap_dump_open_ng(filename, file_type_subtype, encap,snaplen, compressed, NULL, NULL, err);
2026 static wtap_dumper *
2027 wtap_dump_init_dumper(int file_type_subtype, int encap, int snaplen, gboolean compressed,
2028 wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
2032 /* Allocate a data structure for the output stream. */
2033 wdh = wtap_dump_alloc_wdh(file_type_subtype, encap, snaplen, compressed, err);
2035 return NULL; /* couldn't allocate it */
2037 /* Set Section Header Block data */
2038 wdh->shb_hdr = shb_hdr;
2039 /* Set Interface Description Block data */
2040 if ((idb_inf != NULL) && (idb_inf->interface_data->len > 0)) {
2041 wdh->interface_data = idb_inf->interface_data;
2043 wtapng_if_descr_t descr;
2045 descr.wtap_encap = encap;
2046 descr.time_units_per_second = 1000000; /* default microsecond resolution */
2047 descr.link_type = wtap_wtap_encap_to_pcap_encap(encap);
2048 descr.snap_len = snaplen;
2049 descr.opt_comment = NULL;
2050 descr.if_name = g_strdup("Unknown/not available in original file format(libpcap)");
2051 descr.if_description = NULL;
2053 descr.if_tsresol = 6;
2054 descr.if_filter_str= NULL;
2055 descr.bpf_filter_len= 0;
2056 descr.if_filter_bpf_bytes= NULL;
2058 descr.if_fcslen = -1;
2059 descr.num_stat_entries = 0; /* Number of ISB:s */
2060 descr.interface_statistics = NULL;
2061 wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
2062 g_array_append_val(wdh->interface_data, descr);
2068 wtap_dump_open_ng(const char *filename, int file_type_subtype, int encap,
2069 int snaplen, gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
2074 /* Check whether we can open a capture file with that file type
2075 and that encapsulation. */
2076 if (!wtap_dump_open_check(file_type_subtype, encap, compressed, err))
2079 /* Allocate and initialize a data structure for the output stream. */
2080 wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2081 shb_hdr, idb_inf, err);
2085 /* "-" means stdout */
2086 if (strcmp(filename, "-") == 0) {
2088 *err = EINVAL; /* XXX - return a Wiretap error code for this */
2090 return NULL; /* compress won't work on stdout */
2093 if (_setmode(fileno(stdout), O_BINARY) == -1) {
2094 /* "Should not happen" */
2097 return NULL; /* couldn't put standard output in binary mode */
2102 /* In case "fopen()" fails but doesn't set "errno", set "errno"
2103 to a generic "the open failed" error. */
2104 errno = WTAP_ERR_CANT_OPEN;
2105 fh = wtap_dump_file_open(wdh, filename);
2109 return NULL; /* can't create file */
2114 if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2115 /* Get rid of the file we created; we couldn't finish
2117 if (wdh->fh != stdout) {
2118 wtap_dump_file_close(wdh);
2119 ws_unlink(filename);
2128 wtap_dump_fdopen(int fd, int file_type_subtype, int encap, int snaplen,
2129 gboolean compressed, int *err)
2131 return wtap_dump_fdopen_ng(fd, file_type_subtype, encap, snaplen, compressed, NULL, NULL, err);
2135 wtap_dump_fdopen_ng(int fd, int file_type_subtype, int encap, int snaplen,
2136 gboolean compressed, wtapng_section_t *shb_hdr, wtapng_iface_descriptions_t *idb_inf, int *err)
2141 /* Check whether we can open a capture file with that file type
2142 and that encapsulation. */
2143 if (!wtap_dump_open_check(file_type_subtype, encap, compressed, err))
2146 /* Allocate and initialize a data structure for the output stream. */
2147 wdh = wtap_dump_init_dumper(file_type_subtype, encap, snaplen, compressed,
2148 shb_hdr, idb_inf, err);
2154 if (_setmode(fileno(stdout), O_BINARY) == -1) {
2155 /* "Should not happen" */
2158 return NULL; /* couldn't put standard output in binary mode */
2163 /* In case "fopen()" fails but doesn't set "errno", set "errno"
2164 to a generic "the open failed" error. */
2165 errno = WTAP_ERR_CANT_OPEN;
2166 fh = wtap_dump_file_fdopen(wdh, fd);
2170 return NULL; /* can't create standard I/O stream */
2174 if (!wtap_dump_open_finish(wdh, file_type_subtype, compressed, err)) {
2175 wtap_dump_file_close(wdh);
2183 wtap_dump_open_check(int file_type_subtype, int encap, gboolean compressed, int *err)
2185 if (!wtap_dump_can_open(file_type_subtype)) {
2186 /* Invalid type, or type we don't know how to write. */
2187 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
2191 /* OK, we know how to write that type; can we write the specified
2192 encapsulation type? */
2193 *err = (*dump_open_table[file_type_subtype].can_write_encap)(encap);
2194 /* if the err said to check wslua's can_write_encap, try that */
2195 if (*err == WTAP_ERR_CHECK_WSLUA
2196 && dump_open_table[file_type_subtype].wslua_info != NULL
2197 && dump_open_table[file_type_subtype].wslua_info->wslua_can_write_encap != NULL) {
2199 *err = (*dump_open_table[file_type_subtype].wslua_info->wslua_can_write_encap)(encap, dump_open_table[file_type_subtype].wslua_info->wslua_data);
2206 /* if compression is wanted, do we support this for this file_type_subtype? */
2207 if(compressed && !wtap_dump_can_compress(file_type_subtype)) {
2208 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED;
2212 /* All systems go! */
2216 static wtap_dumper *
2217 wtap_dump_alloc_wdh(int file_type_subtype, int encap, int snaplen, gboolean compressed, int *err)
2221 wdh = (wtap_dumper *)g_malloc0(sizeof (wtap_dumper));
2227 wdh->file_type_subtype = file_type_subtype;
2228 wdh->snaplen = snaplen;
2230 wdh->compressed = compressed;
2231 wdh->wslua_data = NULL;
2236 wtap_dump_open_finish(wtap_dumper *wdh, int file_type_subtype, gboolean compressed, int *err)
2241 /* Can we do a seek on the file descriptor?
2242 If not, note that fact. */
2246 fd = fileno((FILE *)wdh->fh);
2247 if (ws_lseek64(fd, 1, SEEK_CUR) == (off_t) -1)
2250 /* Undo the seek. */
2251 ws_lseek64(fd, 0, SEEK_SET);
2256 /* If this file type requires seeking, and we can't seek, fail. */
2257 if (dump_open_table[file_type_subtype].writing_must_seek && cant_seek) {
2258 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
2262 /* Set wdh with wslua data if any - this is how we pass the data
2263 * to the file writer.
2265 if (dump_open_table[file_type_subtype].wslua_info)
2266 wdh->wslua_data = dump_open_table[file_type_subtype].wslua_info->wslua_data;
2268 /* Now try to open the file for writing. */
2269 if (!(*dump_open_table[file_type_subtype].dump_open)(wdh, err)) {
2273 return TRUE; /* success! */
2277 wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
2278 const guint8 *pd, int *err)
2280 return (wdh->subtype_write)(wdh, phdr, pd, err);
2284 wtap_dump_flush(wtap_dumper *wdh)
2287 if(wdh->compressed) {
2288 gzwfile_flush((GZWFILE_T)wdh->fh);
2292 fflush((FILE *)wdh->fh);
2297 wtap_dump_close(wtap_dumper *wdh, int *err)
2299 gboolean ret = TRUE;
2301 if (wdh->subtype_close != NULL) {
2302 /* There's a close routine for this dump stream. */
2303 if (!(wdh->subtype_close)(wdh, err))
2306 errno = WTAP_ERR_CANT_CLOSE;
2307 /* Don't close stdout */
2308 if (wdh->fh != stdout) {
2309 if (wtap_dump_file_close(wdh) == EOF) {
2311 /* The per-format close function succeeded,
2312 but the fclose didn't. Save the reason
2313 why, if our caller asked for it. */
2320 /* as we don't close stdout, at least try to flush it */
2321 wtap_dump_flush(wdh);
2323 if (wdh->priv != NULL)
2330 wtap_get_bytes_dumped(wtap_dumper *wdh)
2332 return wdh->bytes_dumped;
2336 wtap_set_bytes_dumped(wtap_dumper *wdh, gint64 bytes_dumped)
2338 wdh->bytes_dumped = bytes_dumped;
2342 wtap_dump_set_addrinfo_list(wtap_dumper *wdh, addrinfo_lists_t *addrinfo_lists)
2344 if (!wdh || wdh->file_type_subtype < 0 || wdh->file_type_subtype >= wtap_num_file_types_subtypes
2345 || dump_open_table[wdh->file_type_subtype].has_name_resolution == FALSE)
2347 wdh->addrinfo_lists = addrinfo_lists;
2351 /* internally open a file for writing (compressed or not) */
2354 wtap_dump_file_open(wtap_dumper *wdh, const char *filename)
2356 if(wdh->compressed) {
2357 return gzwfile_open(filename);
2359 return ws_fopen(filename, "wb");
2364 wtap_dump_file_open(wtap_dumper *wdh _U_, const char *filename)
2366 return ws_fopen(filename, "wb");
2370 /* internally open a file for writing (compressed or not) */
2373 wtap_dump_file_fdopen(wtap_dumper *wdh, int fd)
2375 if(wdh->compressed) {
2376 return gzwfile_fdopen(fd);
2378 return fdopen(fd, "wb");
2383 wtap_dump_file_fdopen(wtap_dumper *wdh _U_, int fd)
2385 return fdopen(fd, "wb");
2389 /* internally writing raw bytes (compressed or not) */
2391 wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize, int *err)
2396 if (wdh->compressed) {
2397 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned int) bufsize);
2399 * gzwfile_write() returns 0 on error.
2401 if (nwritten == 0) {
2402 *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
2408 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
2410 * At least according to the Mac OS X man page,
2411 * this can return a short count on an error.
2413 if (nwritten != bufsize) {
2414 if (ferror((FILE *)wdh->fh))
2417 *err = WTAP_ERR_SHORT_WRITE;
2424 /* internally close a file for writing (compressed or not) */
2426 wtap_dump_file_close(wtap_dumper *wdh)
2429 if(wdh->compressed) {
2430 return gzwfile_close((GZWFILE_T)wdh->fh);
2434 return fclose((FILE *)wdh->fh);
2439 wtap_dump_file_seek(wtap_dumper *wdh, gint64 offset, int whence, int *err)
2442 if(wdh->compressed) {
2443 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2448 if (-1 == fseek((FILE *)wdh->fh, (long)offset, whence)) {
2459 wtap_dump_file_tell(wtap_dumper *wdh, int *err)
2463 if(wdh->compressed) {
2464 *err = WTAP_ERR_CANT_SEEK_COMPRESSED;
2469 if (-1 == (rval = ftell((FILE *)wdh->fh))) {