diff options
-rw-r--r-- | capture_loop.c | 10 | ||||
-rw-r--r-- | editcap.c | 2 | ||||
-rw-r--r-- | file.c | 13 | ||||
-rw-r--r-- | file.h | 3 | ||||
-rw-r--r-- | gtk/file_dlg.c | 18 | ||||
-rw-r--r-- | mergecap.c | 2 | ||||
-rw-r--r-- | randpkt.c | 2 | ||||
-rw-r--r-- | ringbuffer.c | 2 | ||||
-rw-r--r-- | tethereal.c | 6 | ||||
-rw-r--r-- | wiretap/file_access.c | 280 | ||||
-rw-r--r-- | wiretap/libpcap.c | 42 | ||||
-rw-r--r-- | wiretap/wtap-int.h | 3 | ||||
-rw-r--r-- | wiretap/wtap.def | 3 | ||||
-rw-r--r-- | wiretap/wtap.h | 9 |
14 files changed, 272 insertions, 123 deletions
diff --git a/capture_loop.c b/capture_loop.c index 8421e73a32..8ed04636a6 100644 --- a/capture_loop.c +++ b/capture_loop.c @@ -832,7 +832,7 @@ static int capture_loop_init_wiretap_output(capture_options *capture_opts, int s file_snaplen, &err); } else { ld->wtap_pdh = wtap_dump_fdopen(save_file_fd, WTAP_FILE_PCAP, - ld->wtap_linktype, file_snaplen, &err); + ld->wtap_linktype, file_snaplen, FALSE /* compressed */, &err); } if (ld->wtap_pdh == NULL) { @@ -1242,7 +1242,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct message to our parent so that they'll open the capture file and update its windows to indicate that we have a live capture in progress. */ - fflush(wtap_dump_file(ld.wtap_pdh)); + wtap_dump_flush(ld.wtap_pdh); sync_pipe_filename_to_parent(capture_opts->save_file); /* initialize capture stop (and alike) conditions */ @@ -1328,7 +1328,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct if (cnd_file_duration) { cnd_reset(cnd_file_duration); } - fflush(wtap_dump_file(ld.wtap_pdh)); + wtap_dump_flush(ld.wtap_pdh); sync_pipe_filename_to_parent(capture_opts->save_file); } else { /* File switch failed: stop here */ @@ -1371,7 +1371,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct /* Let the parent process know. */ if (ld.packets_sync_pipe) { /* do sync here */ - fflush(wtap_dump_file(ld.wtap_pdh)); + wtap_dump_flush(ld.wtap_pdh); /* Send our parent a message saying we've written out "ld.sync_packets" packets to the capture file. */ @@ -1403,7 +1403,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct cnd_reset(cnd_file_duration); if(cnd_autostop_size) cnd_reset(cnd_autostop_size); - fflush(wtap_dump_file(ld.wtap_pdh)); + wtap_dump_flush(ld.wtap_pdh); sync_pipe_filename_to_parent(capture_opts->save_file); } else { /* File switch failed: stop here */ @@ -373,7 +373,7 @@ int main(int argc, char *argv[]) out_frame_type = wtap_file_encap(wth); pdh = wtap_dump_open(argv[optind + 1], out_file_type, - out_frame_type, wtap_snapshot_length(wth), &err); + out_frame_type, wtap_snapshot_length(wth), FALSE /* compressed */, &err); if (pdh == NULL) { fprintf(stderr, "editcap: Can't open or create %s: %s\n", argv[optind+1], @@ -983,7 +983,8 @@ cf_merge_files(char **out_filenamep, int in_file_count, pdh = wtap_dump_fdopen(out_fd, file_type, merge_select_frame_type(in_file_count, in_files), - merge_max_snapshot_length(in_file_count, in_files), &open_err); + merge_max_snapshot_length(in_file_count, in_files), + FALSE /* compressed */, &open_err); if (pdh == NULL) { close(out_fd); merge_close_in_files(in_file_count, in_files); @@ -3081,7 +3082,7 @@ save_packet(capture_file *cf _U_, frame_data *fdata, } cf_status_t -cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format) +cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed) { gchar *from_filename; int err; @@ -3160,7 +3161,8 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f /* Either we're filtering packets, or we're saving in a different format; we can't do that by copying or moving the capture file, we have to do it by writing the packets out in Wiretap. */ - pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err); + pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, + compressed, &err); if (pdh == NULL) { cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format); goto fail; @@ -3359,6 +3361,11 @@ cf_open_failure_alert_box(const char *filename, int err, gchar *err_info, filename); break; + case WTAP_ERR_COMPRESSION_NOT_SUPPORTED: + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + "Gzip compression not supported by this file type."); + break; + default: simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "The file \"%s\" could not be %s: %s.", @@ -157,9 +157,10 @@ cf_read_status_t cf_finish_tail(capture_file *cf, int *err); * @param fname the filename to save to * @param range the range of packets to save * @param save_format the format of the file to save (libpcap, ...) + * @param compressed wether to gzip compress the file * @return one of cf_status_t */ -cf_status_t cf_save(capture_file * cf, const char *fname, packet_range_t *range, guint save_format); +cf_status_t cf_save(capture_file * cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed); /** * Get a displayable name of the capture file. diff --git a/gtk/file_dlg.c b/gtk/file_dlg.c index 7288dc8396..100b5bf193 100644 --- a/gtk/file_dlg.c +++ b/gtk/file_dlg.c @@ -1217,6 +1217,7 @@ static void select_file_type_cb(GtkWidget *w _U_, gpointer data) { int new_filetype = GPOINTER_TO_INT(data); + GtkWidget *compressed_cb; if (filetype != new_filetype) { /* We can select only the filtered or marked packets to be saved if we can @@ -1225,6 +1226,8 @@ select_file_type_cb(GtkWidget *w _U_, gpointer data) range_set_displayed_sensitive(range_tb, can_save_with_wiretap(new_filetype)); filetype = new_filetype; file_set_save_marked_sensitive(); + compressed_cb = OBJECT_GET_DATA(file_save_as_w, "compressed"); + gtk_widget_set_sensitive(compressed_cb, wtap_dump_can_compress(new_filetype)); } } @@ -1267,7 +1270,7 @@ gpointer action_after_save_data_g; void file_save_as_cmd(action_after_save_e action_after_save, gpointer action_after_save_data) { - GtkWidget *main_vb, *ft_hb, *ft_lb, *range_fr; + GtkWidget *main_vb, *ft_hb, *ft_lb, *range_fr, *compressed_cb; GtkTooltips *tooltips; #if GTK_MAJOR_VERSION < 2 @@ -1352,6 +1355,13 @@ file_save_as_cmd(action_after_save_e action_after_save, gpointer action_after_sa /* dynamic values in the range frame */ range_update_dynamics(range_tb); + /* compressed */ + compressed_cb = gtk_check_button_new_with_label("Compress with gzip"); + gtk_container_add(GTK_CONTAINER(ft_hb), compressed_cb); + gtk_widget_show(compressed_cb); + OBJECT_SET_DATA(file_save_as_w, "compressed", compressed_cb); + gtk_widget_set_sensitive(compressed_cb, wtap_dump_can_compress(cfile.cd_t)); + SIGNAL_CONNECT(file_save_as_w, "destroy", file_save_as_destroy_cb, NULL); #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2 @@ -1389,6 +1399,7 @@ static void file_save_as_cb(GtkWidget *w _U_, gpointer fs) { gchar *cf_name; gchar *dirname; + GtkWidget *compressed_cb; #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2 @@ -1397,9 +1408,12 @@ file_save_as_cb(GtkWidget *w _U_, gpointer fs) { cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs))); #endif + compressed_cb = OBJECT_GET_DATA(file_save_as_w, "compressed"); + /* Write out the packets (all, or only the ones from the current range) to the file with the specified name. */ - if (cf_save(&cfile, cf_name, &range, filetype) != CF_OK) { + if (cf_save(&cfile, cf_name, &range, filetype, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compressed_cb))) != CF_OK) { /* The write failed; don't dismiss the open dialog box, just leave it around so that the user can, after they dismiss the alert box popped up for the error, try again. */ diff --git a/mergecap.c b/mergecap.c index 83777a7ebe..9136e64930 100644 --- a/mergecap.c +++ b/mergecap.c @@ -301,7 +301,7 @@ main(int argc, char *argv[]) } /* prepare the outfile */ - pdh = wtap_dump_fdopen(out_fd, file_type, frame_type, snaplen, &open_err); + pdh = wtap_dump_fdopen(out_fd, file_type, frame_type, snaplen, FALSE /* compressed */, &open_err); if (pdh == NULL) { merge_close_in_files(in_file_count, in_files); free(in_files); @@ -482,7 +482,7 @@ main(int argc, char **argv) pkthdr.pkt_encap = example->sample_wtap_encap; dump = wtap_dump_open(produce_filename, WTAP_FILE_PCAP, - example->sample_wtap_encap, produce_max_bytes, &err); + example->sample_wtap_encap, produce_max_bytes, FALSE /* compressed */, &err); seed(); diff --git a/ringbuffer.c b/ringbuffer.c index 84d2983d57..4f1d5fe0da 100644 --- a/ringbuffer.c +++ b/ringbuffer.c @@ -241,7 +241,7 @@ ringbuf_init_wtap_dump_fdopen(int filetype, int linktype, int snaplen, int *err) rb_data.linktype = linktype; rb_data.snaplen = snaplen; - rb_data.pdh = wtap_dump_fdopen(rb_data.fd, filetype, linktype, snaplen, err); + rb_data.pdh = wtap_dump_fdopen(rb_data.fd, filetype, linktype, snaplen, FALSE /* compressed */, err); return rb_data.pdh; } diff --git a/tethereal.c b/tethereal.c index 3fe4974140..7b60c68157 100644 --- a/tethereal.c +++ b/tethereal.c @@ -1681,7 +1681,7 @@ capture(char *save_file, int out_file_type) } } else { ld.pdh = wtap_dump_open(save_file, out_file_type, - ld.linktype, file_snaplen, &err); + ld.linktype, file_snaplen, FALSE /* compress */, &err); } if (ld.pdh == NULL) { @@ -1846,7 +1846,7 @@ capture(char *save_file, int out_file_type) } if (ld.output_to_pipe) { if (ld.packet_count > packet_count_prev) { - if (fflush(wtap_dump_file(ld.pdh))) { + if (wtap_dump_file_flush(ld.pdh)) { volatile_err = errno; ld.go = FALSE; } @@ -2121,7 +2121,7 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type) snapshot_length = WTAP_MAX_PACKET_SIZE; } pdh = wtap_dump_open(save_file, out_file_type, - linktype, snapshot_length, &err); + linktype, snapshot_length, FALSE /* compressed */, &err); if (pdh == NULL) { /* We couldn't set up to write to the capture file. */ diff --git a/wiretap/file_access.c b/wiretap/file_access.c index 84705e29fd..08b4d72384 100644 --- a/wiretap/file_access.c +++ b/wiretap/file_access.c @@ -338,175 +338,176 @@ success: static const struct file_type_info { const char *name; const char *short_name; + gboolean can_compress; int (*can_write_encap)(int); int (*dump_open)(wtap_dumper *, gboolean, int *); } dump_open_table[WTAP_NUM_FILE_TYPES] = { /* WTAP_FILE_UNKNOWN */ - { NULL, NULL, + { NULL, NULL, FALSE, NULL, NULL }, /* WTAP_FILE_WTAP */ - { "Wiretap (Ethereal)", NULL, + { "Wiretap (Ethereal)", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_PCAP */ - { "libpcap (tcpdump, Ethereal, etc.)", "libpcap", + { "libpcap (tcpdump, Ethereal, etc.)", "libpcap", TRUE, libpcap_dump_can_write_encap, libpcap_dump_open }, /* WTAP_FILE_PCAP_SS990417 */ - { "RedHat Linux 6.1 libpcap (tcpdump)", "rh6_1libpcap", + { "RedHat Linux 6.1 libpcap (tcpdump)", "rh6_1libpcap", TRUE, libpcap_dump_can_write_encap, libpcap_dump_open }, /* WTAP_FILE_PCAP_SS990915 */ - { "SuSE Linux 6.3 libpcap (tcpdump)", "suse6_3libpcap", + { "SuSE Linux 6.3 libpcap (tcpdump)", "suse6_3libpcap", TRUE, libpcap_dump_can_write_encap, libpcap_dump_open }, /* WTAP_FILE_PCAP_SS991029 */ - { "modified libpcap (tcpdump)", "modlibpcap", + { "modified libpcap (tcpdump)", "modlibpcap", TRUE, libpcap_dump_can_write_encap, libpcap_dump_open }, /* WTAP_FILE_PCAP_NOKIA */ - { "Nokia libpcap (tcpdump)", "nokialibpcap", + { "Nokia libpcap (tcpdump)", "nokialibpcap", TRUE, libpcap_dump_can_write_encap, libpcap_dump_open }, /* WTAP_FILE_PCAP_AIX */ - { "AIX libpcap (tcpdump)", NULL, + { "AIX libpcap (tcpdump)", NULL, TRUE, NULL, NULL }, /* WTAP_FILE_PCAP_NSEC */ - { "Nanosecond libpcap (Ethereal)", "nseclibpcap", + { "Nanosecond libpcap (Ethereal)", "nseclibpcap", TRUE, libpcap_dump_can_write_encap, libpcap_dump_open }, /* WTAP_FILE_LANALYZER */ - { "Novell LANalyzer","lanalyzer", + { "Novell LANalyzer","lanalyzer", FALSE, lanalyzer_dump_can_write_encap, lanalyzer_dump_open }, /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */ - { "Network Associates Sniffer (DOS-based)", "ngsniffer", + { "Network Associates Sniffer (DOS-based)", "ngsniffer", FALSE, ngsniffer_dump_can_write_encap, ngsniffer_dump_open }, /* WTAP_FILE_NGSNIFFER_COMPRESSED */ - { "Network Associates Sniffer (DOS-based), compressed", "ngsniffer_comp", + { "Network Associates Sniffer (DOS-based), compressed", "ngsniffer_comp", FALSE, NULL, NULL }, /* WTAP_FILE_SNOOP */ - { "Sun snoop", "snoop", + { "Sun snoop", "snoop", FALSE, snoop_dump_can_write_encap, snoop_dump_open }, /* WTAP_FILE_SHOMITI */ - { "Shomiti/Finisar Surveyor", "shomiti", + { "Shomiti/Finisar Surveyor", "shomiti", FALSE, NULL, NULL }, /* WTAP_FILE_IPTRACE_1_0 */ - { "AIX iptrace 1.0", NULL, + { "AIX iptrace 1.0", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_IPTRACE_2_0 */ - { "AIX iptrace 2.0", NULL, + { "AIX iptrace 2.0", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_NETMON_1_x */ - { "Microsoft Network Monitor 1.x", "netmon1", + { "Microsoft Network Monitor 1.x", "netmon1", FALSE, netmon_dump_can_write_encap, netmon_dump_open }, /* WTAP_FILE_NETMON_2_x */ - { "Microsoft Network Monitor 2.x", "netmon2", + { "Microsoft Network Monitor 2.x", "netmon2", FALSE, netmon_dump_can_write_encap, netmon_dump_open }, /* WTAP_FILE_NETXRAY_OLD */ - { "Cinco Networks NetXRay 1.x", NULL, + { "Cinco Networks NetXRay 1.x", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_NETXRAY_1_0 */ - { "Cinco Networks NetXRay 2.0 or later", NULL, + { "Cinco Networks NetXRay 2.0 or later", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_NETXRAY_1_1 */ - { "Network Associates Sniffer (Windows-based) 1.1", "ngwsniffer_1_1", + { "Network Associates Sniffer (Windows-based) 1.1", "ngwsniffer_1_1", FALSE, netxray_dump_can_write_encap_1_1, netxray_dump_open_1_1 }, /* WTAP_FILE_NETXRAY_2_00x */ - { "Network Associates Sniffer (Windows-based) 2.00x", "ngwsniffer_2_0", + { "Network Associates Sniffer (Windows-based) 2.00x", "ngwsniffer_2_0", FALSE, netxray_dump_can_write_encap_2_0, netxray_dump_open_2_0 }, /* WTAP_FILE_RADCOM */ - { "RADCOM WAN/LAN analyzer", NULL, + { "RADCOM WAN/LAN analyzer", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_ASCEND */ - { "Lucent/Ascend access server trace", NULL, + { "Lucent/Ascend access server trace", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_NETTL */ - { "HP-UX nettl trace", "nettl", + { "HP-UX nettl trace", "nettl", FALSE, nettl_dump_can_write_encap, nettl_dump_open }, /* WTAP_FILE_TOSHIBA */ - { "Toshiba Compact ISDN Router snoop trace", NULL, + { "Toshiba Compact ISDN Router snoop trace", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_I4BTRACE */ - { "I4B ISDN trace", NULL, + { "I4B ISDN trace", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_CSIDS */ - { "CSIDS IPLog", NULL, + { "CSIDS IPLog", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_PPPDUMP */ - { "pppd log (pppdump format)", NULL, + { "pppd log (pppdump format)", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_ETHERPEEK_V56 */ - { "EtherPeek/TokenPeek trace (V5 & V6 file format)", NULL, + { "EtherPeek/TokenPeek trace (V5 & V6 file format)", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_ETHERPEEK_V7 */ - { "EtherPeek/TokenPeek/AiroPeek trace (V7 file format)", NULL, + { "EtherPeek/TokenPeek/AiroPeek trace (V7 file format)", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_VMS */ - { "TCPIPtrace (VMS)", NULL, + { "TCPIPtrace (VMS)", NULL, FALSE, NULL, NULL}, /* WTAP_FILE_DBS_ETHERWATCH */ - { "DBS Etherwatch (VMS)", NULL, + { "DBS Etherwatch (VMS)", NULL, FALSE, NULL, NULL}, /* WTAP_FILE_VISUAL_NETWORKS */ - { "Visual Networks traffic capture", "visual", + { "Visual Networks traffic capture", "visual", FALSE, visual_dump_can_write_encap, visual_dump_open }, /* WTAP_FILE_COSINE */ - { "CoSine IPSX L2 capture", "cosine", + { "CoSine IPSX L2 capture", "cosine", FALSE, NULL, NULL }, /* WTAP_FILE_5VIEWS */ - { "Accellent 5Views capture", "5views", + { "Accellent 5Views capture", "5views", FALSE, _5views_dump_can_write_encap, _5views_dump_open }, /* WTAP_FILE_ERF */ - { "Endace DAG capture", "erf", + { "Endace DAG capture", "erf", FALSE, NULL, NULL }, /* WTAP_FILE_HCIDUMP */ - { "Bluetooth HCI dump", "hcidump", + { "Bluetooth HCI dump", "hcidump", FALSE, NULL, NULL }, /* WTAP_FILE_NETWORK_INSTRUMENTS_V9 */ - { "Network Instruments Observer version 9", "niobserverv9", + { "Network Instruments Observer version 9", "niobserverv9", FALSE, network_instruments_dump_can_write_encap, network_instruments_dump_open }, /* WTAP_FILE_AIROPEEK_V9 */ - { "EtherPeek/AiroPeek trace (V9 file format)", NULL, + { "EtherPeek/AiroPeek trace (V9 file format)", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_EYESDN */ - { "EyeSDN USB S0/E1 ISDN trace format", NULL, + { "EyeSDN USB S0/E1 ISDN trace format", NULL, FALSE, NULL, NULL }, /* WTAP_FILE_K12 */ - { "Tektronix K12xx 32-bit .rf5 format", "rf5", + { "Tektronix K12xx 32-bit .rf5 format", "rf5", FALSE, k12_dump_can_write_encap, k12_dump_open }, }; @@ -563,29 +564,51 @@ gboolean wtap_dump_can_write_encap(int filetype, int encap) return TRUE; } -static gboolean wtap_dump_open_check(int filetype, int encap, int *err); +gboolean wtap_dump_can_compress(int filetype) +{ +#ifdef HAVE_LIBZ + if (filetype < 0 || filetype >= WTAP_NUM_FILE_TYPES + || dump_open_table[filetype].can_compress == FALSE) + return FALSE; + + return TRUE; +#else + return FALSE; +#endif +} + + +static gboolean wtap_dump_open_check(int filetype, int encap, gboolean comressed, int *err); static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen, - int *err); -static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, int *err); + gboolean compressed, int *err); +static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err); + +static FILE *wtap_dump_file_open(wtap_dumper *wdh, const char *filename); +static FILE *wtap_dump_file_fdopen(wtap_dumper *wdh, int fd); +static int wtap_dump_file_close(wtap_dumper *wdh); wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap, - int snaplen, int *err) + int snaplen, gboolean compressed, int *err) { wtap_dumper *wdh; FILE *fh; /* Check whether we can open a capture file with that file type and that encapsulation. */ - if (!wtap_dump_open_check(filetype, encap, err)) + if (!wtap_dump_open_check(filetype, encap, compressed, err)) return NULL; /* Allocate a data structure for the output stream. */ - wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, err); + wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err); if (wdh == NULL) return NULL; /* couldn't allocate it */ /* Empty filename means stdout */ if (*filename == '\0') { + if(compressed) { + g_free(wdh); + return NULL; /* compress won't work on stdout */ + } #ifdef _WIN32 setmode(fileno(stdout), O_BINARY); #endif @@ -594,56 +617,64 @@ wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap, /* In case "fopen()" fails but doesn't set "errno", set "errno" to a generic "the open failed" error. */ errno = WTAP_ERR_CANT_OPEN; - fh = fopen(filename, "wb"); + fh = wtap_dump_file_open(wdh, filename); if (fh == NULL) { *err = errno; + g_free(wdh); return NULL; /* can't create file */ } wdh->fh = fh; } - if (!wtap_dump_open_finish(wdh, filetype, err)) { + if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) { /* Get rid of the file we created; we couldn't finish opening it. */ - if (wdh->fh != stdout) + if (wdh->fh != stdout) { + wtap_dump_file_close(wdh); unlink(filename); + } + g_free(wdh); return NULL; } return wdh; } wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen, - int *err) + gboolean compressed, int *err) { wtap_dumper *wdh; FILE *fh; /* Check whether we can open a capture file with that file type and that encapsulation. */ - if (!wtap_dump_open_check(filetype, encap, err)) + if (!wtap_dump_open_check(filetype, encap, compressed, err)) return NULL; /* Allocate a data structure for the output stream. */ - wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, err); + wdh = wtap_dump_alloc_wdh(filetype, encap, snaplen, compressed, err); if (wdh == NULL) return NULL; /* couldn't allocate it */ /* In case "fopen()" fails but doesn't set "errno", set "errno" to a generic "the open failed" error. */ errno = WTAP_ERR_CANT_OPEN; - fh = fdopen(fd, "wb"); + fh = wtap_dump_file_fdopen(wdh, fd); if (fh == NULL) { *err = errno; + g_free(wdh); return NULL; /* can't create standard I/O stream */ } wdh->fh = fh; - if (!wtap_dump_open_finish(wdh, filetype, err)) + if (!wtap_dump_open_finish(wdh, filetype, compressed, err)) { + wtap_dump_file_close(wdh); + g_free(wdh); return NULL; + } return wdh; } -static gboolean wtap_dump_open_check(int filetype, int encap, int *err) +static gboolean wtap_dump_open_check(int filetype, int encap, gboolean compressed, int *err) { if (!wtap_dump_can_open(filetype)) { /* Invalid type, or type we don't know how to write. */ @@ -657,12 +688,23 @@ static gboolean wtap_dump_open_check(int filetype, int encap, int *err) if (*err != 0) return FALSE; + /* if compression is wanted, do we support this for this filetype? */ + if(compressed && !wtap_dump_can_compress(filetype)) { + *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED; + return FALSE; + } + + *err = (*dump_open_table[filetype].can_write_encap)(encap); + if (*err != 0) + return FALSE; + + /* All systems go! */ return TRUE; } static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen, - int *err) + gboolean compressed, int *err) { wtap_dumper *wdh; @@ -675,6 +717,7 @@ static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen, wdh->file_type = filetype; wdh->snaplen = snaplen; wdh->encap = encap; + wdh->compressed = compressed; wdh->bytes_dumped = 0; wdh->dump.opaque = NULL; wdh->subtype_write = NULL; @@ -682,49 +725,52 @@ static wtap_dumper* wtap_dump_alloc_wdh(int filetype, int encap, int snaplen, return wdh; } -static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, int *err) +static gboolean wtap_dump_open_finish(wtap_dumper *wdh, int filetype, gboolean compressed, int *err) { int fd; gboolean cant_seek; /* Can we do a seek on the file descriptor? If not, note that fact. */ - fd = fileno(wdh->fh); - if (lseek(fd, 1, SEEK_CUR) == -1) - cant_seek = TRUE; - else { - /* Undo the seek. */ - lseek(fd, 0, SEEK_SET); - cant_seek = FALSE; + if(compressed) { + cant_seek = TRUE; + } else { + fd = fileno(wdh->fh); + if (lseek(fd, 1, SEEK_CUR) == -1) + cant_seek = TRUE; + else { + /* Undo the seek. */ + lseek(fd, 0, SEEK_SET); + cant_seek = FALSE; + } } /* Now try to open the file for writing. */ if (!(*dump_open_table[filetype].dump_open)(wdh, cant_seek, err)) { - /* The attempt failed. Close the stream for the file. - NOTE: this means the FD handed to "wtap_dump_fdopen()" - will be closed if the open fails. */ - if (wdh->fh != stdout) - fclose(wdh->fh); - - /* Now free up the dumper handle. */ - g_free(wdh); return FALSE; } return TRUE; /* success! */ } -FILE* wtap_dump_file(wtap_dumper *wdh) -{ - return wdh->fh; -} - gboolean wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err) { return (wdh->subtype_write)(wdh, phdr, pseudo_header, pd, err); } +void wtap_dump_flush(wtap_dumper *wdh) +{ +#ifdef HAVE_LIBZ + if(wdh->compressed) { + gzflush(wdh->fh, Z_SYNC_FLUSH); /* XXX - is Z_SYNC_FLUSH the right one? */ + } else +#endif + { + fflush(wdh->fh); + } +} + gboolean wtap_dump_close(wtap_dumper *wdh, int *err) { gboolean ret = TRUE; @@ -737,7 +783,7 @@ gboolean wtap_dump_close(wtap_dumper *wdh, int *err) errno = WTAP_ERR_CANT_CLOSE; /* Don't close stdout */ if (wdh->fh != stdout) { - if (fclose(wdh->fh) == EOF) { + if (wtap_dump_file_close(wdh) == EOF) { if (ret) { /* The per-format close function succeeded, but the fclose didn't. Save the reason @@ -764,3 +810,77 @@ void wtap_set_bytes_dumped(wtap_dumper *wdh, long bytes_dumped) wdh->bytes_dumped = bytes_dumped; } + +/* internally open a file for writing (compressed or not) */ +static FILE *wtap_dump_file_open(wtap_dumper *wdh, const char *filename) +{ +#ifdef HAVE_LIBZ + if(wdh->compressed) { + return gzopen(filename, "wb"); + } else +#endif + { + return fopen(filename, "wb"); + } +} + +/* internally open a file for writing (compressed or not) */ +static FILE *wtap_dump_file_fdopen(wtap_dumper *wdh, int fd) +{ +#ifdef HAVE_LIBZ + if(wdh->compressed) { + return gzdopen(fd, "wb"); + } else +#endif + { + return fdopen(fd, "wb"); + } +} + +/* internally writing raw bytes (compressed or not) */ +size_t wtap_dump_file_write(wtap_dumper *wdh, const void *buf, unsigned bufsize) +{ +#ifdef HAVE_LIBZ + if(wdh->compressed) { + return gzwrite(wdh->fh, buf, bufsize); + } else +#endif + { + return fwrite(buf, 1, bufsize, wdh->fh); + } +} + +/* internally close a file for writing (compressed or not) */ +static int wtap_dump_file_close(wtap_dumper *wdh) +{ +#ifdef HAVE_LIBZ + if(wdh->compressed) { + return gzclose(wdh->fh); + } else +#endif + { + return fclose(wdh->fh); + } +} + +int wtap_dump_file_ferror(wtap_dumper *wdh) +{ +#ifdef HAVE_LIBZ + int errnum; + + if(wdh->compressed) { + gzerror(wdh->fh, &errnum); + + if(errnum == Z_ERRNO) { + return errno; + } else { + /* XXX - what to do with this zlib specific number? */ + return errnum; + } + } else +#endif + { + return ferror(wdh->fh); + } +} + diff --git a/wiretap/libpcap.c b/wiretap/libpcap.c index f3cbbe0f73..7226f78585 100644 --- a/wiretap/libpcap.c +++ b/wiretap/libpcap.c @@ -1991,10 +1991,10 @@ gboolean libpcap_dump_open(wtap_dumper *wdh, gboolean cant_seek _U_, int *err) return FALSE; } - nwritten = fwrite(&magic, 1, sizeof magic, wdh->fh); + nwritten = wtap_dump_file_write(wdh, &magic, sizeof magic); if (nwritten != sizeof magic) { - if (nwritten == 0 && ferror(wdh->fh)) - *err = errno; + if (nwritten == 0 && wtap_dump_file_ferror(wdh)) + *err = wtap_dump_file_ferror(wdh); else *err = WTAP_ERR_SHORT_WRITE; return FALSE; @@ -2020,10 +2020,10 @@ gboolean libpcap_dump_open(wtap_dumper *wdh, gboolean cant_seek _U_, int *err) file_hdr.snaplen = (wdh->snaplen != 0) ? wdh->snaplen : WTAP_MAX_PACKET_SIZE; file_hdr.network = wtap_wtap_encap_to_pcap_encap(wdh->encap); - nwritten = fwrite(&file_hdr, 1, sizeof file_hdr, wdh->fh); + nwritten = wtap_dump_file_write(wdh, &file_hdr, sizeof file_hdr); if (nwritten != sizeof file_hdr) { - if (nwritten == 0 && ferror(wdh->fh)) - *err = errno; + if (nwritten == 0 && wtap_dump_file_ferror(wdh)) + *err = wtap_dump_file_ferror(wdh); else *err = WTAP_ERR_SHORT_WRITE; return FALSE; @@ -2123,10 +2123,10 @@ static gboolean libpcap_dump(wtap_dumper *wdh, return FALSE; } - nwritten = fwrite(&rec_hdr, 1, hdr_size, wdh->fh); + nwritten = wtap_dump_file_write(wdh, &rec_hdr, hdr_size); if (nwritten != hdr_size) { - if (nwritten == 0 && ferror(wdh->fh)) - *err = errno; + if (nwritten == 0 && wtap_dump_file_ferror(wdh)) + *err = wtap_dump_file_ferror(wdh); else *err = WTAP_ERR_SHORT_WRITE; return FALSE; @@ -2168,10 +2168,10 @@ static gboolean libpcap_dump(wtap_dumper *wdh, } atm_hdr.vpi = (guint8) pseudo_header->atm.vpi; atm_hdr.vci = phtons(&pseudo_header->atm.vci); - nwritten = fwrite(&atm_hdr, 1, sizeof atm_hdr, wdh->fh); + nwritten = wtap_dump_file_write(wdh, &atm_hdr, sizeof atm_hdr); if (nwritten != sizeof atm_hdr) { - if (nwritten == 0 && ferror(wdh->fh)) - *err = errno; + if (nwritten == 0 && wtap_dump_file_ferror(wdh)) + *err = wtap_dump_file_ferror(wdh); else *err = WTAP_ERR_SHORT_WRITE; return FALSE; @@ -2185,10 +2185,10 @@ static gboolean libpcap_dump(wtap_dumper *wdh, memset(&irda_hdr, 0, sizeof(irda_hdr)); irda_hdr.sll_pkttype = phtons(&pseudo_header->irda.pkttype); irda_hdr.sll_protocol = g_htons(0x0017); - nwritten = fwrite(&irda_hdr, 1, sizeof(irda_hdr), wdh->fh); + nwritten = wtap_dump_file_write(wdh, &irda_hdr, sizeof(irda_hdr)); if (nwritten != sizeof(irda_hdr)) { - if (nwritten == 0 && ferror(wdh->fh)) - *err = errno; + if (nwritten == 0 && wtap_dump_file_ferror(wdh)) + *err = wtap_dump_file_ferror(wdh); else *err = WTAP_ERR_SHORT_WRITE; return FALSE; @@ -2203,10 +2203,10 @@ static gboolean libpcap_dump(wtap_dumper *wdh, mtp2_hdr.sent = pseudo_header->mtp2.sent; mtp2_hdr.annex_a_used = pseudo_header->mtp2.annex_a_used; mtp2_hdr.link_number = phtons(&pseudo_header->mtp2.link_number); - nwritten = fwrite(&mtp2_hdr, 1, sizeof(mtp2_hdr), wdh->fh); + nwritten = wtap_dump_file_write(wdh, &mtp2_hdr, sizeof(mtp2_hdr)); if (nwritten != sizeof(mtp2_hdr)) { - if (nwritten == 0 && ferror(wdh->fh)) - *err = errno; + if (nwritten == 0 && wtap_dump_file_ferror(wdh)) + *err = wtap_dump_file_ferror(wdh); else *err = WTAP_ERR_SHORT_WRITE; return FALSE; @@ -2214,10 +2214,10 @@ static gboolean libpcap_dump(wtap_dumper *wdh, wdh->bytes_dumped += sizeof(mtp2_hdr); } - nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh); + nwritten = wtap_dump_file_write(wdh, pd, phdr->caplen); if (nwritten != phdr->caplen) { - if (nwritten == 0 && ferror(wdh->fh)) - *err = errno; + if (nwritten == 0 && wtap_dump_file_ferror(wdh)) + *err = wtap_dump_file_ferror(wdh); else *err = WTAP_ERR_SHORT_WRITE; return FALSE; diff --git a/wiretap/wtap-int.h b/wiretap/wtap-int.h index 79f3d072f0..52680d5fe7 100644 --- a/wiretap/wtap-int.h +++ b/wiretap/wtap-int.h @@ -230,6 +230,7 @@ struct wtap_dumper { int file_type; int snaplen; int encap; + gboolean compressed; long bytes_dumped; union { @@ -249,6 +250,8 @@ struct wtap_dumper { * e.g. WTAP_FILE_TSPREC_USEC */ }; +extern size_t wtap_dump_file_write(wtap_dumper *wdh, const void *buf, unsigned bufsize); +extern int wtap_dump_file_ferror(wtap_dumper *wdh); /* Macros to byte-swap 32-bit and 16-bit quantities. */ #define BSWAP32(x) \ diff --git a/wiretap/wtap.def b/wiretap/wtap.def index 74d11b8cb1..1470e46055 100644 --- a/wiretap/wtap.def +++ b/wiretap/wtap.def @@ -4,9 +4,10 @@ wtap_close wtap_dump wtap_dump_can_open wtap_dump_can_write_encap +wtap_dump_can_compress wtap_dump_close wtap_dump_fdopen -wtap_dump_file +wtap_dump_flush wtap_dump_open wtap_encap_short_string wtap_encap_string diff --git a/wiretap/wtap.h b/wiretap/wtap.h index 916a7f8b00..81774048bf 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -572,13 +572,14 @@ gboolean wtap_seek_read (wtap *wth, long seek_off, gboolean wtap_dump_can_open(int filetype); gboolean wtap_dump_can_write_encap(int filetype, int encap); +gboolean wtap_dump_can_compress(int filetype); wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap, - int snaplen, int *err); + int snaplen, gboolean compressed, int *err); wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen, - int *err); + gboolean compressed, int *err); gboolean wtap_dump(wtap_dumper *, const struct wtap_pkthdr *, const union wtap_pseudo_header *pseudo_header, const guchar *, int *err); -FILE* wtap_dump_file(wtap_dumper *); +void wtap_dump_flush(wtap_dumper *); gboolean wtap_dump_close(wtap_dumper *, int *); long wtap_get_bytes_dumped(wtap_dumper *); void wtap_set_bytes_dumped(wtap_dumper *wdh, long bytes_dumped); @@ -624,6 +625,8 @@ void wtap_set_bytes_dumped(wtap_dumper *wdh, long bytes_dumped); /* LZ77 compressed data has bad offset to string */ #define WTAP_ERR_RANDOM_OPEN_STDIN -18 /* We're trying to open the standard input for random access */ +#define WTAP_ERR_COMPRESSION_NOT_SUPPORTED -19 + /* The filetype doesn't support output compression */ /* Errors from zlib; zlib error Z_xxx turns into Wiretap error WTAP_ERR_ZLIB + Z_xxx. |