X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=file.c;h=b83bd27138a89416670b20cda3e52abae1ea5582;hb=db02f99fdb6bbeb7ad872bbf836138ca3992ae7a;hp=4b66bb99c016beeaa58e7b57106ebd9929beedd3;hpb=8f8eeb5dcea62a1d4dd27cec193756844fe12c43;p=metze%2Fwireshark%2Fwip.git diff --git a/file.c b/file.c index 4b66bb99c0..b83bd27138 100644 --- a/file.c +++ b/file.c @@ -1,8 +1,6 @@ /* file.c * File I/O routines * - * $Id$ - * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs @@ -22,11 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" - -#ifdef HAVE_UNISTD_H -#include -#endif +#include #include @@ -35,15 +29,11 @@ #include #include #include -#include - -#ifdef HAVE_FCNTL_H -#include -#endif #include #include #include +#include #include @@ -58,7 +48,6 @@ #include #include #include -#include #include #include #include @@ -78,8 +67,6 @@ #include "ui/progress_dlg.h" #include "ui/ui_util.h" -#include "version_info.h" - /* Needed for addrinfo */ #ifdef HAVE_SYS_TYPES_H # include @@ -106,11 +93,9 @@ #endif #ifdef HAVE_LIBPCAP -gboolean auto_scroll_live; +gboolean auto_scroll_live; /* GTK+ only? */ #endif -static void cf_reset_state(capture_file *cf); - static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt, column_info *cinfo, gint64 offset); @@ -200,14 +185,14 @@ cf_callback_add(cf_callback_t func, gpointer user_data) } void -cf_callback_remove(cf_callback_t func) +cf_callback_remove(cf_callback_t func, gpointer user_data) { cf_callback_data_t *cb; GList *cb_item = cf_callbacks; while (cb_item != NULL) { cb = (cf_callback_data_t *)cb_item->data; - if (cb->cb_fct == func) { + if (cb->cb_fct == func && cb->user_data == user_data) { cf_callbacks = g_list_remove(cf_callbacks, cb); g_free(cb); return; @@ -222,46 +207,12 @@ void cf_timestamp_auto_precision(capture_file *cf) { int i; - int prec = timestamp_get_precision(); - /* don't try to get the file's precision if none is opened */ if (cf->state == FILE_CLOSED) { return; } - /* if we are in auto mode, set precision of current file */ - if (prec == TS_PREC_AUTO || - prec == TS_PREC_AUTO_SEC || - prec == TS_PREC_AUTO_DSEC || - prec == TS_PREC_AUTO_CSEC || - prec == TS_PREC_AUTO_MSEC || - prec == TS_PREC_AUTO_USEC || - prec == TS_PREC_AUTO_NSEC) - { - switch(wtap_file_tsprecision(cf->wth)) { - case(WTAP_FILE_TSPREC_SEC): - timestamp_set_precision(TS_PREC_AUTO_SEC); - break; - case(WTAP_FILE_TSPREC_DSEC): - timestamp_set_precision(TS_PREC_AUTO_DSEC); - break; - case(WTAP_FILE_TSPREC_CSEC): - timestamp_set_precision(TS_PREC_AUTO_CSEC); - break; - case(WTAP_FILE_TSPREC_MSEC): - timestamp_set_precision(TS_PREC_AUTO_MSEC); - break; - case(WTAP_FILE_TSPREC_USEC): - timestamp_set_precision(TS_PREC_AUTO_USEC); - break; - case(WTAP_FILE_TSPREC_NSEC): - timestamp_set_precision(TS_PREC_AUTO_NSEC); - break; - default: - g_assert_not_reached(); - } - } /* Set the column widths of those columns that show the time in "command-line-specified" format. */ for (i = 0; i < cf->cinfo.num_cols; i++) { @@ -336,12 +287,12 @@ ws_epan_new(capture_file *cf) } cf_status_t -cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) +cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err) { wtap *wth; gchar *err_info; - wth = wtap_open_offline(fname, err, &err_info, TRUE); + wth = wtap_open_offline(fname, type, err, &err_info, TRUE); if (wth == NULL) goto fail; @@ -349,9 +300,12 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) and fill in the information for this file. */ cf_close(cf); + /* Initialize the packet header. */ + wtap_phdr_init(&cf->phdr); + /* XXX - we really want to initialize this after we've read all the packets, so we know how much we'll ultimately need. */ - buffer_init(&cf->buf, 1500); + ws_buffer_init(&cf->buf, 1500); /* Create new epan session for dissection. * (The old one was freed in cf_close().) @@ -378,6 +332,7 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) cf->computed_elapsed = 0; cf->cd_t = wtap_file_type_subtype(cf->wth); + cf->open_type = type; cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1); cf->count = 0; cf->packet_comment_count = 0; @@ -441,22 +396,22 @@ cf_add_encapsulation_type(capture_file *cf, int encap) g_array_append_val(cf->linktypes, encap); } -/* - * Reset the state for the currently closed file, but don't do the - * UI callbacks; this is for use in "cf_open()", where we don't - * want the UI to go from "file open" to "file closed" back to - * "file open", we want it to go from "old file open" to "new file - * open and being read". - * - * XXX - currently, cf_open() calls cf_close(), rather than - * cf_reset_state(). - */ -static void -cf_reset_state(capture_file *cf) +/* Reset everything to a pristine state */ +void +cf_close(capture_file *cf) { + cf->stop_flag = FALSE; + if (cf->state == FILE_CLOSED) + return; /* Nothing to do */ + /* Die if we're in the middle of reading a file. */ g_assert(cf->state != FILE_READ_IN_PROGRESS); + cf_callback_invoke(cf_cb_file_closing, cf); + + /* close things, if not already closed before */ + color_filters_cleanup(); + if (cf->wth) { wtap_close(cf->wth); cf->wth = NULL; @@ -472,8 +427,14 @@ cf_reset_state(capture_file *cf) /* ...which means we have no changes to that file to save. */ cf->unsaved_changes = FALSE; + /* no open_routine type */ + cf->open_type = WTAP_TYPE_AUTO; + + /* Clean up the packet header. */ + wtap_phdr_cleanup(&cf->phdr); + /* Free up the packet buffer. */ - buffer_free(&cf->buf); + ws_buffer_free(&cf->buf); dfilter_free(cf->rfcode); cf->rfcode = NULL; @@ -502,8 +463,10 @@ cf_reset_state(capture_file *cf) cf->finfo_selected = NULL; /* No frame link-layer types, either. */ - g_array_free(cf->linktypes, TRUE); - cf->linktypes = NULL; + if (cf->linktypes != NULL) { + g_array_free(cf->linktypes, TRUE); + cf->linktypes = NULL; + } /* Clear the packet list. */ packet_list_freeze(); @@ -515,25 +478,13 @@ cf_reset_state(capture_file *cf) reset_tap_listeners(); + epan_free(cf->epan); + cf->epan = NULL; + /* We have no file open. */ cf->state = FILE_CLOSED; -} - -/* Reset everything to a pristine state */ -void -cf_close(capture_file *cf) -{ - if (cf->state != FILE_CLOSED) { - cf_callback_invoke(cf_cb_file_closing, cf); - - /* close things, if not already closed before */ - color_filters_cleanup(); - cf_reset_state(cf); - epan_free(cf->epan); - cf->epan = NULL; - cf_callback_invoke(cf_cb_file_closed, cf); - } + cf_callback_invoke(cf_cb_file_closed, cf); } static float @@ -575,7 +526,6 @@ cf_read(capture_file *cf, gboolean reloading) gchar *err_info; gchar *name_ptr; progdlg_t *progbar = NULL; - gboolean stop_flag; GTimeVal start_time; epan_dissect_t edt; dfilter_t *dfcode; @@ -587,7 +537,7 @@ cf_read(capture_file *cf, gboolean reloading) * We assume this will not fail since cf->dfilter is only set in * cf_filter IFF the filter was valid. */ - compiled = dfilter_compile(cf->dfilter, &dfcode); + compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); g_assert(!cf->dfilter || (compiled && dfcode)); /* Get the union of the flags for all tap listeners. */ @@ -611,7 +561,7 @@ cf_read(capture_file *cf, gboolean reloading) /* The packet list window will be empty until the file is completly loaded */ packet_list_freeze(); - stop_flag = FALSE; + cf->stop_flag = FALSE; g_get_current_time(&start_time); epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); @@ -661,10 +611,10 @@ cf_read(capture_file *cf, gboolean reloading) progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str)); if (reloading) progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr, - TRUE, &stop_flag, &start_time, progbar_val); + TRUE, &cf->stop_flag, &start_time, progbar_val); else progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr, - TRUE, &stop_flag, &start_time, progbar_val); + TRUE, &cf->stop_flag, &start_time, progbar_val); } /* Update the progress bar, but do it only N_PROGBAR_UPDATES times; @@ -690,7 +640,7 @@ cf_read(capture_file *cf, gboolean reloading) } } - if (stop_flag) { + if (cf->stop_flag) { /* Well, the user decided to abort the read. He/She will be warned and it might be enough for him/her to work with the already loaded packets. @@ -704,9 +654,9 @@ cf_read(capture_file *cf, gboolean reloading) } CATCH(OutOfMemoryError) { simple_message_box(ESD_TYPE_ERROR, NULL, - "Some infos / workarounds can be found at:\n" - "http://wiki.wireshark.org/KnownBugs/OutOfMemory", - "Sorry, but Wireshark has run out of memory and has to terminate now!"); + "More information and workarounds can be found at\n" + "https://wiki.wireshark.org/KnownBugs/OutOfMemory", + "Sorry, but Wireshark has run out of memory and has to terminate now."); #if 0 /* Could we close the current capture and free up memory from that? */ #else @@ -764,13 +714,13 @@ cf_read(capture_file *cf, gboolean reloading) packet_list_select_first_row(); } - if (stop_flag) { + if (cf->stop_flag) { simple_message_box(ESD_TYPE_WARN, NULL, "The remaining packets in the file were discarded.\n" "\n" "As a lot of packets from the original file will be missing,\n" "remember to be careful when saving the current content to a file.\n", - "File loading was cancelled!"); + "File loading was cancelled."); return CF_READ_ERROR; } @@ -783,23 +733,10 @@ cf_read(capture_file *cf, gboolean reloading) case WTAP_ERR_UNSUPPORTED: simple_error_message_box( "The capture file contains record data that Wireshark doesn't support.\n(%s)", - err_info); - g_free(err_info); - break; - - case WTAP_ERR_UNSUPPORTED_ENCAP: - simple_error_message_box( - "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)", - err_info); + err_info != NULL ? err_info : "no information supplied"); g_free(err_info); break; - case WTAP_ERR_CANT_READ: - simple_error_message_box( - "An attempt to read from the capture file failed for" - " some unknown reason."); - break; - case WTAP_ERR_SHORT_READ: simple_error_message_box( "The capture file appears to have been cut short" @@ -809,14 +746,14 @@ cf_read(capture_file *cf, gboolean reloading) case WTAP_ERR_BAD_FILE: simple_error_message_box( "The capture file appears to be damaged or corrupt.\n(%s)", - err_info); + err_info != NULL ? err_info : "no information supplied"); g_free(err_info); break; case WTAP_ERR_DECOMPRESS: simple_error_message_box( - "The compressed capture file appears to be damaged or corrupt.\n" - "(%s)", err_info); + "The compressed capture file appears to be damaged or corrupt.\n(%s)", + err_info != NULL ? err_info : "no information supplied"); g_free(err_info); break; @@ -836,10 +773,10 @@ cf_read_status_t cf_continue_tail(capture_file *cf, volatile int to_read, int *err) { gchar *err_info; - int newly_displayed_packets = 0; + volatile int newly_displayed_packets = 0; dfilter_t *dfcode; - epan_dissect_t edt; - gboolean create_proto_tree; + epan_dissect_t edt; + gboolean create_proto_tree; guint tap_flags; gboolean compiled; @@ -847,7 +784,7 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err) * We assume this will not fail since cf->dfilter is only set in * cf_filter IFF the filter was valid. */ - compiled = dfilter_compile(cf->dfilter, &dfcode); + compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); g_assert(!cf->dfilter || (compiled && dfcode)); /* Get the union of the flags for all tap listeners. */ @@ -890,9 +827,9 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err) } CATCH(OutOfMemoryError) { simple_message_box(ESD_TYPE_ERROR, NULL, - "Some infos / workarounds can be found at:\n" - "http://wiki.wireshark.org/KnownBugs/OutOfMemory", - "Sorry, but Wireshark has run out of memory and has to terminate now!"); + "More information and workarounds can be found at\n" + "https://wiki.wireshark.org/KnownBugs/OutOfMemory", + "Sorry, but Wireshark has run out of memory and has to terminate now."); #if 0 /* Could we close the current capture and free up memory from that? */ return CF_READ_ABORTED; @@ -940,10 +877,14 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err) } else if (*err != 0) { /* We got an error reading the capture file. XXX - pop up a dialog box instead? */ - g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")", - wtap_strerror(*err), err_info, cf->filename); - g_free(err_info); - + if (err_info != NULL) { + g_warning("Error \"%s\" while reading \"%s\" (\"%s\")", + wtap_strerror(*err), cf->filename, err_info); + g_free(err_info); + } else { + g_warning("Error \"%s\" while reading \"%s\"", + wtap_strerror(*err), cf->filename); + } return CF_READ_ERROR; } else return CF_READ_OK; @@ -970,7 +911,7 @@ cf_finish_tail(capture_file *cf, int *err) * We assume this will not fail since cf->dfilter is only set in * cf_filter IFF the filter was valid. */ - compiled = dfilter_compile(cf->dfilter, &dfcode); + compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); g_assert(!cf->dfilter || (compiled && dfcode)); /* Get the union of the flags for all tap listeners. */ @@ -1045,10 +986,14 @@ cf_finish_tail(capture_file *cf, int *err) if (*err != 0) { /* We got an error reading the capture file. XXX - pop up a dialog box? */ - - g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")", - wtap_strerror(*err), err_info, cf->filename); - g_free(err_info); + if (err_info != NULL) { + g_warning("Error \"%s\" while reading \"%s\" (\"%s\")", + wtap_strerror(*err), cf->filename, err_info); + g_free(err_info); + } else { + g_warning("Error \"%s\" while reading \"%s\"", + wtap_strerror(*err), cf->filename); + } return CF_READ_ERROR; } else { return CF_READ_OK; @@ -1109,13 +1054,6 @@ cf_get_packet_count(capture_file *cf) return cf->count; } -/* XXX - use a macro instead? */ -void -cf_set_packet_count(capture_file *cf, int packet_count) -{ - cf->count = packet_count; -} - /* XXX - use a macro instead? */ gboolean cf_is_tempfile(capture_file *cf) @@ -1174,7 +1112,7 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, } /* Dissect the frame. */ - epan_dissect_run_with_taps(edt, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo); + epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo); /* If we don't have a display filter, set "passed_dfilter" to 1. */ if (dfcode != NULL) { @@ -1261,7 +1199,7 @@ read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt, epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE); epan_dissect_prime_dfilter(&rf_edt, cf->rfcode); - epan_dissect_run(&rf_edt, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL); + epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL); passed = dfilter_apply_edt(cf->rfcode, &rf_edt); epan_dissect_cleanup(&rf_edt); } @@ -1284,373 +1222,189 @@ read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt, return row; } -cf_status_t -cf_merge_files(char **out_filenamep, int in_file_count, - char *const *in_filenames, int file_type, gboolean do_append) -{ - merge_in_file_t *in_files, *in_file; - char *out_filename; - char *tmpname; - int out_fd; - wtap_dumper *pdh; - int open_err, read_err, write_err, close_err; - gchar *err_info; - int err_fileno; - int i; - gboolean got_read_error = FALSE, got_write_error = FALSE; - gint64 data_offset; - progdlg_t *progbar = NULL; - gboolean stop_flag; - gint64 f_len, file_pos; - float progbar_val; - GTimeVal start_time; - gchar status_str[100]; + +typedef struct _callback_data_t { + gint64 f_len; gint64 progbar_nextstep; gint64 progbar_quantum; - gchar *display_basename; - int selected_frame_type; - gboolean fake_interface_ids = FALSE; - - /* open the input files */ - if (!merge_open_in_files(in_file_count, in_filenames, &in_files, - &open_err, &err_info, &err_fileno)) { - g_free(in_files); - cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info, - FALSE, 0); - return CF_ERROR; - } - - if (*out_filenamep != NULL) { - out_filename = *out_filenamep; - out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600); - if (out_fd == -1) - open_err = errno; - } else { - out_fd = create_tempfile(&tmpname, "wireshark"); - if (out_fd == -1) - open_err = errno; - out_filename = g_strdup(tmpname); - *out_filenamep = out_filename; - } - if (out_fd == -1) { - err_info = NULL; - merge_close_in_files(in_file_count, in_files); - g_free(in_files); - cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type); - return CF_ERROR; - } - - selected_frame_type = merge_select_frame_type(in_file_count, in_files); - - /* If we are trying to merge a number of libpcap files with different encapsulation types - * change the output file type to pcapng and create SHB and IDB:s for the new file use the - * interface index stored in in_files per file to change the phdr before writing the datablock. - * XXX should it be an option to convert to pcapng? - * - * We need something similar when merging pcapng files possibly with an option to say - * the same interface(s) used in all in files. SHBs comments should be merged together. - */ - if ((selected_frame_type == WTAP_ENCAP_PER_PACKET)&&(file_type == WTAP_FILE_TYPE_SUBTYPE_PCAP)) { - /* Write output in pcapng format */ - wtapng_section_t *shb_hdr; - wtapng_iface_descriptions_t *idb_inf, *idb_inf_merge_file; - wtapng_if_descr_t int_data, *file_int_data; - GString *comment_gstr; - - fake_interface_ids = TRUE; - /* Create SHB info */ - shb_hdr = wtap_file_get_shb_info(in_files[0].wth); - comment_gstr = g_string_new(""); - g_string_append_printf(comment_gstr, "%s \n",shb_hdr->opt_comment); - g_string_append_printf(comment_gstr, "File created by merging: \n"); - file_type = WTAP_FILE_TYPE_SUBTYPE_PCAPNG; - - for (i = 0; i < in_file_count; i++) { - g_string_append_printf(comment_gstr, "File%d: %s \n",i+1,in_files[i].filename); - } - shb_hdr->section_length = -1; - /* options */ - shb_hdr->opt_comment = g_string_free(comment_gstr, FALSE); /* NULL if not available */ - shb_hdr->shb_hardware = NULL; /* NULL if not available, UTF-8 string containing the */ - /* description of the hardware used to create this section. */ - shb_hdr->shb_os = NULL; /* NULL if not available, UTF-8 string containing the name */ - /* of the operating system used to create this section. */ - shb_hdr->shb_user_appl = "Wireshark"; /* NULL if not available, UTF-8 string containing the name */ - /* of the application used to create this section. */ - - /* create fake IDB info */ - idb_inf = g_new(wtapng_iface_descriptions_t,1); - idb_inf->number_of_interfaces = in_file_count; /* TODO make this the number of DIFFERENT encapsulation types - * check that snaplength is the same too? - */ - idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t)); - - for (i = 0; i < in_file_count; i++) { - idb_inf_merge_file = wtap_file_get_idb_info(in_files[i].wth); - /* read the interface data from the in file to our combined interfca data */ - file_int_data = &g_array_index (idb_inf_merge_file->interface_data, wtapng_if_descr_t, 0); - int_data.wtap_encap = file_int_data->wtap_encap; - int_data.time_units_per_second = file_int_data->time_units_per_second; - int_data.link_type = file_int_data->link_type; - int_data.snap_len = file_int_data->snap_len; - int_data.if_name = g_strdup(file_int_data->if_name); - int_data.opt_comment = NULL; - int_data.if_description = NULL; - int_data.if_speed = 0; - int_data.if_tsresol = 6; - int_data.if_filter_str = NULL; - int_data.bpf_filter_len = 0; - int_data.if_filter_bpf_bytes = NULL; - int_data.if_os = NULL; - int_data.if_fcslen = -1; - int_data.num_stat_entries = 0; /* Number of ISB:s */ - int_data.interface_statistics = NULL; - - g_array_append_val(idb_inf->interface_data, int_data); - g_free(idb_inf_merge_file); - - /* Set fake interface Id in per file data */ - in_files[i].interface_id = i; - } + GTimeVal start_time; + progdlg_t *progbar; + gboolean stop_flag; +} callback_data_t; - pdh = wtap_dump_fdopen_ng(out_fd, file_type, - selected_frame_type, - merge_max_snapshot_length(in_file_count, in_files), - FALSE /* compressed */, shb_hdr, idb_inf /* wtapng_iface_descriptions_t *idb_inf */, &open_err); - if (pdh == NULL) { - ws_close(out_fd); - merge_close_in_files(in_file_count, in_files); - g_free(in_files); - cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE, - file_type); - return CF_ERROR; - } +static gboolean +merge_callback(merge_event event, int num _U_, + const merge_in_file_t in_files[], const guint in_file_count, + void *data) +{ + guint i; + callback_data_t *cb_data = (callback_data_t*) data; - } else { + g_assert(cb_data != NULL); - pdh = wtap_dump_fdopen(out_fd, file_type, - selected_frame_type, - merge_max_snapshot_length(in_file_count, in_files), - FALSE /* compressed */, &open_err); - if (pdh == NULL) { - ws_close(out_fd); - merge_close_in_files(in_file_count, in_files); - g_free(in_files); - cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE, - file_type); - return CF_ERROR; - } - } + switch (event) { - /* Get the sum of the sizes of all the files. */ - f_len = 0; - for (i = 0; i < in_file_count; i++) - f_len += in_files[i].size; + case MERGE_EVENT_INPUT_FILES_OPENED: + /* do nothing */ + break; - /* Update the progress bar when it gets to this value. */ - progbar_nextstep = 0; - /* When we reach the value that triggers a progress bar update, - bump that value by this amount. */ - progbar_quantum = f_len/N_PROGBAR_UPDATES; - /* Progress so far. */ - progbar_val = 0.0f; + case MERGE_EVENT_FRAME_TYPE_SELECTED: + /* do nothing */ + break; - stop_flag = FALSE; - g_get_current_time(&start_time); + case MERGE_EVENT_READY_TO_MERGE: + /* Get the sum of the sizes of all the files. */ + for (i = 0; i < in_file_count; i++) + cb_data->f_len += in_files[i].size; - /* do the merge (or append) */ - for (;;) { - if (do_append) - in_file = merge_append_read_packet(in_file_count, in_files, &read_err, - &err_info); - else - in_file = merge_read_packet(in_file_count, in_files, &read_err, - &err_info); - if (in_file == NULL) { - /* EOF */ - break; - } + /* When we reach the value that triggers a progress bar update, + bump that value by this amount. */ + cb_data->progbar_quantum = cb_data->f_len / N_PROGBAR_UPDATES; - if (read_err != 0) { - /* I/O error reading from in_file */ - got_read_error = TRUE; + g_get_current_time(&cb_data->start_time); break; - } - - /* Get the sum of the data offsets in all of the files. */ - data_offset = 0; - for (i = 0; i < in_file_count; i++) - data_offset += in_files[i].data_offset; - /* Create the progress bar if necessary. - We check on every iteration of the loop, so that it takes no - longer than the standard time to create it (otherwise, for a - large file, we might take considerably longer than that standard - time in order to get to the next progress bar step). */ - if (progbar == NULL) { - progbar = delayed_create_progress_dlg(NULL, "Merging", "files", - FALSE, &stop_flag, &start_time, progbar_val); - } + case MERGE_EVENT_PACKET_WAS_READ: + { + gint64 data_offset = 0; - /* Update the progress bar, but do it only N_PROGBAR_UPDATES times; - when we update it, we have to run the GTK+ main loop to get it - to repaint what's pending, and doing so may involve an "ioctl()" - to see if there's any pending input from an X server, and doing - that for every packet can be costly, especially on a big file. */ - if (data_offset >= progbar_nextstep) { - /* Get the sum of the seek positions in all of the files. */ - file_pos = 0; + /* Get the sum of the data offsets in all of the files. */ + data_offset = 0; for (i = 0; i < in_file_count; i++) - file_pos += wtap_read_so_far(in_files[i].wth); - progbar_val = (gfloat) file_pos / (gfloat) f_len; - if (progbar_val > 1.0f) { - /* Some file probably grew while we were reading it. - That "shouldn't happen", so we'll just clip the progress - value at 1.0. */ - progbar_val = 1.0f; - } - if (progbar != NULL) { - g_snprintf(status_str, sizeof(status_str), - "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB", - file_pos / 1024, f_len / 1024); - update_progress_dlg(progbar, progbar_val, status_str); + data_offset += in_files[i].data_offset; + + /* Create the progress bar if necessary. + We check on every iteration of the loop, so that it takes no + longer than the standard time to create it (otherwise, for a + large file, we might take considerably longer than that standard + time in order to get to the next progress bar step). */ + if (cb_data->progbar == NULL) { + cb_data->progbar = delayed_create_progress_dlg(NULL, "Merging", "files", + FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f); } - progbar_nextstep += progbar_quantum; - } - if (stop_flag) { - /* Well, the user decided to abort the merge. */ - break; - } + /* Update the progress bar, but do it only N_PROGBAR_UPDATES times; + when we update it, we have to run the GTK+ main loop to get it + to repaint what's pending, and doing so may involve an "ioctl()" + to see if there's any pending input from an X server, and doing + that for every packet can be costly, especially on a big file. */ + if (data_offset >= cb_data->progbar_nextstep) { + float progbar_val; + gint64 file_pos = 0; + /* Get the sum of the seek positions in all of the files. */ + for (i = 0; i < in_file_count; i++) + file_pos += wtap_read_so_far(in_files[i].wth); + + progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len; + if (progbar_val > 1.0f) { + /* Some file probably grew while we were reading it. + That "shouldn't happen", so we'll just clip the progress + value at 1.0. */ + progbar_val = 1.0f; + } - /* If we have WTAP_ENCAP_PER_PACKET and the infiles are of type - * WTAP_FILE_TYPE_SUBTYPE_PCAP, we need to set the interface id - * in the paket header = the interface index we used in the IDBs - * interface description for this file(encapsulation type). - */ - if (fake_interface_ids) { - struct wtap_pkthdr *phdr; + if (cb_data->progbar != NULL) { + gchar status_str[100]; + g_snprintf(status_str, sizeof(status_str), + "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB", + file_pos / 1024, cb_data->f_len / 1024); + update_progress_dlg(cb_data->progbar, progbar_val, status_str); + } + cb_data->progbar_nextstep += cb_data->progbar_quantum; + } + } + break; - phdr = wtap_phdr(in_file->wth); - phdr->interface_id = in_file->interface_id; - phdr->presence_flags = phdr->presence_flags | WTAP_HAS_INTERFACE_ID; - } - if (!wtap_dump(pdh, wtap_phdr(in_file->wth), - wtap_buf_ptr(in_file->wth), &write_err)) { - got_write_error = TRUE; + case MERGE_EVENT_DONE: + /* We're done merging the files; destroy the progress bar if it was created. */ + if (cb_data->progbar != NULL) + destroy_progress_dlg(cb_data->progbar); break; - } } - /* We're done merging the files; destroy the progress bar if it was created. */ - if (progbar != NULL) - destroy_progress_dlg(progbar); + return cb_data->stop_flag; +} + + + +cf_status_t +cf_merge_files(char **out_filenamep, int in_file_count, + char *const *in_filenames, int file_type, gboolean do_append) +{ + char *out_filename; + char *tmpname; + int out_fd; + int err = 0; + gchar *err_info = NULL; + int err_fileno; + merge_result status; + merge_progress_callback_t cb; + - merge_close_in_files(in_file_count, in_files); - if (!got_write_error) { - if (!wtap_dump_close(pdh, &write_err)) - got_write_error = TRUE; + if (*out_filenamep != NULL) { + out_filename = *out_filenamep; + out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600); + if (out_fd == -1) + err = errno; } else { - /* - * We already got a write error; no need to report another - * write error on close. - * - * Don't overwrite the earlier write error. - */ - (void)wtap_dump_close(pdh, &close_err); + out_fd = create_tempfile(&tmpname, "wireshark"); + if (out_fd == -1) + err = errno; + out_filename = g_strdup(tmpname); + *out_filenamep = out_filename; + } + if (out_fd == -1) { + cf_open_failure_alert_box(out_filename, err, NULL, TRUE, file_type); + return CF_ERROR; } - if (got_read_error) { - /* - * Find the file on which we got the error, and report the error. - */ - for (i = 0; i < in_file_count; i++) { - if (in_files[i].state == GOT_ERROR) { - /* Put up a message box noting that a read failed somewhere along - the line. */ - display_basename = g_filename_display_basename(in_files[i].filename); - switch (read_err) { - - case WTAP_ERR_UNSUPPORTED_ENCAP: - simple_error_message_box( - "The capture file %s has a packet with a network type that Wireshark doesn't support.\n(%s)", - display_basename, err_info); - g_free(err_info); - break; - - case WTAP_ERR_CANT_READ: - simple_error_message_box( - "An attempt to read from the capture file %s failed for" - " some unknown reason.", display_basename); - break; + /* prepare our callback routine */ + cb.callback_func = merge_callback; + cb.data = g_malloc0(sizeof(callback_data_t)); - case WTAP_ERR_SHORT_READ: - simple_error_message_box( - "The capture file %s appears to have been cut short" - " in the middle of a packet.", display_basename); - break; + /* merge the files */ + status = merge_files(out_fd, out_filename, file_type, + (const char *const *) in_filenames, in_file_count, + do_append, IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */, + "Wireshark", &cb, &err, &err_info, &err_fileno); - case WTAP_ERR_BAD_FILE: - simple_error_message_box( - "The capture file %s appears to be damaged or corrupt.\n(%s)", - display_basename, err_info); - g_free(err_info); - break; + g_free(cb.data); - case WTAP_ERR_DECOMPRESS: - simple_error_message_box( - "The compressed capture file %s appears to be damaged or corrupt.\n" - "(%s)", display_basename, err_info); - g_free(err_info); - break; + switch (status) { + case MERGE_OK: + break; - default: - simple_error_message_box( - "An error occurred while reading the" - " capture file %s: %s.", - display_basename, wtap_strerror(read_err)); - break; - } - g_free(display_basename); - } - } - } + case MERGE_USER_ABORTED: + /* this isn't really an error, though we will return CF_ERROR later */ + break; - if (got_write_error) { - /* Put up an alert box for the write error. */ - if (write_err < 0) { - /* Wiretap error. */ - switch (write_err) { + case MERGE_ERR_CANT_OPEN_INFILE: + cf_open_failure_alert_box(in_filenames[err_fileno], err, err_info, + FALSE, 0); + ws_close(out_fd); + break; - case WTAP_ERR_UNSUPPORTED_ENCAP: - /* - * This is a problem with the particular frame we're writing; - * note that, and give the frame number. - */ - display_basename = g_filename_display_basename(in_file->filename); - simple_error_message_box( - "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.", - in_file->packet_num, display_basename, - wtap_file_type_subtype_string(file_type)); - g_free(display_basename); - break; + case MERGE_ERR_CANT_OPEN_OUTFILE: + cf_open_failure_alert_box(out_filename, err, err_info, TRUE, + file_type); + ws_close(out_fd); + break; - default: - display_basename = g_filename_display_basename(out_filename); - simple_error_message_box( - "An error occurred while writing to the file \"%s\": %s.", - out_filename, wtap_strerror(write_err)); - g_free(display_basename); - break; - } - } else { - /* OS error. */ - write_failure_alert_box(out_filename, write_err); - } + case MERGE_ERR_CANT_READ_INFILE: /* fall through */ + case MERGE_ERR_BAD_PHDR_INTERFACE_ID: + case MERGE_ERR_CANT_WRITE_OUTFILE: + case MERGE_ERR_CANT_CLOSE_OUTFILE: + default: + simple_error_message_box("%s", err_info ? err_info : "unknown error"); + break; } - if (got_read_error || got_write_error || stop_flag) { + g_free(err_info); + /* for general case, no need to close out_fd: file handle associated to this file + descriptor was already closed by the call to wtap_dump_close() in merge_files() */ + + if (status != MERGE_OK) { /* Callers aren't expected to treat an error or an explicit abort differently - we put up error dialogs ourselves, so they don't have to. */ @@ -1665,6 +1419,7 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force) const char *filter_new = dftext ? dftext : ""; const char *filter_old = cf->dfilter ? cf->dfilter : ""; dfilter_t *dfcode; + gchar *err_msg; GTimeVal start_time; /* if new filter equals old one, do nothing unless told to do so */ @@ -1684,12 +1439,13 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force) * and try to compile it. */ dftext = g_strdup(dftext); - if (!dfilter_compile(dftext, &dfcode)) { + if (!dfilter_compile(dftext, &dfcode, &err_msg)) { /* The attempt failed; report an error. */ simple_message_box(ESD_TYPE_ERROR, NULL, "See the help for a description of the display filter syntax.", "\"%s\" isn't a valid display filter: %s", - dftext, dfilter_error_msg); + dftext, err_msg); + g_free(err_msg); g_free(dftext); return CF_ERROR; } @@ -1710,10 +1466,12 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force) /* Now rescan the packet list, applying the new filter, but not throwing away information constructed on a previous pass. */ - if (dftext == NULL) { - rescan_packets(cf, "Resetting", "Filter", FALSE); - } else { - rescan_packets(cf, "Filtering", dftext, FALSE); + if (cf->state != FILE_CLOSED) { + if (dftext == NULL) { + rescan_packets(cf, "Resetting", "Filter", FALSE); + } else { + rescan_packets(cf, "Filtering", dftext, FALSE); + } } /* Cleanup and release all dfilter resources */ @@ -1737,8 +1495,8 @@ cf_redissect_packets(capture_file *cf) } gboolean -cf_read_frame_r(capture_file *cf, const frame_data *fdata, - struct wtap_pkthdr *phdr, Buffer *buf) +cf_read_record_r(capture_file *cf, const frame_data *fdata, + struct wtap_pkthdr *phdr, Buffer *buf) { int err; gchar *err_info; @@ -1750,13 +1508,13 @@ cf_read_frame_r(capture_file *cf, const frame_data *fdata, const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num)); if (!frame) { - simple_error_message_box("fdata->file_off == -1, but can't find modified frame!"); + simple_error_message_box("fdata->file_off == -1, but can't find modified frame."); return FALSE; } *phdr = frame->phdr; - buffer_assure_space(buf, frame->phdr.caplen); - memcpy(buffer_start_ptr(buf), frame->pd, frame->phdr.caplen); + ws_buffer_assure_space(buf, frame->phdr.caplen); + memcpy(ws_buffer_start_ptr(buf), frame->pd, frame->phdr.caplen); return TRUE; } #endif @@ -1765,15 +1523,10 @@ cf_read_frame_r(capture_file *cf, const frame_data *fdata, display_basename = g_filename_display_basename(cf->filename); switch (err) { - case WTAP_ERR_UNSUPPORTED_ENCAP: - simple_error_message_box("The file \"%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)", - display_basename, err_info); - g_free(err_info); - break; - case WTAP_ERR_BAD_FILE: simple_error_message_box("An error occurred while reading from the file \"%s\": %s.\n(%s)", - display_basename, wtap_strerror(err), err_info); + display_basename, wtap_strerror(err), + err_info != NULL ? err_info : "no information supplied"); g_free(err_info); break; @@ -1790,9 +1543,9 @@ cf_read_frame_r(capture_file *cf, const frame_data *fdata, } gboolean -cf_read_frame(capture_file *cf, frame_data *fdata) +cf_read_record(capture_file *cf, frame_data *fdata) { - return cf_read_frame_r(cf, fdata, &cf->phdr, &cf->buf); + return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf); } /* Rescan the list of packets, reconstructing the CList. @@ -1814,7 +1567,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb guint32 framenum; frame_data *fdata; progdlg_t *progbar = NULL; - gboolean stop_flag; int count; frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame; int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num; @@ -1837,7 +1589,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb * We assume this will not fail since cf->dfilter is only set in * cf_filter IFF the filter was valid. */ - compiled = dfilter_compile(cf->dfilter, &dfcode); + compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); g_assert(!cf->dfilter || (compiled && dfcode)); /* Get the union of the flags for all tap listeners. */ @@ -1873,6 +1625,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb /* 'reset' dissection session */ epan_free(cf->epan); cf->epan = ws_epan_new(cf); + cf->cinfo.epan = cf->epan; /* We need to redissect the packets so we have to discard our old * packet list store. */ @@ -1895,6 +1648,8 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb cf->prev_cap = NULL; cf->cum_bytes = 0; + cf_callback_invoke(cf_cb_file_rescan_started, cf); + /* Update the progress bar when it gets to this value. */ progbar_nextstep = 0; /* When we reach the value that triggers a progress bar update, @@ -1905,7 +1660,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb /* Progress so far. */ progbar_val = 0.0f; - stop_flag = FALSE; + cf->stop_flag = FALSE; g_get_current_time(&start_time); /* no previous row yet */ @@ -1933,7 +1688,8 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb time in order to get to the next progress bar step). */ if (progbar == NULL) progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE, - &stop_flag, &start_time, + &cf->stop_flag, + &start_time, progbar_val); /* Update the progress bar, but do it only N_PROGBAR_UPDATES times; @@ -1957,7 +1713,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb progbar_nextstep += progbar_quantum; } - if (stop_flag) { + if (cf->stop_flag) { /* Well, the user decided to abort the filtering. Just stop. XXX - go back to the previous filter? Users probably just @@ -1987,7 +1743,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb /* Frame dependencies from the previous dissection/filtering are no longer valid. */ fdata->flags.dependent_of_displayed = 0; - if (!cf_read_frame(cf, fdata)) + if (!cf_read_record(cf, fdata)) break; /* error reading the frame */ /* If the previous frame is displayed, and we haven't yet seen the @@ -2000,7 +1756,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb add_packet_to_packet_list(fdata, cf, &edt, dfcode, cinfo, &cf->phdr, - buffer_start_ptr(&cf->buf), + ws_buffer_start_ptr(&cf->buf), add_to_packet_list); /* If this frame is displayed, and this is the first frame we've @@ -2059,6 +1815,8 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb packet_list_thaw(); + cf_callback_invoke(cf_cb_file_rescan_finished, cf); + if (selected_frame_num == -1) { /* The selected frame didn't pass the filter. */ if (selected_frame == NULL) { @@ -2113,7 +1871,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb so we can't select it. */ simple_message_box(ESD_TYPE_INFO, NULL, "The capture file is probably not fully dissected.", - "End of capture exceeded!"); + "End of capture exceeded."); } } } @@ -2192,7 +1950,7 @@ ref_time_packets(capture_file *cf) if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) { /* This frame either passed the display filter list or is marked as a time reference frame. All time reference frames are displayed - even if they dont pass the display filter */ + even if they don't pass the display filter */ if (fdata->flags.ref_time) { /* if this was a TIME REF frame we should reset the cum_bytes field */ cf->cum_bytes = fdata->pkt_len; @@ -2212,7 +1970,7 @@ typedef enum { } psp_return_t; static psp_return_t -process_specified_packets(capture_file *cf, packet_range_t *range, +process_specified_records(capture_file *cf, packet_range_t *range, const char *string1, const char *string2, gboolean terminate_is_stop, gboolean (*callback)(capture_file *, frame_data *, struct wtap_pkthdr *, const guint8 *, void *), @@ -2226,7 +1984,6 @@ process_specified_packets(capture_file *cf, packet_range_t *range, progdlg_t *progbar = NULL; int progbar_count; float progbar_val; - gboolean progbar_stop_flag; GTimeVal progbar_start_time; gchar progbar_status_str[100]; int progbar_nextstep; @@ -2234,8 +1991,8 @@ process_specified_packets(capture_file *cf, packet_range_t *range, range_process_e process_this; struct wtap_pkthdr phdr; - memset(&phdr, 0, sizeof(struct wtap_pkthdr)); - buffer_init(&buf, 1500); + wtap_phdr_init(&phdr); + ws_buffer_init(&buf, 1500); /* Update the progress bar when it gets to this value. */ progbar_nextstep = 0; @@ -2247,7 +2004,7 @@ process_specified_packets(capture_file *cf, packet_range_t *range, /* Progress so far. */ progbar_val = 0.0f; - progbar_stop_flag = FALSE; + cf->stop_flag = FALSE; g_get_current_time(&progbar_start_time); if (range != NULL) @@ -2266,7 +2023,7 @@ process_specified_packets(capture_file *cf, packet_range_t *range, if (progbar == NULL) progbar = delayed_create_progress_dlg(cf->window, string1, string2, terminate_is_stop, - &progbar_stop_flag, + &cf->stop_flag, &progbar_start_time, progbar_val); @@ -2291,7 +2048,7 @@ process_specified_packets(capture_file *cf, packet_range_t *range, progbar_nextstep += progbar_quantum; } - if (progbar_stop_flag) { + if (cf->stop_flag) { /* Well, the user decided to abort the operation. Just stop, and arrange to return PSP_STOPPED to our caller, so they know it was stopped explicitly. */ @@ -2314,13 +2071,13 @@ process_specified_packets(capture_file *cf, packet_range_t *range, } /* Get the packet */ - if (!cf_read_frame_r(cf, fdata, &phdr, &buf)) { + if (!cf_read_record_r(cf, fdata, &phdr, &buf)) { /* Attempt to get the packet failed. */ ret = PSP_FAILED; break; } /* Process the packet */ - if (!callback(cf, fdata, &phdr, buffer_start_ptr(&buf), callback_args)) { + if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) { /* Callback failed. We assume it reported the error appropriately. */ ret = PSP_FAILED; break; @@ -2332,7 +2089,8 @@ process_specified_packets(capture_file *cf, packet_range_t *range, if (progbar != NULL) destroy_progress_dlg(progbar); - buffer_free(&buf); + wtap_phdr_cleanup(&phdr); + ws_buffer_free(&buf); return ret; } @@ -2343,13 +2101,13 @@ typedef struct { } retap_callback_args_t; static gboolean -retap_packet(capture_file *cf _U_, frame_data *fdata, +retap_packet(capture_file *cf, frame_data *fdata, struct wtap_pkthdr *phdr, const guint8 *pd, void *argsp) { retap_callback_args_t *args = (retap_callback_args_t *)argsp; - epan_dissect_run_with_taps(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo); + epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo); epan_dissect_reset(&args->edt); return TRUE; @@ -2365,6 +2123,13 @@ cf_retap_packets(capture_file *cf) guint tap_flags; psp_return_t ret; + /* Presumably the user closed the capture file. */ + if (cf == NULL) { + return CF_READ_ABORTED; + } + + cf_callback_invoke(cf_cb_file_retap_started, cf); + /* Do we have any tap listeners with filters? */ filtering_tap_listeners = have_filtering_tap_listeners(); @@ -2388,12 +2153,14 @@ cf_retap_packets(capture_file *cf) packet_range_init(&range, cf); packet_range_process_init(&range); - ret = process_specified_packets(cf, &range, "Recalculating statistics on", + ret = process_specified_records(cf, &range, "Recalculating statistics on", "all packets", TRUE, retap_packet, &callback_args); epan_dissect_cleanup(&callback_args.edt); + cf_callback_invoke(cf_cb_file_retap_finished, cf); + switch (ret) { case PSP_FINISHED: /* Completed successfully. */ @@ -2441,15 +2208,16 @@ print_packet(capture_file *cf, frame_data *fdata, int cp_off; char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */ char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */ + col_item_t* col_item; /* Fill in the column information if we're printing the summary information. */ if (args->print_args->print_summary) { col_custom_prime_edt(&args->edt, &cf->cinfo); - epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo); + epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo); epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); } else - epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL); + epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL); if (args->print_formfeed) { if (!new_page(args->print_args->stream)) @@ -2478,8 +2246,9 @@ print_packet(capture_file *cf, frame_data *fdata, cp = &args->line_buf[0]; line_len = 0; for (i = 0; i < args->num_visible_cols; i++) { + col_item = &cf->cinfo.columns[args->visible_cols[i]]; /* Find the length of the string for this column. */ - column_len = (int) strlen(cf->cinfo.col_data[args->visible_cols[i]]); + column_len = (int) strlen(col_item->col_data); if (args->col_widths[i] > column_len) column_len = args->col_widths[i]; @@ -2494,10 +2263,10 @@ print_packet(capture_file *cf, frame_data *fdata, } /* Right-justify the packet number column. */ - if (cf->cinfo.col_fmt[args->visible_cols[i]] == COL_NUMBER) - g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]); + if (col_item->col_fmt == COL_NUMBER) + g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data); else - g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]); + g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data); cp += column_len; if (i != args->num_visible_cols - 1) *cp++ = ' '; @@ -2532,7 +2301,7 @@ print_packet(capture_file *cf, frame_data *fdata, } /* Print the information in that tree. */ - if (!proto_tree_print(args->print_args, &args->edt, args->print_args->stream)) + if (!proto_tree_print(args->print_args, &args->edt, NULL, args->print_args->stream)) goto fail; /* Print a blank line if we print anything after this (aka more than one packet). */ @@ -2599,7 +2368,7 @@ cf_print_packets(capture_file *cf, print_args_t *print_args) callback_args.num_visible_cols = 0; callback_args.visible_cols = NULL; - if (!print_preamble(print_args->stream, cf->filename, wireshark_svnversion)) { + if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) { destroy_print_stream(print_args->stream); return CF_PRINT_WRITE_ERROR; } @@ -2649,14 +2418,14 @@ cf_print_packets(capture_file *cf, print_args_t *print_args) if (i == last_visible_col) callback_args.col_widths[visible_col_count] = 0; else { - callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.col_title[i]); + callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title); data_width = get_column_char_width(get_column_format(i)); if (data_width > callback_args.col_widths[visible_col_count]) callback_args.col_widths[visible_col_count] = data_width; } /* Find the length of the string for this column. */ - column_len = (int) strlen(cf->cinfo.col_title[i]); + column_len = (int) strlen(cf->cinfo.columns[i].col_title); if (callback_args.col_widths[i] > column_len) column_len = callback_args.col_widths[visible_col_count]; @@ -2673,9 +2442,9 @@ cf_print_packets(capture_file *cf, print_args_t *print_args) /* Right-justify the packet number column. */ /* if (cf->cinfo.col_fmt[i] == COL_NUMBER) - g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]); + g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title); else*/ - g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]); + g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title); cp += column_len; if (i != cf->cinfo.num_cols - 1) *cp++ = ' '; @@ -2701,7 +2470,7 @@ cf_print_packets(capture_file *cf, print_args_t *print_args) /* Iterate through the list of packets, printing the packets we were told to print. */ - ret = process_specified_packets(cf, &print_args->range, "Printing", + ret = process_specified_records(cf, &print_args->range, "Printing", "selected packets", TRUE, print_packet, &callback_args); epan_dissect_cleanup(&callback_args.edt); @@ -2753,17 +2522,17 @@ typedef struct { } write_packet_callback_args_t; static gboolean -write_pdml_packet(capture_file *cf _U_, frame_data *fdata, +write_pdml_packet(capture_file *cf, frame_data *fdata, struct wtap_pkthdr *phdr, const guint8 *pd, void *argsp) { write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; /* Create the protocol tree, but don't fill in the column information. */ - epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL); + epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL); /* Write out the information in that tree. */ - proto_tree_write_pdml(&args->edt, args->fh); + write_pdml_proto_tree(&args->edt, args->fh); epan_dissect_reset(&args->edt); @@ -2792,7 +2561,7 @@ cf_write_pdml_packets(capture_file *cf, print_args_t *print_args) /* Iterate through the list of packets, printing the packets we were told to print. */ - ret = process_specified_packets(cf, &print_args->range, "Writing PDML", + ret = process_specified_records(cf, &print_args->range, "Writing PDML", "selected packets", TRUE, write_pdml_packet, &callback_args); @@ -2833,12 +2602,13 @@ write_psml_packet(capture_file *cf, frame_data *fdata, { write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; + /* Fill in the column information */ col_custom_prime_edt(&args->edt, &cf->cinfo); - epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo); + epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo); epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); - /* Write out the information in that tree. */ - proto_tree_write_psml(&args->edt, args->fh); + /* Write out the column information. */ + write_psml_columns(&args->edt, args->fh); epan_dissect_reset(&args->edt); @@ -2858,7 +2628,7 @@ cf_write_psml_packets(capture_file *cf, print_args_t *print_args) if (fh == NULL) return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ - write_psml_preamble(fh); + write_psml_preamble(&cf->cinfo, fh); if (ferror(fh)) { fclose(fh); return CF_PRINT_WRITE_ERROR; @@ -2873,7 +2643,7 @@ cf_write_psml_packets(capture_file *cf, print_args_t *print_args) /* Iterate through the list of packets, printing the packets we were told to print. */ - ret = process_specified_packets(cf, &print_args->range, "Writing PSML", + ret = process_specified_records(cf, &print_args->range, "Writing PSML", "selected packets", TRUE, write_psml_packet, &callback_args); @@ -2916,11 +2686,11 @@ write_csv_packet(capture_file *cf, frame_data *fdata, /* Fill in the column information */ col_custom_prime_edt(&args->edt, &cf->cinfo); - epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo); + epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo); epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); - /* Write out the information in that tree. */ - proto_tree_write_csv(&args->edt, args->fh); + /* Write out the column information. */ + write_csv_columns(&args->edt, args->fh); epan_dissect_reset(&args->edt); @@ -2939,7 +2709,7 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args) if (fh == NULL) return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ - write_csv_preamble(fh); + write_csv_column_titles(&cf->cinfo, fh); if (ferror(fh)) { fclose(fh); return CF_PRINT_WRITE_ERROR; @@ -2953,7 +2723,7 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args) /* Iterate through the list of packets, printing the packets we were told to print. */ - ret = process_specified_packets(cf, &print_args->range, "Writing CSV", + ret = process_specified_records(cf, &print_args->range, "Writing CSV", "selected packets", TRUE, write_csv_packet, &callback_args); @@ -2975,12 +2745,6 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args) return CF_PRINT_WRITE_ERROR; } - write_csv_finale(fh); - if (ferror(fh)) { - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - /* XXX - check for an error */ fclose(fh); @@ -2988,14 +2752,14 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args) } static gboolean -write_carrays_packet(capture_file *cf _U_, frame_data *fdata, +carrays_write_packet(capture_file *cf, frame_data *fdata, struct wtap_pkthdr *phdr, const guint8 *pd, void *argsp) { write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; - epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL); - proto_tree_write_carrays(fdata->num, args->fh, &args->edt); + epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL); + write_carrays_hex_data(fdata->num, args->fh, &args->edt); epan_dissect_reset(&args->edt); return !ferror(args->fh); @@ -3013,8 +2777,6 @@ cf_write_carrays_packets(capture_file *cf, print_args_t *print_args) if (fh == NULL) return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ - write_carrays_preamble(fh); - if (ferror(fh)) { fclose(fh); return CF_PRINT_WRITE_ERROR; @@ -3025,10 +2787,10 @@ cf_write_carrays_packets(capture_file *cf, print_args_t *print_args) /* Iterate through the list of packets, printing the packets we were told to print. */ - ret = process_specified_packets(cf, &print_args->range, + ret = process_specified_records(cf, &print_args->range, "Writing C Arrays", "selected packets", TRUE, - write_carrays_packet, &callback_args); + carrays_write_packet, &callback_args); epan_dissect_cleanup(&callback_args.edt); @@ -3045,13 +2807,6 @@ cf_write_carrays_packets(capture_file *cf, print_args_t *print_args) return CF_PRINT_WRITE_ERROR; } - write_carrays_finale(fh); - - if (ferror(fh)) { - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - fclose(fh); return CF_PRINT_OK; } @@ -3086,7 +2841,7 @@ match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion) epan_dissect_t edt; /* Load the frame's data. */ - if (!cf_read_frame(cf, fdata)) { + if (!cf_read_record(cf, fdata)) { /* Attempt to get the packet failed. */ return MR_ERROR; } @@ -3094,7 +2849,7 @@ match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion) /* Construct the protocol tree, including the displayed text */ epan_dissect_init(&edt, cf->epan, TRUE, TRUE); /* We don't need the column information */ - epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL); + epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL); /* Iterate through all the nodes, seeing if they have text that matches. */ mdata->cf = cf; @@ -3145,7 +2900,7 @@ match_subtree_text(proto_node *node, gpointer data) for (i = 0; i < label_len; i++) { c_char = label_ptr[i]; if (cf->case_type) - c_char = toupper(c_char); + c_char = g_ascii_toupper(c_char); if (c_char == string[c_match]) { c_match++; if (c_match == string_len) { @@ -3190,7 +2945,7 @@ match_summary_line(capture_file *cf, frame_data *fdata, void *criterion) size_t c_match = 0; /* Load the frame's data. */ - if (!cf_read_frame(cf, fdata)) { + if (!cf_read_record(cf, fdata)) { /* Attempt to get the packet failed. */ return MR_ERROR; } @@ -3198,19 +2953,19 @@ match_summary_line(capture_file *cf, frame_data *fdata, void *criterion) /* Don't bother constructing the protocol tree */ epan_dissect_init(&edt, cf->epan, FALSE, FALSE); /* Get the column information */ - epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, + epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, &cf->cinfo); /* Find the Info column */ for (colx = 0; colx < cf->cinfo.num_cols; colx++) { - if (cf->cinfo.fmt_matx[colx][COL_INFO]) { + if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) { /* Found it. See if we match. */ - info_column = edt.pi.cinfo->col_data[colx]; + info_column = edt.pi.cinfo->columns[colx].col_data; info_column_len = strlen(info_column); for (i = 0; i < info_column_len; i++) { c_char = info_column[i]; if (cf->case_type) - c_char = toupper(c_char); + c_char = g_ascii_toupper(c_char); if (c_char == string[c_match]) { c_match++; if (c_match == string_len) { @@ -3288,19 +3043,19 @@ match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion) size_t c_match = 0; /* Load the frame's data. */ - if (!cf_read_frame(cf, fdata)) { + if (!cf_read_record(cf, fdata)) { /* Attempt to get the packet failed. */ return MR_ERROR; } result = MR_NOTMATCHED; buf_len = fdata->cap_len; - pd = buffer_start_ptr(&cf->buf); + pd = ws_buffer_start_ptr(&cf->buf); i = 0; while (i < buf_len) { c_char = pd[i]; if (cf->case_type) - c_char = toupper(c_char); + c_char = g_ascii_toupper(c_char); if (c_char != '\0') { if (c_char == ascii_text[c_match]) { c_match += 1; @@ -3336,19 +3091,19 @@ match_narrow(capture_file *cf, frame_data *fdata, void *criterion) size_t c_match = 0; /* Load the frame's data. */ - if (!cf_read_frame(cf, fdata)) { + if (!cf_read_record(cf, fdata)) { /* Attempt to get the packet failed. */ return MR_ERROR; } result = MR_NOTMATCHED; buf_len = fdata->cap_len; - pd = buffer_start_ptr(&cf->buf); + pd = ws_buffer_start_ptr(&cf->buf); i = 0; while (i < buf_len) { c_char = pd[i]; if (cf->case_type) - c_char = toupper(c_char); + c_char = g_ascii_toupper(c_char); if (c_char == ascii_text[c_match]) { c_match += 1; if (c_match == textlen) { @@ -3383,19 +3138,19 @@ match_wide(capture_file *cf, frame_data *fdata, void *criterion) size_t c_match = 0; /* Load the frame's data. */ - if (!cf_read_frame(cf, fdata)) { + if (!cf_read_record(cf, fdata)) { /* Attempt to get the packet failed. */ return MR_ERROR; } result = MR_NOTMATCHED; buf_len = fdata->cap_len; - pd = buffer_start_ptr(&cf->buf); + pd = ws_buffer_start_ptr(&cf->buf); i = 0; while (i < buf_len) { c_char = pd[i]; if (cf->case_type) - c_char = toupper(c_char); + c_char = g_ascii_toupper(c_char); if (c_char == ascii_text[c_match]) { c_match += 1; if (c_match == textlen) { @@ -3429,14 +3184,14 @@ match_binary(capture_file *cf, frame_data *fdata, void *criterion) size_t c_match = 0; /* Load the frame's data. */ - if (!cf_read_frame(cf, fdata)) { + if (!cf_read_record(cf, fdata)) { /* Attempt to get the packet failed. */ return MR_ERROR; } result = MR_NOTMATCHED; buf_len = fdata->cap_len; - pd = buffer_start_ptr(&cf->buf); + pd = ws_buffer_start_ptr(&cf->buf); i = 0; while (i < buf_len) { if (pd[i] == binary_data[c_match]) { @@ -3472,7 +3227,7 @@ cf_find_packet_dfilter_string(capture_file *cf, const char *filter, dfilter_t *sfcode; gboolean result; - if (!dfilter_compile(filter, &sfcode)) { + if (!dfilter_compile(filter, &sfcode, NULL)) { /* * XXX - this shouldn't happen, as the filter string is machine * generated @@ -3499,14 +3254,14 @@ match_dfilter(capture_file *cf, frame_data *fdata, void *criterion) match_result result; /* Load the frame's data. */ - if (!cf_read_frame(cf, fdata)) { + if (!cf_read_record(cf, fdata)) { /* Attempt to get the packet failed. */ return MR_ERROR; } epan_dissect_init(&edt, cf->epan, TRUE, FALSE); epan_dissect_prime_dfilter(&edt, sfcode); - epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL); + epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL); result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED; epan_dissect_cleanup(&edt); return result; @@ -3546,7 +3301,6 @@ find_packet(capture_file *cf, frame_data *fdata; frame_data *new_fd = NULL; progdlg_t *progbar = NULL; - gboolean stop_flag; int count; gboolean found; float progbar_val; @@ -3573,7 +3327,7 @@ find_packet(capture_file *cf, /* Progress so far. */ progbar_val = 0.0f; - stop_flag = FALSE; + cf->stop_flag = FALSE; g_get_current_time(&start_time); title = cf->sfilter?cf->sfilter:""; @@ -3585,7 +3339,7 @@ find_packet(capture_file *cf, time in order to get to the next progress bar step). */ if (progbar == NULL) progbar = delayed_create_progress_dlg(cf->window, "Searching", title, - FALSE, &stop_flag, &start_time, progbar_val); + FALSE, &cf->stop_flag, &start_time, progbar_val); /* Update the progress bar, but do it only N_PROGBAR_UPDATES times; when we update it, we have to run the GTK+ main loop to get it @@ -3609,7 +3363,7 @@ find_packet(capture_file *cf, progbar_nextstep += progbar_quantum; } - if (stop_flag) { + if (cf->stop_flag) { /* Well, the user decided to abort the search. Go back to the frame where we started. */ new_fd = start_fd; @@ -3701,7 +3455,7 @@ find_packet(capture_file *cf, so we can't select it. */ simple_message_box(ESD_TYPE_INFO, NULL, "The capture file is probably not fully dissected.", - "End of capture exceeded!"); + "End of capture exceeded."); return FALSE; } return TRUE; /* success */ @@ -3734,7 +3488,7 @@ cf_goto_frame(capture_file *cf, guint fnumber) so we can't select it. */ simple_message_box(ESD_TYPE_INFO, NULL, "The capture file is probably not fully dissected.", - "End of capture exceeded!"); + "End of capture exceeded."); return FALSE; } return TRUE; /* we got to that packet */ @@ -3825,7 +3579,7 @@ cf_select_packet(capture_file *cf, int row) } /* Get the data in that frame. */ - if (!cf_read_frame (cf, fdata)) { + if (!cf_read_record (cf, fdata)) { return; } @@ -3839,7 +3593,7 @@ cf_select_packet(capture_file *cf, int row) cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE); tap_build_interesting(cf->edt); - epan_dissect_run(cf->edt, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf), + epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf), cf->current_frame, NULL); dfilter_macro_build_ftv_cache(cf->edt->tree); @@ -3941,39 +3695,26 @@ cf_unignore_frame(capture_file *cf, frame_data *frame) const gchar * cf_read_shb_comment(capture_file *cf) { - wtapng_section_t *shb_inf; - const gchar *temp_str; - /* Get info from SHB */ - shb_inf = wtap_file_get_shb_info(cf->wth); - if (shb_inf == NULL) - return NULL; - temp_str = shb_inf->opt_comment; - g_free(shb_inf); - - return temp_str; - + return wtap_file_get_shb_comment(cf->wth); } void cf_update_capture_comment(capture_file *cf, gchar *comment) { - wtapng_section_t *shb_inf; + const gchar *shb_comment; /* Get info from SHB */ - shb_inf = wtap_file_get_shb_info(cf->wth); + shb_comment = wtap_file_get_shb_comment(cf->wth); /* See if the comment has changed or not */ - if (shb_inf && shb_inf->opt_comment) { - if (strcmp(shb_inf->opt_comment, comment) == 0) { + if (shb_comment) { + if (strcmp(shb_comment, comment) == 0) { g_free(comment); - g_free(shb_inf); return; } } - g_free(shb_inf); - /* The comment has changed, let's update it */ wtap_write_shb_comment(cf->wth, comment); /* Mark the file as having unsaved changes */ @@ -3993,6 +3734,8 @@ cf_get_user_packet_comment(capture_file *cf, const frame_data *fd) char * cf_get_comment(capture_file *cf, const frame_data *fd) { + char *comment; + /* fetch user comment */ if (fd->flags.has_user_comment) return g_strdup(cf_get_user_packet_comment(cf, fd)); @@ -4002,14 +3745,16 @@ cf_get_comment(capture_file *cf, const frame_data *fd) struct wtap_pkthdr phdr; /* Packet header */ Buffer buf; /* Packet data */ - phdr.opt_comment = NULL; + wtap_phdr_init(&phdr); + ws_buffer_init(&buf, 1500); - buffer_init(&buf, 1500); - if (!cf_read_frame_r(cf, fd, &phdr, &buf)) + if (!cf_read_record_r(cf, fd, &phdr, &buf)) { /* XXX, what we can do here? */ } - buffer_free(&buf); - return phdr.opt_comment; + comment = phdr.opt_comment; + wtap_phdr_cleanup(&phdr); + ws_buffer_free(&buf); + return comment; } return NULL; } @@ -4073,6 +3818,50 @@ cf_comment_types(capture_file *cf) return comment_types; } +#ifdef WANT_PACKET_EDITOR +static gint +g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_) +{ + if (a > b) + return 1; + else if (a < b) + return -1; + else + return 0; +} + +static void +modified_frame_data_free(gpointer data) +{ + modified_frame_data *mfd = (modified_frame_data *)data; + + g_free(mfd->pd); + g_free(mfd); +} + +/* + * Give a frame new, edited data. + */ +void +cf_set_frame_edited(capture_file *cf, frame_data *fd, + struct wtap_pkthdr *phdr, guint8 *pd) +{ + modified_frame_data *mfd = (modified_frame_data *)g_malloc(sizeof(modified_frame_data)); + + mfd->phdr = *phdr; + mfd->pd = pd; + + if (cf->edited_frames == NULL) + cf->edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL, + modified_frame_data_free); + g_tree_insert(cf->edited_frames, GINT_TO_POINTER(fd->num), mfd); + fd->file_off = -1; + + /* Mark the file as having unsaved changes */ + cf->unsaved_changes = TRUE; +} +#endif + typedef struct { wtap_dumper *pdh; const char *fname; @@ -4087,13 +3876,14 @@ typedef struct { * up a message box for the failure. */ static gboolean -save_packet(capture_file *cf _U_, frame_data *fdata, +save_record(capture_file *cf, frame_data *fdata, struct wtap_pkthdr *phdr, const guint8 *pd, void *argsp) { save_callback_args_t *args = (save_callback_args_t *)argsp; struct wtap_pkthdr hdr; int err; + gchar *err_info; gchar *display_basename; const char *pkt_comment; @@ -4115,6 +3905,7 @@ save_packet(capture_file *cf _U_, frame_data *fdata, For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length from the packet flags. */ + hdr.rec_type = phdr->rec_type; hdr.presence_flags = 0; if (fdata->flags.has_ts) hdr.presence_flags |= WTAP_HAS_TS; @@ -4124,8 +3915,8 @@ save_packet(capture_file *cf _U_, frame_data *fdata, hdr.presence_flags |= WTAP_HAS_PACK_FLAGS; hdr.ts.secs = fdata->abs_ts.secs; hdr.ts.nsecs = fdata->abs_ts.nsecs; - hdr.caplen = fdata->cap_len; - hdr.len = fdata->pkt_len; + hdr.caplen = phdr->caplen; + hdr.len = phdr->len; hdr.pkt_encap = fdata->lnk_t; /* pcapng */ hdr.interface_id = phdr->interface_id; /* identifier of the interface. */ @@ -4140,21 +3931,57 @@ save_packet(capture_file *cf _U_, frame_data *fdata, hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */ #endif /* and save the packet */ - if (!wtap_dump(args->pdh, &hdr, pd, &err)) { + if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) { if (err < 0) { /* Wiretap error. */ switch (err) { - case WTAP_ERR_UNSUPPORTED_ENCAP: + case WTAP_ERR_UNWRITABLE_ENCAP: /* - * This is a problem with the particular frame we're writing; - * note that, and give the frame number. + * This is a problem with the particular frame we're writing and + * the file type and subtype we're writing; note that, and report + * the frame number and file type/subtype. */ simple_error_message_box( "Frame %u has a network type that can't be saved in a \"%s\" file.", fdata->num, wtap_file_type_subtype_string(args->file_type)); break; + case WTAP_ERR_PACKET_TOO_LARGE: + /* + * This is a problem with the particular frame we're writing and + * the file type and subtype we're writing; note that, and report + * the frame number and file type/subtype. + */ + simple_error_message_box( + "Frame %u is larger than Wireshark supports in a \"%s\" file.", + fdata->num, wtap_file_type_subtype_string(args->file_type)); + break; + + case WTAP_ERR_UNWRITABLE_REC_TYPE: + /* + * This is a problem with the particular record we're writing and + * the file type and subtype we're writing; note that, and report + * the record number and file type/subtype. + */ + simple_error_message_box( + "Record %u has a record type that can't be saved in a \"%s\" file.", + fdata->num, wtap_file_type_subtype_string(args->file_type)); + break; + + case WTAP_ERR_UNWRITABLE_REC_DATA: + /* + * This is a problem with the particular frame we're writing and + * the file type and subtype we're writing; note that, and report + * the frame number and file type/subtype. + */ + simple_error_message_box( + "Record %u has data that can't be saved in a \"%s\" file.\n(%s)", + fdata->num, wtap_file_type_subtype_string(args->file_type), + err_info != NULL ? err_info : "no information supplied"); + g_free(err_info); + break; + default: display_basename = g_filename_display_basename(args->fname); simple_error_message_box( @@ -4276,7 +4103,7 @@ cf_has_unsaved_data(capture_file *cf) * If this is a temporary file, or a file with unsaved changes, it * has unsaved data. */ - return cf->is_tempfile || cf->unsaved_changes; + return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes; } /* @@ -4289,9 +4116,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) gchar *err_info; gchar *name_ptr; gint64 data_offset; - gint64 file_pos; progdlg_t *progbar = NULL; - gboolean stop_flag; gint64 size; float progbar_val; GTimeVal start_time; @@ -4309,7 +4134,12 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) wtap_close(cf->wth); /* Open the new file. */ - cf->wth = wtap_open_offline(fname, err, &err_info, TRUE); + /* XXX: this will go through all open_routines for a matching one. But right + now rescan_file() is only used when a file is being saved to a different + format than the original, and the user is not given a choice of which + reader to use (only which format to save it in), so doing this makes + sense for now. */ + cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, err, &err_info, TRUE); if (cf->wth == NULL) { cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0); return CF_READ_ERROR; @@ -4363,7 +4193,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) }else progbar_quantum = 0; - stop_flag = FALSE; + cf->stop_flag = FALSE; g_get_current_time(&start_time); framenum = 0; @@ -4374,15 +4204,15 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) fdata->file_off = data_offset; if (size >= 0) { count++; - file_pos = wtap_read_so_far(cf->wth); + cf->f_datalen = wtap_read_so_far(cf->wth); /* Create the progress bar if necessary. * Check whether it should be created or not every MIN_NUMBER_OF_PACKET */ if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) { - progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str)); + progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str)); progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr, - TRUE, &stop_flag, &start_time, progbar_val); + TRUE, &cf->stop_flag, &start_time, progbar_val); } /* Update the progress bar, but do it only N_PROGBAR_UPDATES times; @@ -4390,9 +4220,9 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) to repaint what's pending, and doing so may involve an "ioctl()" to see if there's any pending input from an X server, and doing that for every packet can be costly, especially on a big file. */ - if (file_pos >= progbar_nextstep) { + if (cf->f_datalen >= progbar_nextstep) { if (progbar != NULL) { - progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str)); + progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str)); /* update the packet bar content on the first run or frequently on very large files */ #ifdef HAVE_LIBPCAP if (progbar_quantum > 500000 || displayed_once == 0) { @@ -4408,7 +4238,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) } } - if (stop_flag) { + if (cf->stop_flag) { /* Well, the user decided to abort the rescan. Sadly, as this isn't a reread, recovering is difficult, so we'll just close the current capture. */ @@ -4448,7 +4278,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) cf_callback_invoke(cf_cb_file_rescan_finished, cf); - if (stop_flag) { + if (cf->stop_flag) { /* Our caller will give up at this point. */ return CF_READ_ABORTED; } @@ -4462,23 +4292,10 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) case WTAP_ERR_UNSUPPORTED: simple_error_message_box( "The capture file contains record data that Wireshark doesn't support.\n(%s)", - err_info); + err_info != NULL ? err_info : "no information supplied"); g_free(err_info); break; - case WTAP_ERR_UNSUPPORTED_ENCAP: - simple_error_message_box( - "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)", - err_info); - g_free(err_info); - break; - - case WTAP_ERR_CANT_READ: - simple_error_message_box( - "An attempt to read from the capture file failed for" - " some unknown reason."); - break; - case WTAP_ERR_SHORT_READ: simple_error_message_box( "The capture file appears to have been cut short" @@ -4488,14 +4305,15 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) case WTAP_ERR_BAD_FILE: simple_error_message_box( "The capture file appears to be damaged or corrupt.\n(%s)", - err_info); + err_info != NULL ? err_info : "no information supplied"); g_free(err_info); break; case WTAP_ERR_DECOMPRESS: simple_error_message_box( "The compressed capture file appears to be damaged or corrupt.\n" - "(%s)", err_info); + "(%s)", + err_info != NULL ? err_info : "no information supplied"); g_free(err_info); break; @@ -4511,7 +4329,7 @@ rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err) } cf_write_status_t -cf_save_packets(capture_file *cf, const char *fname, guint save_format, +cf_save_records(capture_file *cf, const char *fname, guint save_format, gboolean compressed, gboolean discard_comments, gboolean dont_reopen) { @@ -4618,12 +4436,15 @@ cf_save_packets(capture_file *cf, const char *fname, guint save_format, or moving the capture file, we have to do it by writing the packets out in Wiretap. */ - wtapng_section_t *shb_hdr = NULL; + wtapng_section_t *shb_hdr = NULL; wtapng_iface_descriptions_t *idb_inf = NULL; + wtapng_name_res_t *nrb_hdr = NULL; int encap; - shb_hdr = wtap_file_get_shb_info(cf->wth); + /* XXX: what free's this shb_hdr? */ + shb_hdr = wtap_file_get_shb_for_new_file(cf->wth); idb_inf = wtap_file_get_idb_info(cf->wth); + nrb_hdr = wtap_file_get_nrb_for_new_file(cf->wth); /* Determine what file encapsulation type we should use. */ encap = wtap_dump_file_encap_type(cf->linktypes); @@ -4638,10 +4459,10 @@ cf_save_packets(capture_file *cf, const char *fname, guint save_format, from which we're reading the packets that we're writing!) */ fname_new = g_strdup_printf("%s~", fname); pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap, - compressed, shb_hdr, idb_inf, &err); + compressed, shb_hdr, idb_inf, nrb_hdr, &err); } else { pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap, - compressed, shb_hdr, idb_inf, &err); + compressed, shb_hdr, idb_inf, nrb_hdr, &err); } g_free(idb_inf); idb_inf = NULL; @@ -4658,8 +4479,8 @@ cf_save_packets(capture_file *cf, const char *fname, guint save_format, callback_args.pdh = pdh; callback_args.fname = fname; callback_args.file_type = save_format; - switch (process_specified_packets(cf, NULL, "Saving", "packets", - TRUE, save_packet, &callback_args)) { + switch (process_specified_records(cf, NULL, "Saving", "packets", + TRUE, save_record, &callback_args)) { case PSP_FINISHED: /* Completed successfully. */ @@ -4743,7 +4564,11 @@ cf_save_packets(capture_file *cf, const char *fname, guint save_format, the wtap structure, the filename, and the "is temporary" status applies to the new file; just update that. */ wtap_close(cf->wth); - cf->wth = wtap_open_offline(fname, &err, &err_info, TRUE); + /* Although we're just "copying" and then opening the copy, it will + try all open_routine readers to open the copy, so we need to + reset the cfile's open_type. */ + cf->open_type = WTAP_TYPE_AUTO; + cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE); if (cf->wth == NULL) { cf_open_failure_alert_box(fname, err, err_info, FALSE, 0); cf_close(cf); @@ -4774,6 +4599,9 @@ cf_save_packets(capture_file *cf, const char *fname, guint save_format, ...as long as, for gzipped files, the process of writing out the file *also* generates the information needed to support fast random access to the compressed file. */ + /* rescan_file will cause us to try all open_routines, so + reset cfile's open_type */ + cf->open_type = WTAP_TYPE_AUTO; if (rescan_file(cf, fname, FALSE, &err) != CF_READ_OK) { /* The rescan failed; just close the file. Either a dialog was popped up for the failure, so the @@ -4831,8 +4659,9 @@ cf_export_specified_packets(capture_file *cf, const char *fname, int err; wtap_dumper *pdh; save_callback_args_t callback_args; - wtapng_section_t *shb_hdr; - wtapng_iface_descriptions_t *idb_inf; + wtapng_section_t *shb_hdr = NULL; + wtapng_iface_descriptions_t *idb_inf = NULL; + wtapng_name_res_t *nrb_hdr = NULL; int encap; cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname); @@ -4844,8 +4673,10 @@ cf_export_specified_packets(capture_file *cf, const char *fname, written, don't special-case the operation - read each packet and then write it out if it's one of the specified ones. */ - shb_hdr = wtap_file_get_shb_info(cf->wth); + /* XXX: what free's this shb_hdr? */ + shb_hdr = wtap_file_get_shb_for_new_file(cf->wth); idb_inf = wtap_file_get_idb_info(cf->wth); + nrb_hdr = wtap_file_get_nrb_for_new_file(cf->wth); /* Determine what file encapsulation type we should use. */ encap = wtap_dump_file_encap_type(cf->linktypes); @@ -4860,10 +4691,10 @@ cf_export_specified_packets(capture_file *cf, const char *fname, from which we're reading the packets that we're writing!) */ fname_new = g_strdup_printf("%s~", fname); pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap, - compressed, shb_hdr, idb_inf, &err); + compressed, shb_hdr, idb_inf, nrb_hdr, &err); } else { pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap, - compressed, shb_hdr, idb_inf, &err); + compressed, shb_hdr, idb_inf, nrb_hdr, &err); } g_free(idb_inf); idb_inf = NULL; @@ -4880,14 +4711,14 @@ cf_export_specified_packets(capture_file *cf, const char *fname, told to process. XXX - we've already called "packet_range_process_init(range)", but - "process_specified_packets()" will do it again. Fortunately, + "process_specified_records()" will do it again. Fortunately, that's harmless in this case, as we haven't done anything to "range" since we initialized it. */ callback_args.pdh = pdh; callback_args.fname = fname; callback_args.file_type = save_format; - switch (process_specified_packets(cf, range, "Writing", "specified packets", - TRUE, save_packet, &callback_args)) { + switch (process_specified_records(cf, range, "Writing", "specified records", + TRUE, save_record, &callback_args)) { case PSP_FINISHED: /* Completed successfully. */ @@ -4983,9 +4814,10 @@ cf_open_failure_alert_box(const char *filename, int err, gchar *err_info, case WTAP_ERR_UNSUPPORTED: /* Seen only when opening a capture file for reading. */ simple_error_message_box( - "The file \"%s\" isn't a capture file in a format Wireshark understands.\n" + "The file \"%s\" contains record data that Wireshark doesn't support.\n" "(%s)", - display_basename, err_info); + display_basename, + err_info != NULL ? err_info : "no information supplied"); g_free(err_info); break; @@ -4997,22 +4829,15 @@ cf_open_failure_alert_box(const char *filename, int err, gchar *err_info, display_basename, wtap_file_type_subtype_string(file_type)); break; - case WTAP_ERR_UNSUPPORTED_FILE_TYPE: + case WTAP_ERR_UNWRITABLE_FILE_TYPE: /* Seen only when opening a capture file for writing. */ simple_error_message_box( "Wireshark doesn't support writing capture files in that format."); break; - case WTAP_ERR_UNSUPPORTED_ENCAP: - if (for_writing) { - simple_error_message_box("Wireshark can't save this capture in that format."); - } else { - simple_error_message_box( - "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n" - "(%s)", - display_basename, err_info); - g_free(err_info); - } + case WTAP_ERR_UNWRITABLE_ENCAP: + /* Seen only when opening a capture file for writing. */ + simple_error_message_box("Wireshark can't save this capture in that format."); break; case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED: @@ -5031,7 +4856,8 @@ cf_open_failure_alert_box(const char *filename, int err, gchar *err_info, simple_error_message_box( "The file \"%s\" appears to be damaged or corrupt.\n" "(%s)", - display_basename, err_info); + display_basename, + err_info != NULL ? err_info : "no information supplied"); g_free(err_info); break; @@ -5068,7 +4894,8 @@ cf_open_failure_alert_box(const char *filename, int err, gchar *err_info, case WTAP_ERR_DECOMPRESS: simple_error_message_box( "The compressed file \"%s\" appears to be damaged or corrupt.\n" - "(%s)", display_basename, err_info); + "(%s)", display_basename, + err_info != NULL ? err_info : "no information supplied"); g_free(err_info); break; @@ -5185,7 +5012,7 @@ cf_reload(capture_file *cf) { filename = g_strdup(cf->filename); is_tempfile = cf->is_tempfile; cf->is_tempfile = FALSE; - if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) { + if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) { switch (cf_read(cf, TRUE)) { case CF_READ_OK: