From 70d432c35724b23cfb1f6d80773b520523a65f75 Mon Sep 17 00:00:00 2001 From: David Perry Date: Sun, 20 Feb 2022 19:39:37 +0000 Subject: Remove editor modelines and .editorconfig exceptions from root files --- file.c | 8209 ++++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 4104 insertions(+), 4105 deletions(-) (limited to 'file.c') diff --git a/file.c b/file.c index ea916c7743..23c5fef297 100644 --- a/file.c +++ b/file.c @@ -79,41 +79,41 @@ static gboolean read_record(capture_file *cf, wtap_rec *rec, Buffer *buf, static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect); typedef enum { - MR_NOTMATCHED, - MR_MATCHED, - MR_ERROR + MR_NOTMATCHED, + MR_MATCHED, + MR_ERROR } match_result; typedef match_result (*ws_match_function)(capture_file *, frame_data *, - wtap_rec *, Buffer *, void *); + wtap_rec *, Buffer *, void *); static match_result match_protocol_tree(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static void match_subtree_text(proto_node *node, gpointer data); static match_result match_summary_line(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_narrow_and_wide_case(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_narrow(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_narrow_case(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_wide(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_wide_case(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_binary(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_regex(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_dfilter(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_marked(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_time_reference(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static gboolean find_packet(capture_file *cf, ws_match_function match_function, - void *criterion, search_direction dir); + void *criterion, search_direction dir); static void cf_rename_failure_alert_box(const char *filename, int err); @@ -137,7 +137,7 @@ static guint32 max_records = G_MAXUINT32; void cf_set_max_records(guint max_records_arg) { - max_records = max_records_arg; + max_records = max_records_arg; } /* @@ -146,8 +146,8 @@ cf_set_max_records(guint max_records_arg) * instance for the signals. */ typedef struct { - cf_callback_t cb_fct; - gpointer user_data; + cf_callback_t cb_fct; + gpointer user_data; } cf_callback_data_t; static GList *cf_callbacks = NULL; @@ -155,193 +155,193 @@ static GList *cf_callbacks = NULL; static void cf_callback_invoke(int event, gpointer data) { - cf_callback_data_t *cb; - GList *cb_item = cf_callbacks; + cf_callback_data_t *cb; + GList *cb_item = cf_callbacks; - /* there should be at least one interested */ - ws_assert(cb_item != NULL); + /* there should be at least one interested */ + ws_assert(cb_item != NULL); - while (cb_item != NULL) { - cb = (cf_callback_data_t *)cb_item->data; - cb->cb_fct(event, data, cb->user_data); - cb_item = g_list_next(cb_item); - } + while (cb_item != NULL) { + cb = (cf_callback_data_t *)cb_item->data; + cb->cb_fct(event, data, cb->user_data); + cb_item = g_list_next(cb_item); + } } - void cf_callback_add(cf_callback_t func, gpointer user_data) { - cf_callback_data_t *cb; + cf_callback_data_t *cb; - cb = g_new(cf_callback_data_t,1); - cb->cb_fct = func; - cb->user_data = user_data; + cb = g_new(cf_callback_data_t,1); + cb->cb_fct = func; + cb->user_data = user_data; - cf_callbacks = g_list_prepend(cf_callbacks, cb); + cf_callbacks = g_list_prepend(cf_callbacks, cb); } void 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 && cb->user_data == user_data) { - cf_callbacks = g_list_remove(cf_callbacks, cb); - g_free(cb); - return; + 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 && cb->user_data == user_data) { + cf_callbacks = g_list_remove(cf_callbacks, cb); + g_free(cb); + return; + } + cb_item = g_list_next(cb_item); } - cb_item = g_list_next(cb_item); - } - ws_assert_not_reached(); + ws_assert_not_reached(); } void cf_timestamp_auto_precision(capture_file *cf) { - int i; + int i; - /* don't try to get the file's precision if none is opened */ - if (cf->state == FILE_CLOSED) { - return; - } + /* don't try to get the file's precision if none is opened */ + if (cf->state == FILE_CLOSED) { + return; + } - /* 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++) { - if (col_has_time_fmt(&cf->cinfo, i)) { - packet_list_resize_column(i); + /* 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++) { + if (col_has_time_fmt(&cf->cinfo, i)) { + packet_list_resize_column(i); + } } - } } gulong cf_get_computed_elapsed(capture_file *cf) { - return cf->computed_elapsed; + return cf->computed_elapsed; } -static void compute_elapsed(capture_file *cf, gint64 start_time) +static void +compute_elapsed(capture_file *cf, gint64 start_time) { - gint64 delta_time = g_get_monotonic_time() - start_time; + gint64 delta_time = g_get_monotonic_time() - start_time; - cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */ + cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */ } static const nstime_t * ws_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num) { - if (prov->prev_dis && prov->prev_dis->num == frame_num) - return &prov->prev_dis->abs_ts; + if (prov->prev_dis && prov->prev_dis->num == frame_num) + return &prov->prev_dis->abs_ts; - if (prov->prev_cap && prov->prev_cap->num == frame_num) - return &prov->prev_cap->abs_ts; + if (prov->prev_cap && prov->prev_cap->num == frame_num) + return &prov->prev_cap->abs_ts; - if (prov->frames) { - frame_data *fd = frame_data_sequence_find(prov->frames, frame_num); + if (prov->frames) { + frame_data *fd = frame_data_sequence_find(prov->frames, frame_num); - return (fd) ? &fd->abs_ts : NULL; - } + return (fd) ? &fd->abs_ts : NULL; + } - return NULL; + return NULL; } static epan_t * ws_epan_new(capture_file *cf) { - static const struct packet_provider_funcs funcs = { - ws_get_frame_ts, - cap_file_provider_get_interface_name, - cap_file_provider_get_interface_description, - cap_file_provider_get_modified_block - }; - - return epan_new(&cf->provider, &funcs); + static const struct packet_provider_funcs funcs = { + ws_get_frame_ts, + cap_file_provider_get_interface_name, + cap_file_provider_get_interface_description, + cap_file_provider_get_modified_block + }; + + return epan_new(&cf->provider, &funcs); } cf_status_t 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, type, err, &err_info, TRUE); - if (wth == NULL) - goto fail; - - /* The open succeeded. Close whatever capture file we had open, - and fill in the information for this file. */ - cf_close(cf); - - /* Initialize the record metadata. */ - wtap_rec_init(&cf->rec); + wtap *wth; + gchar *err_info; - /* XXX - we really want to initialize this after we've read all - the packets, so we know how much we'll ultimately need. */ - ws_buffer_init(&cf->buf, 1514); - - /* We're about to start reading the file. */ - cf->state = FILE_READ_IN_PROGRESS; - - cf->provider.wth = wth; - cf->f_datalen = 0; + wth = wtap_open_offline(fname, type, err, &err_info, TRUE); + if (wth == NULL) + goto fail; - /* Set the file name because we need it to set the follow stream filter. - XXX - is that still true? We need it for other reasons, though, - in any case. */ - cf->filename = g_strdup(fname); + /* The open succeeded. Close whatever capture file we had open, + and fill in the information for this file. */ + cf_close(cf); - /* Indicate whether it's a permanent or temporary file. */ - cf->is_tempfile = is_tempfile; + /* Initialize the record metadata. */ + wtap_rec_init(&cf->rec); - /* No user changes yet. */ - cf->unsaved_changes = FALSE; + /* XXX - we really want to initialize this after we've read all + the packets, so we know how much we'll ultimately need. */ + ws_buffer_init(&cf->buf, 1514); - cf->computed_elapsed = 0; + /* We're about to start reading the file. */ + cf->state = FILE_READ_IN_PROGRESS; - cf->cd_t = wtap_file_type_subtype(cf->provider.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; - cf->displayed_count = 0; - cf->marked_count = 0; - cf->ignored_count = 0; - cf->ref_time_count = 0; - cf->drops_known = FALSE; - cf->drops = 0; - cf->snap = wtap_snapshot_length(cf->provider.wth); + cf->provider.wth = wth; + cf->f_datalen = 0; - /* Allocate a frame_data_sequence for the frames in this file */ - cf->provider.frames = new_frame_data_sequence(); + /* Set the file name because we need it to set the follow stream filter. + XXX - is that still true? We need it for other reasons, though, + in any case. */ + cf->filename = g_strdup(fname); - nstime_set_zero(&cf->elapsed_time); - cf->provider.ref = NULL; - cf->provider.prev_dis = NULL; - cf->provider.prev_cap = NULL; - cf->cum_bytes = 0; + /* Indicate whether it's a permanent or temporary file. */ + cf->is_tempfile = is_tempfile; - /* Create new epan session for dissection. - * (The old one was freed in cf_close().) - */ - cf->epan = ws_epan_new(cf); + /* No user changes yet. */ + cf->unsaved_changes = FALSE; + + cf->computed_elapsed = 0; + + cf->cd_t = wtap_file_type_subtype(cf->provider.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; + cf->displayed_count = 0; + cf->marked_count = 0; + cf->ignored_count = 0; + cf->ref_time_count = 0; + cf->drops_known = FALSE; + cf->drops = 0; + cf->snap = wtap_snapshot_length(cf->provider.wth); + + /* Allocate a frame_data_sequence for the frames in this file */ + cf->provider.frames = new_frame_data_sequence(); + + nstime_set_zero(&cf->elapsed_time); + cf->provider.ref = NULL; + cf->provider.prev_dis = NULL; + cf->provider.prev_cap = NULL; + cf->cum_bytes = 0; + + /* Create new epan session for dissection. + * (The old one was freed in cf_close().) + */ + cf->epan = ws_epan_new(cf); - packet_list_queue_draw(); - cf_callback_invoke(cf_cb_file_opened, cf); + packet_list_queue_draw(); + cf_callback_invoke(cf_cb_file_opened, cf); - wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name); - wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name); - wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback); + wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name); + wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name); + wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback); - return CF_OK; + return CF_OK; fail: - cfile_open_failure_alert_box(fname, *err, err_info); - return CF_ERROR; + cfile_open_failure_alert_box(fname, *err, err_info); + return CF_ERROR; } /* @@ -350,100 +350,100 @@ fail: static void cf_add_encapsulation_type(capture_file *cf, int encap) { - guint i; - - for (i = 0; i < cf->linktypes->len; i++) { - if (g_array_index(cf->linktypes, gint, i) == encap) - return; /* it's already there */ - } - /* It's not already there - add it. */ - g_array_append_val(cf->linktypes, encap); + guint i; + + for (i = 0; i < cf->linktypes->len; i++) { + if (g_array_index(cf->linktypes, gint, i) == encap) + return; /* it's already there */ + } + /* It's not already there - add it. */ + g_array_append_val(cf->linktypes, encap); } /* 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 */ + cf->stop_flag = FALSE; + if (cf->state == FILE_CLOSED) + return; /* Nothing to do */ - /* Die if we're in the middle of reading a file. */ - ws_assert(cf->state != FILE_READ_IN_PROGRESS); - ws_assert(!cf->read_lock); + /* Die if we're in the middle of reading a file. */ + ws_assert(cf->state != FILE_READ_IN_PROGRESS); + ws_assert(!cf->read_lock); - cf_callback_invoke(cf_cb_file_closing, cf); + cf_callback_invoke(cf_cb_file_closing, cf); - /* close things, if not already closed before */ - color_filters_cleanup(); + /* close things, if not already closed before */ + color_filters_cleanup(); - if (cf->provider.wth) { - wtap_close(cf->provider.wth); - cf->provider.wth = NULL; - } - /* We have no file open... */ - if (cf->filename != NULL) { - /* If it's a temporary file, remove it. */ - if (cf->is_tempfile) - ws_unlink(cf->filename); - g_free(cf->filename); - cf->filename = NULL; - } - /* ...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 record metadata. */ - wtap_rec_cleanup(&cf->rec); - - /* Clear the packet list. */ - packet_list_freeze(); - packet_list_clear(); - packet_list_thaw(); - - /* Free up the packet buffer. */ - ws_buffer_free(&cf->buf); - - dfilter_free(cf->rfcode); - cf->rfcode = NULL; - if (cf->provider.frames != NULL) { - free_frame_data_sequence(cf->provider.frames); - cf->provider.frames = NULL; - } - if (cf->provider.frames_modified_blocks) { - g_tree_destroy(cf->provider.frames_modified_blocks); - cf->provider.frames_modified_blocks = NULL; - } - cf_unselect_packet(cf); /* nothing to select */ - cf->first_displayed = 0; - cf->last_displayed = 0; - - /* No frames, no frame selected, no field in that frame selected. */ - cf->count = 0; - cf->current_frame = NULL; - cf->current_row = 0; - cf->finfo_selected = NULL; - - /* No frame link-layer types, either. */ - if (cf->linktypes != NULL) { - g_array_free(cf->linktypes, TRUE); - cf->linktypes = NULL; - } - - cf->f_datalen = 0; - nstime_set_zero(&cf->elapsed_time); - - reset_tap_listeners(); - - epan_free(cf->epan); - cf->epan = NULL; - - /* We have no file open. */ - cf->state = FILE_CLOSED; - - cf_callback_invoke(cf_cb_file_closed, cf); + if (cf->provider.wth) { + wtap_close(cf->provider.wth); + cf->provider.wth = NULL; + } + /* We have no file open... */ + if (cf->filename != NULL) { + /* If it's a temporary file, remove it. */ + if (cf->is_tempfile) + ws_unlink(cf->filename); + g_free(cf->filename); + cf->filename = NULL; + } + /* ...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 record metadata. */ + wtap_rec_cleanup(&cf->rec); + + /* Clear the packet list. */ + packet_list_freeze(); + packet_list_clear(); + packet_list_thaw(); + + /* Free up the packet buffer. */ + ws_buffer_free(&cf->buf); + + dfilter_free(cf->rfcode); + cf->rfcode = NULL; + if (cf->provider.frames != NULL) { + free_frame_data_sequence(cf->provider.frames); + cf->provider.frames = NULL; + } + if (cf->provider.frames_modified_blocks) { + g_tree_destroy(cf->provider.frames_modified_blocks); + cf->provider.frames_modified_blocks = NULL; + } + cf_unselect_packet(cf); /* nothing to select */ + cf->first_displayed = 0; + cf->last_displayed = 0; + + /* No frames, no frame selected, no field in that frame selected. */ + cf->count = 0; + cf->current_frame = NULL; + cf->current_row = 0; + cf->finfo_selected = NULL; + + /* No frame link-layer types, either. */ + if (cf->linktypes != NULL) { + g_array_free(cf->linktypes, TRUE); + cf->linktypes = NULL; + } + + cf->f_datalen = 0; + nstime_set_zero(&cf->elapsed_time); + + reset_tap_listeners(); + + epan_free(cf->epan); + cf->epan = NULL; + + /* We have no file open. */ + cf->state = FILE_CLOSED; + + cf_callback_invoke(cf_cb_file_closed, cf); } /* @@ -453,797 +453,808 @@ cf_close(capture_file *cf) static inline gboolean progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos) { - double elapsed; + double elapsed; - if (progdlg) return FALSE; - elapsed = g_timer_elapsed(prog_timer, NULL); - if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */ - || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */ - return TRUE; - } - return FALSE; + if (progdlg) return FALSE; + elapsed = g_timer_elapsed(prog_timer, NULL); + if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */ + || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */ + return TRUE; + } + return FALSE; } static float calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size) { - float progbar_val; + float progbar_val; - progbar_val = (gfloat) file_pos / (gfloat) size; - if (progbar_val > 1.0) { + progbar_val = (gfloat) file_pos / (gfloat) size; + if (progbar_val > 1.0) { - /* The file probably grew while we were reading it. - * Update file size, and try again. - */ - size = wtap_file_size(cf->provider.wth, NULL); + /* The file probably grew while we were reading it. + * Update file size, and try again. + */ + size = wtap_file_size(cf->provider.wth, NULL); - if (size >= 0) - progbar_val = (gfloat) file_pos / (gfloat) size; + if (size >= 0) + progbar_val = (gfloat) file_pos / (gfloat) size; - /* If it's still > 1, either "wtap_file_size()" failed (in which - * case there's not much we can do about it), or the file - * *shrank* (in which case there's not much we can do about - * it); just clip the progress value at 1.0. - */ - if (progbar_val > 1.0f) - progbar_val = 1.0f; - } + /* If it's still > 1, either "wtap_file_size()" failed (in which + * case there's not much we can do about it), or the file + * *shrank* (in which case there's not much we can do about + * it); just clip the progress value at 1.0. + */ + if (progbar_val > 1.0f) + progbar_val = 1.0f; + } - snprintf(status_str, status_size, - "%" PRId64 "KB of %" PRId64 "KB", - file_pos / 1024, size / 1024); + snprintf(status_str, status_size, + "%" PRId64 "KB of %" PRId64 "KB", + file_pos / 1024, size / 1024); - return progbar_val; + return progbar_val; } cf_read_status_t cf_read(capture_file *cf, gboolean reloading) { - int err = 0; - gchar *err_info = NULL; - volatile gboolean too_many_records = FALSE; - gchar *name_ptr; - progdlg_t *volatile progbar = NULL; - GTimer *prog_timer = g_timer_new(); - gint64 size; - gint64 start_time; - epan_dissect_t edt; - wtap_rec rec; - Buffer buf; - dfilter_t *dfcode; - column_info *cinfo; - volatile gboolean create_proto_tree; - guint tap_flags; - gboolean compiled _U_; - volatile gboolean is_read_aborted = FALSE; - - /* The update_progress_dlg call below might end up accepting a user request to - * trigger redissection/rescans which can modify/destroy the dissection - * context ("cf->epan"). That condition should be prevented by callers, but in - * case it occurs let's fail gracefully. - */ - if (cf->read_lock) { - ws_warning("Failing due to recursive cf_read(\"%s\", %d) call!", - cf->filename, reloading); - return CF_READ_ERROR; - } - cf->read_lock = TRUE; - - /* Compile the current display filter. - * 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, NULL); - ws_assert(!cf->dfilter || (compiled && dfcode)); - - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); - - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a display filter; - * - * one of the tap listeners is going to apply a filter; - * - * one of the tap listeners requires a protocol tree; - * - * a postdissector wants field values or protocols on - * the first pass. - */ - create_proto_tree = - (dfcode != NULL || have_filtering_tap_listeners() || - (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids()); - - reset_tap_listeners(); - - name_ptr = g_filename_display_basename(cf->filename); - - if (reloading) - cf_callback_invoke(cf_cb_file_reload_started, cf); - else - cf_callback_invoke(cf_cb_file_read_started, cf); - - /* Record the file's compression type. - XXX - do we know this at open time? */ - cf->compression_type = wtap_get_compression_type(cf->provider.wth); - - /* The packet list window will be empty until the file is completly loaded */ - packet_list_freeze(); - - cf->stop_flag = FALSE; - start_time = g_get_monotonic_time(); - - epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); - - /* If any tap listeners require the columns, construct them. */ - cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; - - /* Find the size of the file. */ - size = wtap_file_size(cf->provider.wth, NULL); - - g_timer_start(prog_timer); - - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); - - TRY { - guint32 count = 0; - - gint64 file_pos; - gint64 data_offset; - - float progbar_val; - gchar status_str[100]; + int err = 0; + gchar *err_info = NULL; + volatile gboolean too_many_records = FALSE; + gchar *name_ptr; + progdlg_t *volatile progbar = NULL; + GTimer *prog_timer = g_timer_new(); + gint64 size; + gint64 start_time; + epan_dissect_t edt; + wtap_rec rec; + Buffer buf; + dfilter_t *dfcode; + column_info *cinfo; + volatile gboolean create_proto_tree; + guint tap_flags; + gboolean compiled _U_; + volatile gboolean is_read_aborted = FALSE; + + /* The update_progress_dlg call below might end up accepting a user request to + * trigger redissection/rescans which can modify/destroy the dissection + * context ("cf->epan"). That condition should be prevented by callers, but in + * case it occurs let's fail gracefully. + */ + if (cf->read_lock) { + ws_warning("Failing due to recursive cf_read(\"%s\", %d) call!", + cf->filename, reloading); + return CF_READ_ERROR; + } + cf->read_lock = TRUE; - while ((wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, - &data_offset))) { - if (size >= 0) { - if (cf->count == max_records) { - /* - * Quit if we've already read the maximum number of - * records allowed. - */ - too_many_records = TRUE; - break; - } - count++; - file_pos = wtap_read_so_far(cf->provider.wth); + /* Compile the current display filter. + * 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, NULL); + ws_assert(!cf->dfilter || (compiled && dfcode)); - /* Create the progress bar if necessary. */ - if (progress_is_slow(progbar, prog_timer, size, file_pos)) { - progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str)); - progbar = delayed_create_progress_dlg(cf->window, NULL, NULL, TRUE, - &cf->stop_flag, progbar_val); - } + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); - /* - * Update the progress bar, but do it only after - * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg - * and packets_bar_update will likely trigger UI paint events, which - * might take a while depending on the platform and display. Reset - * our timer *after* painting. - */ - if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { - progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str)); - /* update the packet bar content on the first run or frequently on very large files */ - update_progress_dlg(progbar, progbar_val, status_str); - compute_elapsed(cf, start_time); - packets_bar_update(); - g_timer_start(prog_timer); + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a display filter; + * + * one of the tap listeners is going to apply a filter; + * + * one of the tap listeners requires a protocol tree; + * + * a postdissector wants field values or protocols on + * the first pass. + */ + create_proto_tree = + (dfcode != NULL || have_filtering_tap_listeners() || + (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids()); + + reset_tap_listeners(); + + name_ptr = g_filename_display_basename(cf->filename); + + if (reloading) + cf_callback_invoke(cf_cb_file_reload_started, cf); + else + cf_callback_invoke(cf_cb_file_read_started, cf); + + /* Record the file's compression type. + XXX - do we know this at open time? */ + cf->compression_type = wtap_get_compression_type(cf->provider.wth); + + /* The packet list window will be empty until the file is completly loaded */ + packet_list_freeze(); + + cf->stop_flag = FALSE; + start_time = g_get_monotonic_time(); + + epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); + + /* If any tap listeners require the columns, construct them. */ + cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; + + /* Find the size of the file. */ + size = wtap_file_size(cf->provider.wth, NULL); + + g_timer_start(prog_timer); + + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); + + TRY { + guint32 count = 0; + + gint64 file_pos; + gint64 data_offset; + + float progbar_val; + gchar status_str[100]; + + while ((wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, + &data_offset))) { + if (size >= 0) { + if (cf->count == max_records) { + /* + * Quit if we've already read the maximum number of + * records allowed. + */ + too_many_records = TRUE; + break; + } + count++; + file_pos = wtap_read_so_far(cf->provider.wth); + + /* Create the progress bar if necessary. */ + if (progress_is_slow(progbar, prog_timer, size, file_pos)) { + progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str)); + progbar = delayed_create_progress_dlg(cf->window, NULL, NULL, TRUE, + &cf->stop_flag, progbar_val); + } + + /* + * Update the progress bar, but do it only after + * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg + * and packets_bar_update will likely trigger UI paint events, which + * might take a while depending on the platform and display. Reset + * our timer *after* painting. + */ + if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { + progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str)); + /* update the packet bar content on the first run or frequently on very large files */ + update_progress_dlg(progbar, progbar_val, status_str); + compute_elapsed(cf, start_time); + packets_bar_update(); + g_timer_start(prog_timer); + } + /* + * The previous GUI triggers should not have destroyed the running + * session. If that did happen, it could blow up when read_record tries + * to use the destroyed edt.session, so detect it right here. + */ + ws_assert(edt.session == cf->epan); + } + + if (cf->state == FILE_READ_ABORTED) { + /* Well, the user decided to exit Wireshark. Break out of the + loop, and let the code below (which is called even if there + aren't any packets left to read) exit. */ + is_read_aborted = TRUE; + break; + } + 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. + This is especially true for very large capture files, where you don't + want to wait loading the whole file (which may last minutes or even + hours even on fast machines) just to see that it was the wrong file. */ + break; + } + read_record(cf, &rec, &buf, dfcode, &edt, cinfo, data_offset); + wtap_rec_reset(&rec); } - /* - * The previous GUI triggers should not have destroyed the running - * session. If that did happen, it could blow up when read_record tries - * to use the destroyed edt.session, so detect it right here. - */ - ws_assert(edt.session == cf->epan); - } - - if (cf->state == FILE_READ_ABORTED) { - /* Well, the user decided to exit Wireshark. Break out of the - loop, and let the code below (which is called even if there - aren't any packets left to read) exit. */ - is_read_aborted = TRUE; - break; - } - 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. - This is especially true for very large capture files, where you don't - want to wait loading the whole file (which may last minutes or even - hours even on fast machines) just to see that it was the wrong file. */ - break; - } - read_record(cf, &rec, &buf, dfcode, &edt, cinfo, data_offset); - wtap_rec_reset(&rec); - } - } - CATCH(OutOfMemoryError) { - simple_message_box(ESD_TYPE_ERROR, NULL, - "More information and workarounds can be found at\n" - WS_WIKI_URL("KnownBugs/OutOfMemory"), - "Sorry, but Wireshark has run out of memory and has to terminate now."); + } + CATCH(OutOfMemoryError) { + simple_message_box(ESD_TYPE_ERROR, NULL, + "More information and workarounds can be found at\n" + WS_WIKI_URL("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? */ + /* Could we close the current capture and free up memory from that? */ #else - /* we have to terminate, as we cannot recover from the memory error */ - exit(1); + /* we have to terminate, as we cannot recover from the memory error */ + exit(1); #endif - } - ENDTRY; + } + ENDTRY; + + /* We're done reading sequentially through the file. */ + cf->state = FILE_READ_DONE; - /* We're done reading sequentially through the file. */ - cf->state = FILE_READ_DONE; + /* Destroy the progress bar if it was created. */ + if (progbar != NULL) + destroy_progress_dlg(progbar); + g_timer_destroy(prog_timer); - /* Destroy the progress bar if it was created. */ - if (progbar != NULL) - destroy_progress_dlg(progbar); - g_timer_destroy(prog_timer); + /* Free the display name */ + g_free(name_ptr); - /* Free the display name */ - g_free(name_ptr); + /* Cleanup and release all dfilter resources */ + dfilter_free(dfcode); - /* Cleanup and release all dfilter resources */ - dfilter_free(dfcode); + epan_dissect_cleanup(&edt); + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); - epan_dissect_cleanup(&edt); - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); + /* Close the sequential I/O side, to free up memory it requires. */ + wtap_sequential_close(cf->provider.wth); - /* Close the sequential I/O side, to free up memory it requires. */ - wtap_sequential_close(cf->provider.wth); + /* Allow the protocol dissectors to free up memory that they + * don't need after the sequential run-through of the packets. */ + postseq_cleanup_all_protocols(); - /* Allow the protocol dissectors to free up memory that they - * don't need after the sequential run-through of the packets. */ - postseq_cleanup_all_protocols(); + /* compute the time it took to load the file */ + compute_elapsed(cf, start_time); - /* compute the time it took to load the file */ - compute_elapsed(cf, start_time); + /* Set the file encapsulation type now; we don't know what it is until + we've looked at all the packets, as we don't know until then whether + there's more than one type (and thus whether it's + WTAP_ENCAP_PER_PACKET). */ + cf->lnk_t = wtap_file_encap(cf->provider.wth); - /* Set the file encapsulation type now; we don't know what it is until - we've looked at all the packets, as we don't know until then whether - there's more than one type (and thus whether it's - WTAP_ENCAP_PER_PACKET). */ - cf->lnk_t = wtap_file_encap(cf->provider.wth); + cf->current_frame = frame_data_sequence_find(cf->provider.frames, cf->first_displayed); + cf->current_row = 0; - cf->current_frame = frame_data_sequence_find(cf->provider.frames, cf->first_displayed); - cf->current_row = 0; + packet_list_thaw(); + if (reloading) + cf_callback_invoke(cf_cb_file_reload_finished, cf); + else + cf_callback_invoke(cf_cb_file_read_finished, cf); - packet_list_thaw(); - if (reloading) - cf_callback_invoke(cf_cb_file_reload_finished, cf); - else - cf_callback_invoke(cf_cb_file_read_finished, cf); + /* If we have any displayed packets to select, select the first of those + packets by making the first row the selected row. */ + if (cf->first_displayed != 0) { + packet_list_select_first_row(); + } - /* If we have any displayed packets to select, select the first of those - packets by making the first row the selected row. */ - if (cf->first_displayed != 0) { - packet_list_select_first_row(); - } + /* It is safe again to execute redissections. */ + ws_assert(cf->read_lock); + cf->read_lock = FALSE; - /* It is safe again to execute redissections. */ - ws_assert(cf->read_lock); - cf->read_lock = FALSE; + if (is_read_aborted) { + /* + * Well, the user decided to exit Wireshark while reading this *offline* + * capture file (Live captures are handled by something like + * cf_continue_tail). Clean up accordingly. + */ + cf_close(cf); + cf->redissection_queued = RESCAN_NONE; + return CF_READ_ABORTED; + } - if (is_read_aborted) { - /* - * Well, the user decided to exit Wireshark while reading this *offline* - * capture file (Live captures are handled by something like - * cf_continue_tail). Clean up accordingly. - */ - cf_close(cf); - cf->redissection_queued = RESCAN_NONE; - return CF_READ_ABORTED; - } - - if (cf->redissection_queued != RESCAN_NONE) { - /* Redissection was queued up. Clear the request and perform it now. */ - gboolean redissect = cf->redissection_queued == RESCAN_REDISSECT; - rescan_packets(cf, NULL, NULL, redissect); - } - - 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."); - return CF_READ_ERROR; - } - - if (err != 0) { - /* Put up a message box noting that the read failed somewhere along - the line. Don't throw out the stuff we managed to read, though, - if any. */ - cfile_read_failure_alert_box(NULL, err, err_info); - return CF_READ_ERROR; - } else if (too_many_records) { - 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" - "\n" - "The command-line utility editcap can be used to split " - "the file into multiple smaller files", - "The file contains more records than the maximum " - "supported number of records, %u.", max_records); - return CF_READ_ERROR; - } else - return CF_READ_OK; + if (cf->redissection_queued != RESCAN_NONE) { + /* Redissection was queued up. Clear the request and perform it now. */ + gboolean redissect = cf->redissection_queued == RESCAN_REDISSECT; + rescan_packets(cf, NULL, NULL, redissect); + } + + 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."); + return CF_READ_ERROR; + } + + if (err != 0) { + /* Put up a message box noting that the read failed somewhere along + the line. Don't throw out the stuff we managed to read, though, + if any. */ + cfile_read_failure_alert_box(NULL, err, err_info); + return CF_READ_ERROR; + } else if (too_many_records) { + 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" + "\n" + "The command-line utility editcap can be used to split " + "the file into multiple smaller files", + "The file contains more records than the maximum " + "supported number of records, %u.", max_records); + return CF_READ_ERROR; + } else + return CF_READ_OK; } #ifdef HAVE_LIBPCAP cf_read_status_t cf_continue_tail(capture_file *cf, volatile int to_read, wtap_rec *rec, - Buffer *buf, int *err) + Buffer *buf, int *err) { - gchar *err_info; - volatile int newly_displayed_packets = 0; - dfilter_t *dfcode; - epan_dissect_t edt; - gboolean create_proto_tree; - guint tap_flags; - gboolean compiled _U_; - - /* Compile the current display filter. - * 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, NULL); - ws_assert(!cf->dfilter || (compiled && dfcode)); - - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); - - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a display filter; - * - * one of the tap listeners is going to apply a filter; - * - * one of the tap listeners requires a protocol tree; - * - * a postdissector wants field values or protocols on - * the first pass. - */ - create_proto_tree = - (dfcode != NULL || have_filtering_tap_listeners() || - (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids()); - - *err = 0; - - /* Don't freeze/thaw the list when doing live capture */ - /*packet_list_freeze();*/ - - epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); - - TRY { - gint64 data_offset = 0; - column_info *cinfo; + gchar *err_info; + volatile int newly_displayed_packets = 0; + dfilter_t *dfcode; + epan_dissect_t edt; + gboolean create_proto_tree; + guint tap_flags; + gboolean compiled _U_; + + /* Compile the current display filter. + * 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, NULL); + ws_assert(!cf->dfilter || (compiled && dfcode)); - /* If any tap listeners require the columns, construct them. */ - cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); + + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a display filter; + * + * one of the tap listeners is going to apply a filter; + * + * one of the tap listeners requires a protocol tree; + * + * a postdissector wants field values or protocols on + * the first pass. + */ + create_proto_tree = + (dfcode != NULL || have_filtering_tap_listeners() || + (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids()); + + *err = 0; + + /* Don't freeze/thaw the list when doing live capture */ + /*packet_list_freeze();*/ + + epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); - while (to_read != 0) { - wtap_cleareof(cf->provider.wth); - if (!wtap_read(cf->provider.wth, rec, buf, err, &err_info, - &data_offset)) { - break; - } - if (cf->state == FILE_READ_ABORTED) { - /* Well, the user decided to exit Wireshark. Break out of the - loop, and let the code below (which is called even if there - aren't any packets left to read) exit. */ - break; - } - if (read_record(cf, rec, buf, dfcode, &edt, cinfo, data_offset)) { - newly_displayed_packets++; - } - to_read--; - } - wtap_rec_reset(rec); - } - CATCH(OutOfMemoryError) { - simple_message_box(ESD_TYPE_ERROR, NULL, - "More information and workarounds can be found at\n" - WS_WIKI_URL("KnownBugs/OutOfMemory"), - "Sorry, but Wireshark has run out of memory and has to terminate now."); + TRY { + gint64 data_offset = 0; + column_info *cinfo; + + /* If any tap listeners require the columns, construct them. */ + cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; + + while (to_read != 0) { + wtap_cleareof(cf->provider.wth); + if (!wtap_read(cf->provider.wth, rec, buf, err, &err_info, + &data_offset)) { + break; + } + if (cf->state == FILE_READ_ABORTED) { + /* Well, the user decided to exit Wireshark. Break out of the + loop, and let the code below (which is called even if there + aren't any packets left to read) exit. */ + break; + } + if (read_record(cf, rec, buf, dfcode, &edt, cinfo, data_offset)) { + newly_displayed_packets++; + } + to_read--; + } + wtap_rec_reset(rec); + } + CATCH(OutOfMemoryError) { + simple_message_box(ESD_TYPE_ERROR, NULL, + "More information and workarounds can be found at\n" + WS_WIKI_URL("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; + /* Could we close the current capture and free up memory from that? */ + return CF_READ_ABORTED; #else - /* we have to terminate, as we cannot recover from the memory error */ - exit(1); + /* we have to terminate, as we cannot recover from the memory error */ + exit(1); #endif - } - ENDTRY; - - /* Update the file encapsulation; it might have changed based on the - packets we've read. */ - cf->lnk_t = wtap_file_encap(cf->provider.wth); - - /* Cleanup and release all dfilter resources */ - dfilter_free(dfcode); - - epan_dissect_cleanup(&edt); - - /* Don't freeze/thaw the list when doing live capture */ - /*packet_list_thaw();*/ - /* With the new packet list the first packet - * isn't automatically selected. - */ - if (!cf->current_frame && !packet_list_multi_select_active()) - packet_list_select_first_row(); - - /* moving to the end of the packet list - if the user requested so and - we have some new packets. */ - if (newly_displayed_packets && cf->count != 0) - packet_list_moveto_end(); - - if (cf->state == FILE_READ_ABORTED) { - /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED - so that our caller can kill off the capture child process; - this will cause an EOF on the pipe from the child, so - "cf_finish_tail()" will be called, and it will clean up - and exit. */ - return CF_READ_ABORTED; - } else if (*err != 0) { - /* We got an error reading the capture file. - XXX - pop up a dialog box instead? */ - if (err_info != NULL) { - ws_warning("Error \"%s\" while reading \"%s\" (\"%s\")", - wtap_strerror(*err), cf->filename, err_info); - g_free(err_info); - } else { - ws_warning("Error \"%s\" while reading \"%s\"", - wtap_strerror(*err), cf->filename); } - return CF_READ_ERROR; - } else - return CF_READ_OK; + ENDTRY; + + /* Update the file encapsulation; it might have changed based on the + packets we've read. */ + cf->lnk_t = wtap_file_encap(cf->provider.wth); + + /* Cleanup and release all dfilter resources */ + dfilter_free(dfcode); + + epan_dissect_cleanup(&edt); + + /* Don't freeze/thaw the list when doing live capture */ + /*packet_list_thaw();*/ + /* With the new packet list the first packet + * isn't automatically selected. + */ + if (!cf->current_frame && !packet_list_multi_select_active()) + packet_list_select_first_row(); + + /* moving to the end of the packet list - if the user requested so and + we have some new packets. */ + if (newly_displayed_packets && cf->count != 0) + packet_list_moveto_end(); + + if (cf->state == FILE_READ_ABORTED) { + /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED + so that our caller can kill off the capture child process; + this will cause an EOF on the pipe from the child, so + "cf_finish_tail()" will be called, and it will clean up + and exit. */ + return CF_READ_ABORTED; + } else if (*err != 0) { + /* We got an error reading the capture file. + XXX - pop up a dialog box instead? */ + if (err_info != NULL) { + ws_warning("Error \"%s\" while reading \"%s\" (\"%s\")", + wtap_strerror(*err), cf->filename, err_info); + g_free(err_info); + } else { + ws_warning("Error \"%s\" while reading \"%s\"", + wtap_strerror(*err), cf->filename); + } + return CF_READ_ERROR; + } else + return CF_READ_OK; } void -cf_fake_continue_tail(capture_file *cf) { - cf->state = FILE_READ_DONE; +cf_fake_continue_tail(capture_file *cf) +{ + cf->state = FILE_READ_DONE; } cf_read_status_t cf_finish_tail(capture_file *cf, wtap_rec *rec, Buffer *buf, int *err) { - gchar *err_info; - gint64 data_offset; - dfilter_t *dfcode; - column_info *cinfo; - epan_dissect_t edt; - gboolean create_proto_tree; - guint tap_flags; - gboolean compiled _U_; - - /* Compile the current display filter. - * 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, NULL); - ws_assert(!cf->dfilter || (compiled && dfcode)); - - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); - - /* If any tap listeners require the columns, construct them. */ - cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; - - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a display filter; - * - * one of the tap listeners is going to apply a filter; - * - * one of the tap listeners requires a protocol tree; - * - * a postdissector wants field values or protocols on - * the first pass. - */ - create_proto_tree = - (dfcode != NULL || have_filtering_tap_listeners() || - (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids()); - - if (cf->provider.wth == NULL) { - cf_close(cf); - return CF_READ_ERROR; - } + gchar *err_info; + gint64 data_offset; + dfilter_t *dfcode; + column_info *cinfo; + epan_dissect_t edt; + gboolean create_proto_tree; + guint tap_flags; + gboolean compiled _U_; + + /* Compile the current display filter. + * 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, NULL); + ws_assert(!cf->dfilter || (compiled && dfcode)); + + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); + + /* If any tap listeners require the columns, construct them. */ + cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; + + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a display filter; + * + * one of the tap listeners is going to apply a filter; + * + * one of the tap listeners requires a protocol tree; + * + * a postdissector wants field values or protocols on + * the first pass. + */ + create_proto_tree = + (dfcode != NULL || have_filtering_tap_listeners() || + (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids()); + + if (cf->provider.wth == NULL) { + cf_close(cf); + return CF_READ_ERROR; + } + + /* Don't freeze/thaw the list when doing live capture */ + /*packet_list_freeze();*/ + + epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); - /* Don't freeze/thaw the list when doing live capture */ - /*packet_list_freeze();*/ + while ((wtap_read(cf->provider.wth, rec, buf, err, &err_info, &data_offset))) { + if (cf->state == FILE_READ_ABORTED) { + /* Well, the user decided to abort the read. Break out of the + loop, and let the code below (which is called even if there + aren't any packets left to read) exit. */ + break; + } + read_record(cf, rec, buf, dfcode, &edt, cinfo, data_offset); + wtap_rec_reset(rec); + } + + /* Cleanup and release all dfilter resources */ + dfilter_free(dfcode); - epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); + epan_dissect_cleanup(&edt); + + /* Don't freeze/thaw the list when doing live capture */ + /*packet_list_thaw();*/ - while ((wtap_read(cf->provider.wth, rec, buf, err, &err_info, &data_offset))) { if (cf->state == FILE_READ_ABORTED) { - /* Well, the user decided to abort the read. Break out of the - loop, and let the code below (which is called even if there - aren't any packets left to read) exit. */ - break; + /* Well, the user decided to abort the read. We're only called + when the child capture process closes the pipe to us (meaning + it's probably exited), so we can just close the capture + file; we return CF_READ_ABORTED so our caller can do whatever + is appropriate when that happens. */ + cf_close(cf); + return CF_READ_ABORTED; } - read_record(cf, rec, buf, dfcode, &edt, cinfo, data_offset); - wtap_rec_reset(rec); - } - /* Cleanup and release all dfilter resources */ - dfilter_free(dfcode); + /* We're done reading sequentially through the file. */ + cf->state = FILE_READ_DONE; - epan_dissect_cleanup(&edt); + /* We're done reading sequentially through the file; close the + sequential I/O side, to free up memory it requires. */ + wtap_sequential_close(cf->provider.wth); - /* Don't freeze/thaw the list when doing live capture */ - /*packet_list_thaw();*/ + /* Allow the protocol dissectors to free up memory that they + * don't need after the sequential run-through of the packets. */ + postseq_cleanup_all_protocols(); - if (cf->state == FILE_READ_ABORTED) { - /* Well, the user decided to abort the read. We're only called - when the child capture process closes the pipe to us (meaning - it's probably exited), so we can just close the capture - file; we return CF_READ_ABORTED so our caller can do whatever - is appropriate when that happens. */ - cf_close(cf); - return CF_READ_ABORTED; - } - - /* We're done reading sequentially through the file. */ - cf->state = FILE_READ_DONE; - - /* We're done reading sequentially through the file; close the - sequential I/O side, to free up memory it requires. */ - wtap_sequential_close(cf->provider.wth); - - /* Allow the protocol dissectors to free up memory that they - * don't need after the sequential run-through of the packets. */ - postseq_cleanup_all_protocols(); - - /* Update the file encapsulation; it might have changed based on the - packets we've read. */ - cf->lnk_t = wtap_file_encap(cf->provider.wth); - - /* Update the details in the file-set dialog, as the capture file - * has likely grown since we first stat-ed it */ - fileset_update_file(cf->filename); - - if (*err != 0) { - /* We got an error reading the capture file. - XXX - pop up a dialog box? */ - if (err_info != NULL) { - ws_warning("Error \"%s\" while reading \"%s\" (\"%s\")", - wtap_strerror(*err), cf->filename, err_info); - g_free(err_info); + /* Update the file encapsulation; it might have changed based on the + packets we've read. */ + cf->lnk_t = wtap_file_encap(cf->provider.wth); + + /* Update the details in the file-set dialog, as the capture file + * has likely grown since we first stat-ed it */ + fileset_update_file(cf->filename); + + if (*err != 0) { + /* We got an error reading the capture file. + XXX - pop up a dialog box? */ + if (err_info != NULL) { + ws_warning("Error \"%s\" while reading \"%s\" (\"%s\")", + wtap_strerror(*err), cf->filename, err_info); + g_free(err_info); + } else { + ws_warning("Error \"%s\" while reading \"%s\"", + wtap_strerror(*err), cf->filename); + } + return CF_READ_ERROR; } else { - ws_warning("Error \"%s\" while reading \"%s\"", - wtap_strerror(*err), cf->filename); + return CF_READ_OK; } - return CF_READ_ERROR; - } else { - return CF_READ_OK; - } } #endif /* HAVE_LIBPCAP */ gchar * cf_get_display_name(capture_file *cf) { - gchar *displayname; + gchar *displayname; - /* Return a name to use in displays */ - if (!cf->is_tempfile) { - /* Get the last component of the file name, and use that. */ - if (cf->filename) { - displayname = g_filename_display_basename(cf->filename); - } else { - displayname=g_strdup("(No file)"); - } - } else { - /* The file we read is a temporary file from a live capture or - a merge operation; we don't mention its name, but, if it's - from a capture, give the source of the capture. */ - if (cf->source) { - displayname = g_strdup(cf->source); + /* Return a name to use in displays */ + if (!cf->is_tempfile) { + /* Get the last component of the file name, and use that. */ + if (cf->filename) { + displayname = g_filename_display_basename(cf->filename); + } else { + displayname=g_strdup("(No file)"); + } } else { - displayname = g_strdup("(Untitled)"); + /* The file we read is a temporary file from a live capture or + a merge operation; we don't mention its name, but, if it's + from a capture, give the source of the capture. */ + if (cf->source) { + displayname = g_strdup(cf->source); + } else { + displayname = g_strdup("(Untitled)"); + } } - } - return displayname; + return displayname; } gchar * cf_get_basename(capture_file *cf) { - gchar *displayname; - - /* Return a name to use in the GUI for the basename for files to - which we save statistics */ - if (!cf->is_tempfile) { - /* Get the last component of the file name, and use that. */ - if (cf->filename) { - displayname = g_filename_display_basename(cf->filename); - - /* If the file name ends with any extension that corresponds - to a file type we support - including compressed versions - of those files - strip it off. */ - size_t displayname_len = strlen(displayname); - GSList *extensions = wtap_get_all_file_extensions_list(); - GSList *suffix; - for (suffix = extensions; suffix != NULL; suffix = g_slist_next(suffix)) { - /* Does the file name end with that extension? */ - const char *extension = (char *)suffix->data; - size_t extension_len = strlen(extension); - if (displayname_len > extension_len && - displayname[displayname_len - extension_len - 1] == '.' && - strcmp(&displayname[displayname_len - extension_len], extension) == 0) { - /* Yes. Strip the extension off, and return the result. */ - displayname[displayname_len - extension_len - 1] = '\0'; - break; + gchar *displayname; + + /* Return a name to use in the GUI for the basename for files to + which we save statistics */ + if (!cf->is_tempfile) { + /* Get the last component of the file name, and use that. */ + if (cf->filename) { + displayname = g_filename_display_basename(cf->filename); + + /* If the file name ends with any extension that corresponds + to a file type we support - including compressed versions + of those files - strip it off. */ + size_t displayname_len = strlen(displayname); + GSList *extensions = wtap_get_all_file_extensions_list(); + GSList *suffix; + for (suffix = extensions; suffix != NULL; suffix = g_slist_next(suffix)) { + /* Does the file name end with that extension? */ + const char *extension = (char *)suffix->data; + size_t extension_len = strlen(extension); + if (displayname_len > extension_len && + displayname[displayname_len - extension_len - 1] == '.' && + strcmp(&displayname[displayname_len - extension_len], extension) == 0) { + /* Yes. Strip the extension off, and return the result. */ + displayname[displayname_len - extension_len - 1] = '\0'; + break; + } + } + wtap_free_extensions_list(extensions); + } else { + displayname=g_strdup(""); } - } - wtap_free_extensions_list(extensions); - } else { - displayname=g_strdup(""); - } - } else { - /* The file we read is a temporary file from a live capture or - a merge operation; we don't mention its name, but, if it's - from a capture, give the source of the capture. */ - if (cf->source) { - displayname = g_strdup(cf->source); } else { - displayname = g_strdup(""); + /* The file we read is a temporary file from a live capture or + a merge operation; we don't mention its name, but, if it's + from a capture, give the source of the capture. */ + if (cf->source) { + displayname = g_strdup(cf->source); + } else { + displayname = g_strdup(""); + } } - } - return displayname; + return displayname; } -void cf_set_tempfile_source(capture_file *cf, gchar *source) { - if (cf->source) { - g_free(cf->source); - } +void +cf_set_tempfile_source(capture_file *cf, gchar *source) +{ + if (cf->source) { + g_free(cf->source); + } - if (source) { - cf->source = g_strdup(source); - } else { - cf->source = g_strdup(""); - } + if (source) { + cf->source = g_strdup(source); + } else { + cf->source = g_strdup(""); + } } -const gchar *cf_get_tempfile_source(capture_file *cf) { - if (!cf->source) { - return ""; - } +const gchar * +cf_get_tempfile_source(capture_file *cf) +{ + if (!cf->source) { + return ""; + } - return cf->source; + return cf->source; } /* XXX - use a macro instead? */ int cf_get_packet_count(capture_file *cf) { - return cf->count; + return cf->count; } /* XXX - use a macro instead? */ gboolean cf_is_tempfile(capture_file *cf) { - return cf->is_tempfile; + return cf->is_tempfile; } -void cf_set_tempfile(capture_file *cf, gboolean is_tempfile) +void +cf_set_tempfile(capture_file *cf, gboolean is_tempfile) { - cf->is_tempfile = is_tempfile; + cf->is_tempfile = is_tempfile; } /* XXX - use a macro instead? */ -void cf_set_drops_known(capture_file *cf, gboolean drops_known) +void +cf_set_drops_known(capture_file *cf, gboolean drops_known) { - cf->drops_known = drops_known; + cf->drops_known = drops_known; } /* XXX - use a macro instead? */ -void cf_set_drops(capture_file *cf, guint32 drops) +void +cf_set_drops(capture_file *cf, guint32 drops) { - cf->drops = drops; + cf->drops = drops; } /* XXX - use a macro instead? */ -gboolean cf_get_drops_known(capture_file *cf) +gboolean +cf_get_drops_known(capture_file *cf) { - return cf->drops_known; + return cf->drops_known; } /* XXX - use a macro instead? */ -guint32 cf_get_drops(capture_file *cf) +guint32 +cf_get_drops(capture_file *cf) { - return cf->drops; + return cf->drops; } -void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode) +void +cf_set_rfcode(capture_file *cf, dfilter_t *rfcode) { - cf->rfcode = rfcode; + cf->rfcode = rfcode; } static void add_packet_to_packet_list(frame_data *fdata, capture_file *cf, - epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo, - wtap_rec *rec, Buffer *buf, gboolean add_to_packet_list) + epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo, + wtap_rec *rec, Buffer *buf, gboolean add_to_packet_list) { - frame_data_set_before_dissect(fdata, &cf->elapsed_time, - &cf->provider.ref, cf->provider.prev_dis); - cf->provider.prev_cap = fdata; + frame_data_set_before_dissect(fdata, &cf->elapsed_time, + &cf->provider.ref, cf->provider.prev_dis); + cf->provider.prev_cap = fdata; - if (dfcode != NULL) { - epan_dissect_prime_with_dfilter(edt, dfcode); - } + if (dfcode != NULL) { + epan_dissect_prime_with_dfilter(edt, dfcode); + } #if 0 - /* Prepare coloring rules, this ensures that display filter rules containing - * frame.color_rule references are still processed. - * TODO: actually detect that situation or maybe apply other optimizations? */ - if (edt->tree && color_filters_used()) { - color_filters_prime_edt(edt); - fdata->need_colorize = 1; - } + /* Prepare coloring rules, this ensures that display filter rules containing + * frame.color_rule references are still processed. + * TODO: actually detect that situation or maybe apply other optimizations? */ + if (edt->tree && color_filters_used()) { + color_filters_prime_edt(edt); + fdata->need_colorize = 1; + } #endif - if (!fdata->visited) { - /* This is the first pass, so prime the epan_dissect_t with the - hfids postdissectors want on the first pass. */ - prime_epan_dissect_with_postdissector_wanted_hfids(edt); - } - - /* Dissect the frame. */ - epan_dissect_run_with_taps(edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, cinfo); - - /* If we don't have a display filter, set "passed_dfilter" to 1. */ - if (dfcode != NULL) { - fdata->passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0; - - if (fdata->passed_dfilter) { - /* This frame passed the display filter but it may depend on other - * (potentially not displayed) frames. Find those frames and mark them - * as depended upon. - */ - g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames); - } - } else - fdata->passed_dfilter = 1; - - if (fdata->passed_dfilter || fdata->ref_time) - cf->displayed_count++; - - if (add_to_packet_list) { - /* We fill the needed columns from new_packet_list */ - packet_list_append(cinfo, fdata); - } - - if (fdata->passed_dfilter || fdata->ref_time) - { - frame_data_set_after_dissect(fdata, &cf->cum_bytes); - cf->provider.prev_dis = fdata; - - /* If we haven't yet seen the first frame, this is it. */ - if (cf->first_displayed == 0) - cf->first_displayed = fdata->num; - - /* This is the last frame we've seen so far. */ - cf->last_displayed = fdata->num; - } - - epan_dissect_reset(edt); + if (!fdata->visited) { + /* This is the first pass, so prime the epan_dissect_t with the + hfids postdissectors want on the first pass. */ + prime_epan_dissect_with_postdissector_wanted_hfids(edt); + } + + /* Dissect the frame. */ + epan_dissect_run_with_taps(edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, cinfo); + + /* If we don't have a display filter, set "passed_dfilter" to 1. */ + if (dfcode != NULL) { + fdata->passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0; + + if (fdata->passed_dfilter) { + /* This frame passed the display filter but it may depend on other + * (potentially not displayed) frames. Find those frames and mark them + * as depended upon. + */ + g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames); + } + } else + fdata->passed_dfilter = 1; + + if (fdata->passed_dfilter || fdata->ref_time) + cf->displayed_count++; + + if (add_to_packet_list) { + /* We fill the needed columns from new_packet_list */ + packet_list_append(cinfo, fdata); + } + + if (fdata->passed_dfilter || fdata->ref_time) + { + frame_data_set_after_dissect(fdata, &cf->cum_bytes); + cf->provider.prev_dis = fdata; + + /* If we haven't yet seen the first frame, this is it. */ + if (cf->first_displayed == 0) + cf->first_displayed = fdata->num; + + /* This is the last frame we've seen so far. */ + cf->last_displayed = fdata->num; + } + + epan_dissect_reset(edt); } /* @@ -1253,365 +1264,365 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, */ static gboolean read_record(capture_file *cf, wtap_rec *rec, Buffer *buf, dfilter_t *dfcode, - epan_dissect_t *edt, column_info *cinfo, gint64 offset) + epan_dissect_t *edt, column_info *cinfo, gint64 offset) { - frame_data fdlocal; - frame_data *fdata; - gboolean passed = TRUE; - gboolean added = FALSE; - - /* Add this packet's link-layer encapsulation type to cf->linktypes, if - it's not already there. - XXX - yes, this is O(N), so if every packet had a different - link-layer encapsulation type, it'd be O(N^2) to read the file, but - there are probably going to be a small number of encapsulation types - in a file. */ - if (rec->rec_type == REC_TYPE_PACKET) { - cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap); - } - - /* The frame number of this packet, if we add it to the set of frames, - would be one more than the count of frames in the file so far. */ - frame_data_init(&fdlocal, cf->count + 1, rec, offset, cf->cum_bytes); - - if (cf->rfcode) { - epan_dissect_t rf_edt; - - epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE); - epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode); - epan_dissect_run(&rf_edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, &fdlocal, buf), - &fdlocal, NULL); - passed = dfilter_apply_edt(cf->rfcode, &rf_edt); - epan_dissect_cleanup(&rf_edt); - } - - if (passed) { - added = TRUE; - - /* This does a shallow copy of fdlocal, which is good enough. */ - fdata = frame_data_sequence_add(cf->provider.frames, &fdlocal); - - cf->count++; - if (rec->block != NULL) - cf->packet_comment_count += wtap_block_count_option(rec->block, OPT_COMMENT); - cf->f_datalen = offset + fdlocal.cap_len; - - /* When a redissection is in progress (or queued), do not process packets. - * This will be done once all (new) packets have been scanned. */ - if (!cf->redissecting && cf->redissection_queued == RESCAN_NONE) { - add_packet_to_packet_list(fdata, cf, edt, dfcode, cinfo, rec, buf, TRUE); - } - } - - return added; + frame_data fdlocal; + frame_data *fdata; + gboolean passed = TRUE; + gboolean added = FALSE; + + /* Add this packet's link-layer encapsulation type to cf->linktypes, if + it's not already there. + XXX - yes, this is O(N), so if every packet had a different + link-layer encapsulation type, it'd be O(N^2) to read the file, but + there are probably going to be a small number of encapsulation types + in a file. */ + if (rec->rec_type == REC_TYPE_PACKET) { + cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap); + } + + /* The frame number of this packet, if we add it to the set of frames, + would be one more than the count of frames in the file so far. */ + frame_data_init(&fdlocal, cf->count + 1, rec, offset, cf->cum_bytes); + + if (cf->rfcode) { + epan_dissect_t rf_edt; + + epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE); + epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode); + epan_dissect_run(&rf_edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, &fdlocal, buf), + &fdlocal, NULL); + passed = dfilter_apply_edt(cf->rfcode, &rf_edt); + epan_dissect_cleanup(&rf_edt); + } + + if (passed) { + added = TRUE; + + /* This does a shallow copy of fdlocal, which is good enough. */ + fdata = frame_data_sequence_add(cf->provider.frames, &fdlocal); + + cf->count++; + if (rec->block != NULL) + cf->packet_comment_count += wtap_block_count_option(rec->block, OPT_COMMENT); + cf->f_datalen = offset + fdlocal.cap_len; + + /* When a redissection is in progress (or queued), do not process packets. + * This will be done once all (new) packets have been scanned. */ + if (!cf->redissecting && cf->redissection_queued == RESCAN_NONE) { + add_packet_to_packet_list(fdata, cf, edt, dfcode, cinfo, rec, buf, TRUE); + } + } + + return added; } typedef struct _callback_data_t { - gpointer pd_window; - gint64 f_len; - progdlg_t *progbar; - GTimer *prog_timer; - gboolean stop_flag; + gpointer pd_window; + gint64 f_len; + progdlg_t *progbar; + GTimer *prog_timer; + gboolean stop_flag; } callback_data_t; static gboolean merge_callback(merge_event event, int num _U_, - const merge_in_file_t in_files[], const guint in_file_count, - void *data) + 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; + guint i; + callback_data_t *cb_data = (callback_data_t*) data; - ws_assert(cb_data != NULL); + ws_assert(cb_data != NULL); - switch (event) { + switch (event) { - case MERGE_EVENT_INPUT_FILES_OPENED: - /* do nothing */ - break; - - case MERGE_EVENT_FRAME_TYPE_SELECTED: - /* do nothing */ - break; + case MERGE_EVENT_INPUT_FILES_OPENED: + /* do nothing */ + break; - 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; + case MERGE_EVENT_FRAME_TYPE_SELECTED: + /* do nothing */ + break; - cb_data->prog_timer = g_timer_new(); - g_timer_start(cb_data->prog_timer); - break; + 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; - case MERGE_EVENT_RECORD_WAS_READ: - { - /* 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(cb_data->pd_window, NULL, NULL, - FALSE, &cb_data->stop_flag, 0.0f); - } + cb_data->prog_timer = g_timer_new(); + g_timer_start(cb_data->prog_timer); + break; - /* - * Update the progress bar, but do it only after - * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg - * and packets_bar_update will likely trigger UI paint events, which - * might take a while depending on the platform and display. Reset - * our timer *after* painting. - */ - if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { - 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; + case MERGE_EVENT_RECORD_WAS_READ: + { + /* 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(cb_data->pd_window, NULL, NULL, + FALSE, &cb_data->stop_flag, 0.0f); + } + + /* + * Update the progress bar, but do it only after + * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg + * and packets_bar_update will likely trigger UI paint events, which + * might take a while depending on the platform and display. Reset + * our timer *after* painting. + */ + if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { + 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 (cb_data->progbar != NULL) { + gchar status_str[100]; + snprintf(status_str, sizeof(status_str), + "%" PRId64 "KB of %" PRId64 "KB", + file_pos / 1024, cb_data->f_len / 1024); + update_progress_dlg(cb_data->progbar, progbar_val, status_str); + } + g_timer_start(cb_data->prog_timer); + } } + break; - if (cb_data->progbar != NULL) { - gchar status_str[100]; - snprintf(status_str, sizeof(status_str), - "%" PRId64 "KB of %" PRId64 "KB", - file_pos / 1024, cb_data->f_len / 1024); - update_progress_dlg(cb_data->progbar, progbar_val, status_str); - } - g_timer_start(cb_data->prog_timer); - } - } - break; - - 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); - g_timer_destroy(cb_data->prog_timer); - break; - } - - return cb_data->stop_flag; + 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); + g_timer_destroy(cb_data->prog_timer); + break; + } + + return cb_data->stop_flag; } cf_status_t cf_merge_files_to_tempfile(gpointer pd_window, const char *temp_dir, char **out_filenamep, - int in_file_count, const char *const *in_filenames, - int file_type, gboolean do_append) + int in_file_count, const char *const *in_filenames, + int file_type, gboolean do_append) { - int err = 0; - gchar *err_info = NULL; - guint err_fileno; - guint32 err_framenum; - merge_result status; - merge_progress_callback_t cb; - callback_data_t *cb_data = g_new0(callback_data_t, 1); - - /* prepare our callback routine */ - cb_data->pd_window = pd_window; - cb.callback_func = merge_callback; - cb.data = cb_data; - - cf_callback_invoke(cf_cb_file_merge_started, NULL); - - /* merge the files */ - status = merge_files_to_tempfile(temp_dir, out_filenamep, "wireshark", file_type, - in_filenames, - in_file_count, do_append, - IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */, - "Wireshark", &cb, &err, &err_info, - &err_fileno, &err_framenum); - - g_free(cb.data); - - switch (status) { - case MERGE_OK: - break; - - case MERGE_USER_ABORTED: - /* this isn't really an error, though we will return CF_ERROR later */ - break; - - case MERGE_ERR_CANT_OPEN_INFILE: - cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info); - break; - - case MERGE_ERR_CANT_OPEN_OUTFILE: - cfile_dump_open_failure_alert_box(*out_filenamep, err, err_info, - file_type); - break; - - case MERGE_ERR_CANT_READ_INFILE: - cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info); - break; - - case MERGE_ERR_BAD_PHDR_INTERFACE_ID: - simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.", - err_framenum, in_filenames[err_fileno]); - break; - - case MERGE_ERR_CANT_WRITE_OUTFILE: - cfile_write_failure_alert_box(in_filenames[err_fileno], - *out_filenamep, err, err_info, - err_framenum, file_type); - break; - - case MERGE_ERR_CANT_CLOSE_OUTFILE: - cfile_close_failure_alert_box(*out_filenamep, err, err_info); - break; - - default: - simple_error_message_box("Unknown merge_files error %d", status); - break; - } - - cf_callback_invoke(cf_cb_file_merge_finished, NULL); - - 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. */ - return CF_ERROR; - } else - return CF_OK; + int err = 0; + gchar *err_info = NULL; + guint err_fileno; + guint32 err_framenum; + merge_result status; + merge_progress_callback_t cb; + callback_data_t *cb_data = g_new0(callback_data_t, 1); + + /* prepare our callback routine */ + cb_data->pd_window = pd_window; + cb.callback_func = merge_callback; + cb.data = cb_data; + + cf_callback_invoke(cf_cb_file_merge_started, NULL); + + /* merge the files */ + status = merge_files_to_tempfile(temp_dir, out_filenamep, "wireshark", file_type, + in_filenames, + in_file_count, do_append, + IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */, + "Wireshark", &cb, &err, &err_info, + &err_fileno, &err_framenum); + + g_free(cb.data); + + switch (status) { + case MERGE_OK: + break; + + case MERGE_USER_ABORTED: + /* this isn't really an error, though we will return CF_ERROR later */ + break; + + case MERGE_ERR_CANT_OPEN_INFILE: + cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info); + break; + + case MERGE_ERR_CANT_OPEN_OUTFILE: + cfile_dump_open_failure_alert_box(*out_filenamep, err, err_info, + file_type); + break; + + case MERGE_ERR_CANT_READ_INFILE: + cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info); + break; + + case MERGE_ERR_BAD_PHDR_INTERFACE_ID: + simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.", + err_framenum, in_filenames[err_fileno]); + break; + + case MERGE_ERR_CANT_WRITE_OUTFILE: + cfile_write_failure_alert_box(in_filenames[err_fileno], + *out_filenamep, err, err_info, + err_framenum, file_type); + break; + + case MERGE_ERR_CANT_CLOSE_OUTFILE: + cfile_close_failure_alert_box(*out_filenamep, err, err_info); + break; + + default: + simple_error_message_box("Unknown merge_files error %d", status); + break; + } + + cf_callback_invoke(cf_cb_file_merge_finished, NULL); + + 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. */ + return CF_ERROR; + } else + return CF_OK; } cf_status_t 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; + const char *filter_new = dftext ? dftext : ""; + const char *filter_old = cf->dfilter ? cf->dfilter : ""; + dfilter_t *dfcode; + gchar *err_msg; + + /* if new filter equals old one, do nothing unless told to do so */ + if (!force && strcmp(filter_new, filter_old) == 0) { + return CF_OK; + } - /* if new filter equals old one, do nothing unless told to do so */ - if (!force && strcmp(filter_new, filter_old) == 0) { - return CF_OK; - } + dfcode=NULL; + + if (dftext == NULL) { + /* The new filter is an empty filter (i.e., display all packets). + * so leave dfcode==NULL + */ + } else { + /* + * We have a filter; make a copy of it (as we'll be saving it), + * and try to compile it. + */ + dftext = g_strdup(dftext); + 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, err_msg); + g_free(err_msg); + g_free(dftext); + return CF_ERROR; + } - dfcode=NULL; + /* Was it empty? */ + if (dfcode == NULL) { + /* Yes - free the filter text, and set it to null. */ + g_free(dftext); + dftext = NULL; + } + } - if (dftext == NULL) { - /* The new filter is an empty filter (i.e., display all packets). - * so leave dfcode==NULL - */ - } else { - /* - * We have a filter; make a copy of it (as we'll be saving it), - * and try to compile it. + /* We have a valid filter. Replace the current filter. */ + g_free(cf->dfilter); + cf->dfilter = dftext; + + + /* Now rescan the packet list, applying the new filter, but not + * throwing away information constructed on a previous pass. + * If a dissection is already in progress, queue it. */ - dftext = g_strdup(dftext); - 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, err_msg); - g_free(err_msg); - g_free(dftext); - return CF_ERROR; - } - - /* Was it empty? */ - if (dfcode == NULL) { - /* Yes - free the filter text, and set it to null. */ - g_free(dftext); - dftext = NULL; - } - } - - /* We have a valid filter. Replace the current filter. */ - g_free(cf->dfilter); - cf->dfilter = dftext; - - - /* Now rescan the packet list, applying the new filter, but not - * throwing away information constructed on a previous pass. - * If a dissection is already in progress, queue it. - */ - if (cf->redissection_queued == RESCAN_NONE) { - if (cf->read_lock) { - cf->redissection_queued = RESCAN_SCAN; - } else if (cf->state != FILE_CLOSED) { - if (dftext == NULL) { - rescan_packets(cf, "Resetting", "filter", FALSE); - } else { - rescan_packets(cf, "Filtering", dftext, FALSE); - } + if (cf->redissection_queued == RESCAN_NONE) { + if (cf->read_lock) { + cf->redissection_queued = RESCAN_SCAN; + } else 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 */ - dfilter_free(dfcode); + /* Cleanup and release all dfilter resources */ + dfilter_free(dfcode); - return CF_OK; + return CF_OK; } void cf_redissect_packets(capture_file *cf) { - if (cf->read_lock || cf->redissection_queued == RESCAN_SCAN) { - /* Dissection in progress, signal redissection rather than rescanning. That - * would destroy the current (in-progress) dissection in "cf_read" which - * will cause issues when "cf_read" tries to add packets to the list. - * If a previous rescan was requested, "upgrade" it to a full redissection. - */ - cf->redissection_queued = RESCAN_REDISSECT; - } - if (cf->redissection_queued != RESCAN_NONE) { - /* Redissection is (already) queued, wait for "cf_read" to finish. */ - return; - } - - if (cf->state != FILE_CLOSED) { - /* Restart dissection in case no cf_read is pending. */ - rescan_packets(cf, "Reprocessing", "all packets", TRUE); - } + if (cf->read_lock || cf->redissection_queued == RESCAN_SCAN) { + /* Dissection in progress, signal redissection rather than rescanning. That + * would destroy the current (in-progress) dissection in "cf_read" which + * will cause issues when "cf_read" tries to add packets to the list. + * If a previous rescan was requested, "upgrade" it to a full redissection. + */ + cf->redissection_queued = RESCAN_REDISSECT; + } + if (cf->redissection_queued != RESCAN_NONE) { + /* Redissection is (already) queued, wait for "cf_read" to finish. */ + return; + } + + if (cf->state != FILE_CLOSED) { + /* Restart dissection in case no cf_read is pending. */ + rescan_packets(cf, "Reprocessing", "all packets", TRUE); + } } gboolean cf_read_record(capture_file *cf, const frame_data *fdata, - wtap_rec *rec, Buffer *buf) + wtap_rec *rec, Buffer *buf) { - int err; - gchar *err_info; + int err; + gchar *err_info; - if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) { - cfile_read_failure_alert_box(cf->filename, err, err_info); - return FALSE; - } - return TRUE; + if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) { + cfile_read_failure_alert_box(cf->filename, err, err_info); + return FALSE; + } + return TRUE; } gboolean cf_read_record_no_alert(capture_file *cf, const frame_data *fdata, - wtap_rec *rec, Buffer *buf) + wtap_rec *rec, Buffer *buf) { - int err; - gchar *err_info; + int err; + gchar *err_info; - if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) { - g_free(err_info); - return FALSE; - } - return TRUE; + if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) { + g_free(err_info); + return FALSE; + } + return TRUE; } gboolean cf_read_current_record(capture_file *cf) { - return cf_read_record(cf, cf->current_frame, &cf->rec, &cf->buf); + return cf_read_record(cf, cf->current_frame, &cf->rec, &cf->buf); } /* Rescan the list of packets, reconstructing the CList. @@ -1629,390 +1640,390 @@ cf_read_current_record(capture_file *cf) static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect) { - /* Rescan packets new packet list */ - guint32 framenum; - frame_data *fdata; - wtap_rec rec; - Buffer buf; - progdlg_t *progbar = NULL; - GTimer *prog_timer = g_timer_new(); - 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; - gboolean selected_frame_seen; - float progbar_val; - gint64 start_time; - gchar status_str[100]; - epan_dissect_t edt; - dfilter_t *dfcode; - column_info *cinfo; - gboolean create_proto_tree; - guint tap_flags; - gboolean add_to_packet_list = FALSE; - gboolean compiled _U_; - guint32 frames_count; - gboolean queued_rescan_type = RESCAN_NONE; - - /* Rescan in progress, clear pending actions. */ - cf->redissection_queued = RESCAN_NONE; - ws_assert(!cf->read_lock); - cf->read_lock = TRUE; - - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); - - /* Compile the current display filter. - * 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, NULL); - ws_assert(!cf->dfilter || (compiled && dfcode)); - - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); - - /* If any tap listeners require the columns, construct them. */ - cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; - - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a display filter; - * - * one of the tap listeners is going to apply a filter; - * - * one of the tap listeners requires a protocol tree; - * - * we're redissecting and a postdissector wants field - * values or protocols on the first pass. - */ - create_proto_tree = - (dfcode != NULL || have_filtering_tap_listeners() || - (tap_flags & TL_REQUIRES_PROTO_TREE) || - (redissect && postdissectors_want_hfids())); - - reset_tap_listeners(); - /* Which frame, if any, is the currently selected frame? - XXX - should the selected frame or the focus frame be the "current" - frame, that frame being the one from which "Find Frame" searches - start? */ - selected_frame = cf->current_frame; - - /* Mark frame num as not found */ - selected_frame_num = -1; - - /* Freeze the packet list while we redo it, so we don't get any - screen updates while it happens. */ - packet_list_freeze(); - - if (redissect) { - /* We need to re-initialize all the state information that protocols - keep, because some preference that controls a dissector has changed, - which might cause the state information to be constructed differently - by that dissector. */ - - /* We might receive new packets while redissecting, and we don't - want to dissect those before their time. */ - cf->redissecting = TRUE; - - /* 'reset' dissection session */ - epan_free(cf->epan); - if (cf->edt && cf->edt->pi.fd) { - /* All pointers in "per frame proto data" for the currently selected - packet are allocated in wmem_file_scope() and deallocated in epan_free(). - Free them here to avoid unintended usage in packet_list_clear(). */ - frame_data_destroy(cf->edt->pi.fd); - } - cf->epan = ws_epan_new(cf); - cf->cinfo.epan = cf->epan; + /* Rescan packets new packet list */ + guint32 framenum; + frame_data *fdata; + wtap_rec rec; + Buffer buf; + progdlg_t *progbar = NULL; + GTimer *prog_timer = g_timer_new(); + 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; + gboolean selected_frame_seen; + float progbar_val; + gint64 start_time; + gchar status_str[100]; + epan_dissect_t edt; + dfilter_t *dfcode; + column_info *cinfo; + gboolean create_proto_tree; + guint tap_flags; + gboolean add_to_packet_list = FALSE; + gboolean compiled _U_; + guint32 frames_count; + gboolean queued_rescan_type = RESCAN_NONE; + + /* Rescan in progress, clear pending actions. */ + cf->redissection_queued = RESCAN_NONE; + ws_assert(!cf->read_lock); + cf->read_lock = TRUE; - /* A new Lua tap listener may be registered in lua_prime_all_fields() - called via epan_new() / init_dissection() when reloading Lua plugins. */ - if (!create_proto_tree && have_filtering_tap_listeners()) { - create_proto_tree = TRUE; - } + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); - /* We need to redissect the packets so we have to discard our old - * packet list store. */ - packet_list_clear(); - add_to_packet_list = TRUE; - } + /* Compile the current display filter. + * 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, NULL); + ws_assert(!cf->dfilter || (compiled && dfcode)); - /* We don't yet know which will be the first and last frames displayed. */ - cf->first_displayed = 0; - cf->last_displayed = 0; + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); - /* We currently don't display any packets */ - cf->displayed_count = 0; + /* If any tap listeners require the columns, construct them. */ + cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; - /* Iterate through the list of frames. Call a routine for each frame - to check whether it should be displayed and, if so, add it to - the display list. */ - cf->provider.ref = NULL; - cf->provider.prev_dis = NULL; - cf->provider.prev_cap = NULL; - cf->cum_bytes = 0; + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a display filter; + * + * one of the tap listeners is going to apply a filter; + * + * one of the tap listeners requires a protocol tree; + * + * we're redissecting and a postdissector wants field + * values or protocols on the first pass. + */ + create_proto_tree = + (dfcode != NULL || have_filtering_tap_listeners() || + (tap_flags & TL_REQUIRES_PROTO_TREE) || + (redissect && postdissectors_want_hfids())); - cf_callback_invoke(cf_cb_file_rescan_started, cf); + reset_tap_listeners(); + /* Which frame, if any, is the currently selected frame? + XXX - should the selected frame or the focus frame be the "current" + frame, that frame being the one from which "Find Frame" searches + start? */ + selected_frame = cf->current_frame; - g_timer_start(prog_timer); - /* Count of packets at which we've looked. */ - count = 0; - /* Progress so far. */ - progbar_val = 0.0f; + /* Mark frame num as not found */ + selected_frame_num = -1; - cf->stop_flag = FALSE; - start_time = g_get_monotonic_time(); + /* Freeze the packet list while we redo it, so we don't get any + screen updates while it happens. */ + packet_list_freeze(); - /* no previous row yet */ - prev_frame_num = -1; - prev_frame = NULL; + if (redissect) { + /* We need to re-initialize all the state information that protocols + keep, because some preference that controls a dissector has changed, + which might cause the state information to be constructed differently + by that dissector. */ + + /* We might receive new packets while redissecting, and we don't + want to dissect those before their time. */ + cf->redissecting = TRUE; + + /* 'reset' dissection session */ + epan_free(cf->epan); + if (cf->edt && cf->edt->pi.fd) { + /* All pointers in "per frame proto data" for the currently selected + packet are allocated in wmem_file_scope() and deallocated in epan_free(). + Free them here to avoid unintended usage in packet_list_clear(). */ + frame_data_destroy(cf->edt->pi.fd); + } + cf->epan = ws_epan_new(cf); + cf->cinfo.epan = cf->epan; - preceding_frame_num = -1; - preceding_frame = NULL; - following_frame_num = -1; - following_frame = NULL; + /* A new Lua tap listener may be registered in lua_prime_all_fields() + called via epan_new() / init_dissection() when reloading Lua plugins. */ + if (!create_proto_tree && have_filtering_tap_listeners()) { + create_proto_tree = TRUE; + } - selected_frame_seen = FALSE; + /* We need to redissect the packets so we have to discard our old + * packet list store. */ + packet_list_clear(); + add_to_packet_list = TRUE; + } - frames_count = cf->count; + /* We don't yet know which will be the first and last frames displayed. */ + cf->first_displayed = 0; + cf->last_displayed = 0; - epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); + /* We currently don't display any packets */ + cf->displayed_count = 0; - if (redissect) { - /* - * Decryption secrets are read while sequentially processing records and - * then passed to the dissector. During redissection, the previous secrets - * are lost (see epan_free above), but they are not read again from the - * file as only packet records are re-read. Therefore reset the wtap secrets - * callback such that wtap resupplies the secrets callback with previously - * read secrets. - */ - wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback); - } + /* Iterate through the list of frames. Call a routine for each frame + to check whether it should be displayed and, if so, add it to + the display list. */ + cf->provider.ref = NULL; + cf->provider.prev_dis = NULL; + cf->provider.prev_cap = NULL; + cf->cum_bytes = 0; - for (framenum = 1; framenum <= frames_count; framenum++) { - fdata = frame_data_sequence_find(cf->provider.frames, framenum); + cf_callback_invoke(cf_cb_file_rescan_started, cf); - /* 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(cf->window, action, action_item, TRUE, - &cf->stop_flag, - progbar_val); + g_timer_start(prog_timer); + /* Count of packets at which we've looked. */ + count = 0; + /* Progress so far. */ + progbar_val = 0.0f; - /* - * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL - * has elapsed. Calling update_progress_dlg and packets_bar_update will - * likely trigger UI paint events, which might take a while depending on - * the platform and display. Reset our timer *after* painting. - */ - if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { - /* let's not divide by zero. I should never be started - * with count == 0, so let's assert that - */ - ws_assert(cf->count > 0); - progbar_val = (gfloat) count / frames_count; + cf->stop_flag = FALSE; + start_time = g_get_monotonic_time(); - if (progbar != NULL) { - snprintf(status_str, sizeof(status_str), - "%4u of %u frames", count, frames_count); - update_progress_dlg(progbar, progbar_val, status_str); - } + /* no previous row yet */ + prev_frame_num = -1; + prev_frame = NULL; - g_timer_start(prog_timer); - } + preceding_frame_num = -1; + preceding_frame = NULL; + following_frame_num = -1; + following_frame = NULL; - queued_rescan_type = cf->redissection_queued; - if (queued_rescan_type != RESCAN_NONE) { - /* A redissection was requested while an existing redissection was - * pending. */ - break; + selected_frame_seen = FALSE; + + frames_count = cf->count; + + epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); + + if (redissect) { + /* + * Decryption secrets are read while sequentially processing records and + * then passed to the dissector. During redissection, the previous secrets + * are lost (see epan_free above), but they are not read again from the + * file as only packet records are re-read. Therefore reset the wtap secrets + * callback such that wtap resupplies the secrets callback with previously + * read secrets. + */ + wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback); } - if (cf->stop_flag) { - /* Well, the user decided to abort the filtering. Just stop. + for (framenum = 1; framenum <= frames_count; framenum++) { + fdata = frame_data_sequence_find(cf->provider.frames, framenum); + + /* 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(cf->window, action, action_item, TRUE, + &cf->stop_flag, + progbar_val); - XXX - go back to the previous filter? Users probably just - want not to wait for a filtering operation to finish; - unless we cancel by having no filter, reverting to the - previous filter will probably be even more expensive than - continuing the filtering, as it involves going back to the - beginning and filtering, and even with no filter we currently - have to re-generate the entire clist, which is also expensive. + /* + * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL + * has elapsed. Calling update_progress_dlg and packets_bar_update will + * likely trigger UI paint events, which might take a while depending on + * the platform and display. Reset our timer *after* painting. + */ + if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { + /* let's not divide by zero. I should never be started + * with count == 0, so let's assert that + */ + ws_assert(cf->count > 0); + progbar_val = (gfloat) count / frames_count; - I'm not sure what Network Monitor does, but it doesn't appear - to give you an unfiltered display if you cancel. */ - break; + if (progbar != NULL) { + snprintf(status_str, sizeof(status_str), + "%4u of %u frames", count, frames_count); + update_progress_dlg(progbar, progbar_val, status_str); + } + + g_timer_start(prog_timer); + } + + queued_rescan_type = cf->redissection_queued; + if (queued_rescan_type != RESCAN_NONE) { + /* A redissection was requested while an existing redissection was + * pending. */ + break; + } + + if (cf->stop_flag) { + /* Well, the user decided to abort the filtering. Just stop. + + XXX - go back to the previous filter? Users probably just + want not to wait for a filtering operation to finish; + unless we cancel by having no filter, reverting to the + previous filter will probably be even more expensive than + continuing the filtering, as it involves going back to the + beginning and filtering, and even with no filter we currently + have to re-generate the entire clist, which is also expensive. + + I'm not sure what Network Monitor does, but it doesn't appear + to give you an unfiltered display if you cancel. */ + break; + } + + count++; + + if (redissect) { + /* Since all state for the frame was destroyed, mark the frame + * as not visited, free the GSList referring to the state + * data (the per-frame data itself was freed by + * "init_dissection()"), and null out the GSList pointer. */ + frame_data_reset(fdata); + frames_count = cf->count; + } + + /* Frame dependencies from the previous dissection/filtering are no longer valid. */ + fdata->dependent_of_displayed = 0; + + if (!cf_read_record(cf, fdata, &rec, &buf)) + break; /* error reading the frame */ + + /* If the previous frame is displayed, and we haven't yet seen the + selected frame, remember that frame - it's the closest one we've + yet seen before the selected frame. */ + if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->passed_dfilter) { + preceding_frame_num = prev_frame_num; + preceding_frame = prev_frame; + } + + add_packet_to_packet_list(fdata, cf, &edt, dfcode, + cinfo, &rec, &buf, + add_to_packet_list); + + /* If this frame is displayed, and this is the first frame we've + seen displayed after the selected frame, remember this frame - + it's the closest one we've yet seen at or after the selected + frame. */ + if (fdata->passed_dfilter && selected_frame_seen && following_frame_num == -1) { + following_frame_num = fdata->num; + following_frame = fdata; + } + if (fdata == selected_frame) { + selected_frame_seen = TRUE; + if (fdata->passed_dfilter) + selected_frame_num = fdata->num; + } + + /* Remember this frame - it'll be the previous frame + on the next pass through the loop. */ + prev_frame_num = fdata->num; + prev_frame = fdata; + wtap_rec_reset(&rec); } - count++; + epan_dissect_cleanup(&edt); + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + + /* We are done redissecting the packet list. */ + cf->redissecting = FALSE; if (redissect) { - /* Since all state for the frame was destroyed, mark the frame - * as not visited, free the GSList referring to the state - * data (the per-frame data itself was freed by - * "init_dissection()"), and null out the GSList pointer. */ - frame_data_reset(fdata); - frames_count = cf->count; - } - - /* Frame dependencies from the previous dissection/filtering are no longer valid. */ - fdata->dependent_of_displayed = 0; - - if (!cf_read_record(cf, fdata, &rec, &buf)) - break; /* error reading the frame */ - - /* If the previous frame is displayed, and we haven't yet seen the - selected frame, remember that frame - it's the closest one we've - yet seen before the selected frame. */ - if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->passed_dfilter) { - preceding_frame_num = prev_frame_num; - preceding_frame = prev_frame; - } - - add_packet_to_packet_list(fdata, cf, &edt, dfcode, - cinfo, &rec, &buf, - add_to_packet_list); - - /* If this frame is displayed, and this is the first frame we've - seen displayed after the selected frame, remember this frame - - it's the closest one we've yet seen at or after the selected - frame. */ - if (fdata->passed_dfilter && selected_frame_seen && following_frame_num == -1) { - following_frame_num = fdata->num; - following_frame = fdata; - } - if (fdata == selected_frame) { - selected_frame_seen = TRUE; - if (fdata->passed_dfilter) - selected_frame_num = fdata->num; - } - - /* Remember this frame - it'll be the previous frame - on the next pass through the loop. */ - prev_frame_num = fdata->num; - prev_frame = fdata; - wtap_rec_reset(&rec); - } - - epan_dissect_cleanup(&edt); - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - - /* We are done redissecting the packet list. */ - cf->redissecting = FALSE; - - if (redissect) { - frames_count = cf->count; - /* Clear out what remains of the visited flags and per-frame data - pointers. - - XXX - that may cause various forms of bogosity when dissecting - these frames, as they won't have been seen by this sequential - pass, but the only alternative I see is to keep scanning them - even though the user requested that the scan stop, and that - would leave the user stuck with an Wireshark grinding on - until it finishes. Should we just stick them with that? */ - for (; framenum <= frames_count; framenum++) { - fdata = frame_data_sequence_find(cf->provider.frames, framenum); - frame_data_reset(fdata); - } - } - - /* We're done filtering the packets; destroy the progress bar if it - was created. */ - if (progbar != NULL) - destroy_progress_dlg(progbar); - g_timer_destroy(prog_timer); - - /* Unfreeze the packet list. */ - if (!add_to_packet_list) - packet_list_recreate_visible_rows(); - - /* Compute the time it took to filter the file */ - compute_elapsed(cf, start_time); - - 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) { - /* That's because there *was* no selected frame. Make the first - displayed frame the current frame. */ - selected_frame_num = 0; + frames_count = cf->count; + /* Clear out what remains of the visited flags and per-frame data + pointers. + + XXX - that may cause various forms of bogosity when dissecting + these frames, as they won't have been seen by this sequential + pass, but the only alternative I see is to keep scanning them + even though the user requested that the scan stop, and that + would leave the user stuck with an Wireshark grinding on + until it finishes. Should we just stick them with that? */ + for (; framenum <= frames_count; framenum++) { + fdata = frame_data_sequence_find(cf->provider.frames, framenum); + frame_data_reset(fdata); + } + } + + /* We're done filtering the packets; destroy the progress bar if it + was created. */ + if (progbar != NULL) + destroy_progress_dlg(progbar); + g_timer_destroy(prog_timer); + + /* Unfreeze the packet list. */ + if (!add_to_packet_list) + packet_list_recreate_visible_rows(); + + /* Compute the time it took to filter the file */ + compute_elapsed(cf, start_time); + + 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) { + /* That's because there *was* no selected frame. Make the first + displayed frame the current frame. */ + selected_frame_num = 0; + } else { + /* Find the nearest displayed frame to the selected frame (whether + it's before or after that frame) and make that the current frame. + If the next and previous displayed frames are equidistant from the + selected frame, choose the next one. */ + ws_assert(following_frame == NULL || + following_frame->num >= selected_frame->num); + ws_assert(preceding_frame == NULL || + preceding_frame->num <= selected_frame->num); + if (following_frame == NULL) { + /* No frame after the selected frame passed the filter, so we + have to select the last displayed frame before the selected + frame. */ + selected_frame_num = preceding_frame_num; + selected_frame = preceding_frame; + } else if (preceding_frame == NULL) { + /* No frame before the selected frame passed the filter, so we + have to select the first displayed frame after the selected + frame. */ + selected_frame_num = following_frame_num; + selected_frame = following_frame; + } else { + /* Frames before and after the selected frame passed the filter, so + we'll select the previous frame */ + selected_frame_num = preceding_frame_num; + selected_frame = preceding_frame; + } + } + } + + if (selected_frame_num == -1) { + /* There are no frames displayed at all. */ + cf_unselect_packet(cf); } else { - /* Find the nearest displayed frame to the selected frame (whether - it's before or after that frame) and make that the current frame. - If the next and previous displayed frames are equidistant from the - selected frame, choose the next one. */ - ws_assert(following_frame == NULL || - following_frame->num >= selected_frame->num); - ws_assert(preceding_frame == NULL || - preceding_frame->num <= selected_frame->num); - if (following_frame == NULL) { - /* No frame after the selected frame passed the filter, so we - have to select the last displayed frame before the selected - frame. */ - selected_frame_num = preceding_frame_num; - selected_frame = preceding_frame; - } else if (preceding_frame == NULL) { - /* No frame before the selected frame passed the filter, so we - have to select the first displayed frame after the selected - frame. */ - selected_frame_num = following_frame_num; - selected_frame = following_frame; - } else { - /* Frames before and after the selected frame passed the filter, so - we'll select the previous frame */ - selected_frame_num = preceding_frame_num; - selected_frame = preceding_frame; - } - } - } - - if (selected_frame_num == -1) { - /* There are no frames displayed at all. */ - cf_unselect_packet(cf); - } else { - /* Either the frame that was selected passed the filter, or we've - found the nearest displayed frame to that frame. Select it, make - it the focus row, and make it visible. */ - /* Set to invalid to force update of packet list and packet details */ - cf->current_row = -1; - if (selected_frame_num == 0) { - packet_list_select_first_row(); - }else{ - if (!packet_list_select_row_from_data(selected_frame)) { - /* We didn't find a row corresponding to this frame. - This means that the frame isn't being displayed currently, - 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."); - } + /* Either the frame that was selected passed the filter, or we've + found the nearest displayed frame to that frame. Select it, make + it the focus row, and make it visible. */ + /* Set to invalid to force update of packet list and packet details */ + cf->current_row = -1; + if (selected_frame_num == 0) { + packet_list_select_first_row(); + }else{ + if (!packet_list_select_row_from_data(selected_frame)) { + /* We didn't find a row corresponding to this frame. + This means that the frame isn't being displayed currently, + 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."); + } + } } - } - /* Cleanup and release all dfilter resources */ - dfilter_free(dfcode); + /* Cleanup and release all dfilter resources */ + dfilter_free(dfcode); - /* It is safe again to execute redissections. */ - ws_assert(cf->read_lock); - cf->read_lock = FALSE; + /* It is safe again to execute redissections. */ + ws_assert(cf->read_lock); + cf->read_lock = FALSE; - /* If another rescan (due to dfilter change) or redissection (due to profile - * change) was requested, the rescan above is aborted and restarted here. */ - if (queued_rescan_type != RESCAN_NONE) { - redissect = redissect || queued_rescan_type == RESCAN_REDISSECT; - rescan_packets(cf, "Reprocessing", "all packets", redissect); - } + /* If another rescan (due to dfilter change) or redissection (due to profile + * change) was requested, the rescan above is aborted and restarted here. */ + if (queued_rescan_type != RESCAN_NONE) { + redissect = redissect || queued_rescan_type == RESCAN_REDISSECT; + rescan_packets(cf, "Reprocessing", "all packets", redissect); + } } @@ -2024,1233 +2035,1233 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb void cf_reftime_packets(capture_file* cf) { - guint32 framenum; - frame_data *fdata; - nstime_t rel_ts; + guint32 framenum; + frame_data *fdata; + nstime_t rel_ts; - cf->provider.ref = NULL; - cf->provider.prev_dis = NULL; - cf->cum_bytes = 0; + cf->provider.ref = NULL; + cf->provider.prev_dis = NULL; + cf->cum_bytes = 0; - for (framenum = 1; framenum <= cf->count; framenum++) { - fdata = frame_data_sequence_find(cf->provider.frames, framenum); + for (framenum = 1; framenum <= cf->count; framenum++) { + fdata = frame_data_sequence_find(cf->provider.frames, framenum); - /* just add some value here until we know if it is being displayed or not */ - fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len; + /* just add some value here until we know if it is being displayed or not */ + fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len; - /* - *Timestamps - */ + /* + *Timestamps + */ - /* If we don't have the time stamp of the first packet in the - capture, it's because this is the first packet. Save the time - stamp of this packet as the time stamp of the first packet. */ - if (cf->provider.ref == NULL) - cf->provider.ref = fdata; - /* if this frames is marked as a reference time frame, reset - firstsec and firstusec to this frame */ - if (fdata->ref_time) - cf->provider.ref = fdata; - - /* If we don't have the time stamp of the previous displayed packet, - it's because this is the first displayed packet. Save the time - stamp of this packet as the time stamp of the previous displayed - packet. */ - if (cf->provider.prev_dis == NULL) { - cf->provider.prev_dis = fdata; - } + /* If we don't have the time stamp of the first packet in the + capture, it's because this is the first packet. Save the time + stamp of this packet as the time stamp of the first packet. */ + if (cf->provider.ref == NULL) + cf->provider.ref = fdata; + /* if this frames is marked as a reference time frame, reset + firstsec and firstusec to this frame */ + if (fdata->ref_time) + cf->provider.ref = fdata; + + /* If we don't have the time stamp of the previous displayed packet, + it's because this is the first displayed packet. Save the time + stamp of this packet as the time stamp of the previous displayed + packet. */ + if (cf->provider.prev_dis == NULL) { + cf->provider.prev_dis = fdata; + } - /* Get the time elapsed between the first packet and this packet. */ - fdata->frame_ref_num = (fdata != cf->provider.ref) ? cf->provider.ref->num : 0; - nstime_delta(&rel_ts, &fdata->abs_ts, &cf->provider.ref->abs_ts); + /* Get the time elapsed between the first packet and this packet. */ + fdata->frame_ref_num = (fdata != cf->provider.ref) ? cf->provider.ref->num : 0; + nstime_delta(&rel_ts, &fdata->abs_ts, &cf->provider.ref->abs_ts); - /* If it's greater than the current elapsed time, set the elapsed time - to it (we check for "greater than" so as not to be confused by - time moving backwards). */ - if ((gint32)cf->elapsed_time.secs < rel_ts.secs - || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) { - cf->elapsed_time = rel_ts; - } + /* If it's greater than the current elapsed time, set the elapsed time + to it (we check for "greater than" so as not to be confused by + time moving backwards). */ + if ((gint32)cf->elapsed_time.secs < rel_ts.secs + || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) { + cf->elapsed_time = rel_ts; + } - /* If this frame is displayed, get the time elapsed between the - previous displayed packet and this packet. */ - if ( fdata->passed_dfilter ) { - fdata->prev_dis_num = cf->provider.prev_dis->num; - cf->provider.prev_dis = fdata; - } + /* If this frame is displayed, get the time elapsed between the + previous displayed packet and this packet. */ + if ( fdata->passed_dfilter ) { + fdata->prev_dis_num = cf->provider.prev_dis->num; + cf->provider.prev_dis = fdata; + } - /* - * Byte counts - */ - if ( (fdata->passed_dfilter) || (fdata->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 don't pass the display filter */ - if (fdata->ref_time) { - /* if this was a TIME REF frame we should reset the cum_bytes field */ - cf->cum_bytes = fdata->pkt_len; - fdata->cum_bytes = cf->cum_bytes; - } else { - /* increase cum_bytes with this packets length */ - cf->cum_bytes += fdata->pkt_len; + /* + * Byte counts + */ + if ( (fdata->passed_dfilter) || (fdata->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 don't pass the display filter */ + if (fdata->ref_time) { + /* if this was a TIME REF frame we should reset the cum_bytes field */ + cf->cum_bytes = fdata->pkt_len; + fdata->cum_bytes = cf->cum_bytes; + } else { + /* increase cum_bytes with this packets length */ + cf->cum_bytes += fdata->pkt_len; + } } } - } } typedef enum { - PSP_FINISHED, - PSP_STOPPED, - PSP_FAILED + PSP_FINISHED, + PSP_STOPPED, + PSP_FAILED } psp_return_t; static psp_return_t 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 *, - wtap_rec *, Buffer *, void *), - void *callback_args, - gboolean show_progress_bar) + const char *string1, const char *string2, gboolean terminate_is_stop, + gboolean (*callback)(capture_file *, frame_data *, + wtap_rec *, Buffer *, void *), + void *callback_args, + gboolean show_progress_bar) { - guint32 framenum; - frame_data *fdata; - wtap_rec rec; - Buffer buf; - psp_return_t ret = PSP_FINISHED; - - progdlg_t *progbar = NULL; - GTimer *prog_timer = g_timer_new(); - int progbar_count; - float progbar_val; - gchar progbar_status_str[100]; - range_process_e process_this; - - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); - - g_timer_start(prog_timer); - /* Count of packets at which we've looked. */ - progbar_count = 0; - /* Progress so far. */ - progbar_val = 0.0f; - - if (cf->read_lock) { - ws_warning("Failing due to nested process_specified_records(\"%s\") call!", cf->filename); - return PSP_FAILED; - } - cf->read_lock = TRUE; - - cf->stop_flag = FALSE; - - if (range != NULL) - packet_range_process_init(range); + guint32 framenum; + frame_data *fdata; + wtap_rec rec; + Buffer buf; + psp_return_t ret = PSP_FINISHED; + + progdlg_t *progbar = NULL; + GTimer *prog_timer = g_timer_new(); + int progbar_count; + float progbar_val; + gchar progbar_status_str[100]; + range_process_e process_this; - /* Iterate through all the packets, printing the packets that - were selected by the current display filter. */ - for (framenum = 1; framenum <= cf->count; framenum++) { - fdata = frame_data_sequence_find(cf->provider.frames, framenum); - - /* 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 (show_progress_bar && progbar == NULL) - progbar = delayed_create_progress_dlg(cf->window, string1, string2, - terminate_is_stop, - &cf->stop_flag, - progbar_val); + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); - /* - * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL - * has elapsed. Calling update_progress_dlg and packets_bar_update will - * likely trigger UI paint events, which might take a while depending on - * the platform and display. Reset our timer *after* painting. - */ - if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { - /* let's not divide by zero. I should never be started - * with count == 0, so let's assert that - */ - ws_assert(cf->count > 0); - progbar_val = (gfloat) progbar_count / cf->count; + g_timer_start(prog_timer); + /* Count of packets at which we've looked. */ + progbar_count = 0; + /* Progress so far. */ + progbar_val = 0.0f; - snprintf(progbar_status_str, sizeof(progbar_status_str), - "%4u of %u packets", progbar_count, cf->count); - update_progress_dlg(progbar, progbar_val, progbar_status_str); + if (cf->read_lock) { + ws_warning("Failing due to nested process_specified_records(\"%s\") call!", cf->filename); + return PSP_FAILED; + } + cf->read_lock = TRUE; + + cf->stop_flag = FALSE; + + if (range != NULL) + packet_range_process_init(range); + + /* Iterate through all the packets, printing the packets that + were selected by the current display filter. */ + for (framenum = 1; framenum <= cf->count; framenum++) { + fdata = frame_data_sequence_find(cf->provider.frames, framenum); + + /* 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 (show_progress_bar && progbar == NULL) + progbar = delayed_create_progress_dlg(cf->window, string1, string2, + terminate_is_stop, + &cf->stop_flag, + progbar_val); - g_timer_start(prog_timer); + /* + * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL + * has elapsed. Calling update_progress_dlg and packets_bar_update will + * likely trigger UI paint events, which might take a while depending on + * the platform and display. Reset our timer *after* painting. + */ + if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { + /* let's not divide by zero. I should never be started + * with count == 0, so let's assert that + */ + ws_assert(cf->count > 0); + progbar_val = (gfloat) progbar_count / cf->count; + + snprintf(progbar_status_str, sizeof(progbar_status_str), + "%4u of %u packets", progbar_count, cf->count); + update_progress_dlg(progbar, progbar_val, progbar_status_str); + + g_timer_start(prog_timer); + } + + 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. */ + ret = PSP_STOPPED; + break; + } + + progbar_count++; + + if (range != NULL) { + /* do we have to process this packet? */ + process_this = packet_range_process_packet(range, fdata); + if (process_this == range_process_next) { + /* this packet uninteresting, continue with next one */ + continue; + } else if (process_this == range_processing_finished) { + /* all interesting packets processed, stop the loop */ + break; + } + } + + /* Get the packet */ + if (!cf_read_record(cf, fdata, &rec, &buf)) { + /* Attempt to get the packet failed. */ + ret = PSP_FAILED; + break; + } + /* Process the packet */ + if (!callback(cf, fdata, &rec, &buf, callback_args)) { + /* Callback failed. We assume it reported the error appropriately. */ + ret = PSP_FAILED; + break; + } + wtap_rec_reset(&rec); } - 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. */ - ret = PSP_STOPPED; - break; - } - - progbar_count++; - - if (range != NULL) { - /* do we have to process this packet? */ - process_this = packet_range_process_packet(range, fdata); - if (process_this == range_process_next) { - /* this packet uninteresting, continue with next one */ - continue; - } else if (process_this == range_processing_finished) { - /* all interesting packets processed, stop the loop */ - break; - } - } - - /* Get the packet */ - if (!cf_read_record(cf, fdata, &rec, &buf)) { - /* Attempt to get the packet failed. */ - ret = PSP_FAILED; - break; - } - /* Process the packet */ - if (!callback(cf, fdata, &rec, &buf, callback_args)) { - /* Callback failed. We assume it reported the error appropriately. */ - ret = PSP_FAILED; - break; - } - wtap_rec_reset(&rec); - } - - /* We're done printing the packets; destroy the progress bar if - it was created. */ - if (progbar != NULL) - destroy_progress_dlg(progbar); - g_timer_destroy(prog_timer); - - ws_assert(cf->read_lock); - cf->read_lock = FALSE; - - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - - return ret; + /* We're done printing the packets; destroy the progress bar if + it was created. */ + if (progbar != NULL) + destroy_progress_dlg(progbar); + g_timer_destroy(prog_timer); + + ws_assert(cf->read_lock); + cf->read_lock = FALSE; + + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + + return ret; } typedef struct { - epan_dissect_t edt; - column_info *cinfo; + epan_dissect_t edt; + column_info *cinfo; } retap_callback_args_t; static gboolean retap_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, Buffer *buf, - void *argsp) + void *argsp) { - retap_callback_args_t *args = (retap_callback_args_t *)argsp; + retap_callback_args_t *args = (retap_callback_args_t *)argsp; - epan_dissect_run_with_taps(&args->edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, args->cinfo); - epan_dissect_reset(&args->edt); + epan_dissect_run_with_taps(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, args->cinfo); + epan_dissect_reset(&args->edt); - return TRUE; + return TRUE; } cf_read_status_t cf_retap_packets(capture_file *cf) { - packet_range_t range; - retap_callback_args_t callback_args; - gboolean create_proto_tree; - 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); - - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); - - /* If any tap listeners require the columns, construct them. */ - callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; - - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * one of the tap listeners is going to apply a filter; - * - * one of the tap listeners requires a protocol tree. - */ - create_proto_tree = - (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE)); - - /* Reset the tap listeners. */ - reset_tap_listeners(); - - epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE); - - /* Iterate through the list of packets, dissecting all packets and - re-running the taps. */ - packet_range_init(&range, cf); - packet_range_process_init(&range); - - ret = process_specified_records(cf, &range, "Recalculating statistics on", - "all packets", TRUE, retap_packet, - &callback_args, TRUE); - - packet_range_cleanup(&range); - epan_dissect_cleanup(&callback_args.edt); - - cf_callback_invoke(cf_cb_file_retap_finished, cf); - - switch (ret) { - case PSP_FINISHED: - /* Completed successfully. */ - return CF_READ_OK; + packet_range_t range; + retap_callback_args_t callback_args; + gboolean create_proto_tree; + 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); + + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); + + /* If any tap listeners require the columns, construct them. */ + callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; + + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * one of the tap listeners is going to apply a filter; + * + * one of the tap listeners requires a protocol tree. + */ + create_proto_tree = + (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE)); + + /* Reset the tap listeners. */ + reset_tap_listeners(); + + epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE); + + /* Iterate through the list of packets, dissecting all packets and + re-running the taps. */ + packet_range_init(&range, cf); + packet_range_process_init(&range); + + ret = process_specified_records(cf, &range, "Recalculating statistics on", + "all packets", TRUE, retap_packet, + &callback_args, TRUE); + + packet_range_cleanup(&range); + epan_dissect_cleanup(&callback_args.edt); + + cf_callback_invoke(cf_cb_file_retap_finished, cf); + + switch (ret) { + case PSP_FINISHED: + /* Completed successfully. */ + return CF_READ_OK; - case PSP_STOPPED: - /* Well, the user decided to abort the refiltering. - Return CF_READ_ABORTED so our caller knows they did that. */ - return CF_READ_ABORTED; + case PSP_STOPPED: + /* Well, the user decided to abort the refiltering. + Return CF_READ_ABORTED so our caller knows they did that. */ + return CF_READ_ABORTED; - case PSP_FAILED: - /* Error while retapping. */ - return CF_READ_ERROR; - } + case PSP_FAILED: + /* Error while retapping. */ + return CF_READ_ERROR; + } - ws_assert_not_reached(); - return CF_READ_OK; + ws_assert_not_reached(); + return CF_READ_OK; } typedef struct { - print_args_t *print_args; - gboolean print_header_line; - char *header_line_buf; - int header_line_buf_len; - gboolean print_formfeed; - gboolean print_separator; - char *line_buf; - int line_buf_len; - gint *col_widths; - int num_visible_cols; - gint *visible_cols; - epan_dissect_t edt; + print_args_t *print_args; + gboolean print_header_line; + char *header_line_buf; + int header_line_buf_len; + gboolean print_formfeed; + gboolean print_separator; + char *line_buf; + int line_buf_len; + gint *col_widths; + int num_visible_cols; + gint *visible_cols; + epan_dissect_t edt; } print_callback_args_t; static gboolean print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, Buffer *buf, - void *argsp) + void *argsp) { - print_callback_args_t *args = (print_callback_args_t *)argsp; - int i; - char *cp; - int line_len; - int column_len; - 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, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, &cf->cinfo); - epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); - } else - epan_dissect_run(&args->edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, NULL); - - if (args->print_formfeed) { - if (!new_page(args->print_args->stream)) - goto fail; + print_callback_args_t *args = (print_callback_args_t *)argsp; + int i; + char *cp; + int line_len; + int column_len; + 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, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, &cf->cinfo); + epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); + } else + epan_dissect_run(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, NULL); - /* - * Print another header line if we print a packet summary on the - * new page. - */ - if (args->print_args->print_col_headings) - args->print_header_line = TRUE; - } else { - if (args->print_separator) { - if (!print_line(args->print_args->stream, 0, "")) - goto fail; - } - } - - /* - * We generate bookmarks, if the output format supports them. - * The name is "__frameN__". - */ - snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num); - - if (args->print_args->print_summary) { - if (!args->print_args->print_col_headings) - args->print_header_line = FALSE; - if (args->print_header_line) { - if (!print_line(args->print_args->stream, 0, args->header_line_buf)) - goto fail; - args->print_header_line = FALSE; /* we might not need to print any more */ - } - 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(col_item->col_data); - if (args->col_widths[i] > column_len) - column_len = args->col_widths[i]; - - /* Make sure there's room in the line buffer for the column; if not, - double its length. */ - line_len += column_len + 1; /* "+1" for space */ - if (line_len > args->line_buf_len) { - cp_off = (int) (cp - args->line_buf); - args->line_buf_len = 2 * line_len; - args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1); - cp = args->line_buf + cp_off; - } - - /* Right-justify the packet number column. */ - if (col_item->col_fmt == COL_NUMBER) - snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data); - else - 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++ = ' '; - } - *cp = '\0'; + if (args->print_formfeed) { + if (!new_page(args->print_args->stream)) + goto fail; - /* - * Generate a bookmark, using the summary line as the title. - */ - if (!print_bookmark(args->print_args->stream, bookmark_name, - args->line_buf)) - goto fail; + /* + * Print another header line if we print a packet summary on the + * new page. + */ + if (args->print_args->print_col_headings) + args->print_header_line = TRUE; + } else { + if (args->print_separator) { + if (!print_line(args->print_args->stream, 0, "")) + goto fail; + } + } - if (!print_line(args->print_args->stream, 0, args->line_buf)) - goto fail; - } else { /* - * Generate a bookmark, using "Frame N" as the title, as we're not - * printing the summary line. + * We generate bookmarks, if the output format supports them. + * The name is "__frameN__". */ - snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num); - if (!print_bookmark(args->print_args->stream, bookmark_name, - bookmark_title)) - goto fail; - } /* if (print_summary) */ + snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num); - if (args->print_args->print_dissections != print_dissections_none) { if (args->print_args->print_summary) { - /* Separate the summary line from the tree with a blank line. */ - if (!print_line(args->print_args->stream, 0, "")) - goto fail; + if (!args->print_args->print_col_headings) + args->print_header_line = FALSE; + if (args->print_header_line) { + if (!print_line(args->print_args->stream, 0, args->header_line_buf)) + goto fail; + args->print_header_line = FALSE; /* we might not need to print any more */ + } + 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(col_item->col_data); + if (args->col_widths[i] > column_len) + column_len = args->col_widths[i]; + + /* Make sure there's room in the line buffer for the column; if not, + double its length. */ + line_len += column_len + 1; /* "+1" for space */ + if (line_len > args->line_buf_len) { + cp_off = (int) (cp - args->line_buf); + args->line_buf_len = 2 * line_len; + args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1); + cp = args->line_buf + cp_off; + } + + /* Right-justify the packet number column. */ + if (col_item->col_fmt == COL_NUMBER) + snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data); + else + 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++ = ' '; + } + *cp = '\0'; + + /* + * Generate a bookmark, using the summary line as the title. + */ + if (!print_bookmark(args->print_args->stream, bookmark_name, + args->line_buf)) + goto fail; + + if (!print_line(args->print_args->stream, 0, args->line_buf)) + goto fail; + } else { + /* + * Generate a bookmark, using "Frame N" as the title, as we're not + * printing the summary line. + */ + snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num); + if (!print_bookmark(args->print_args->stream, bookmark_name, + bookmark_title)) + goto fail; + } /* if (print_summary) */ + + if (args->print_args->print_dissections != print_dissections_none) { + if (args->print_args->print_summary) { + /* Separate the summary line from the tree with a blank line. */ + if (!print_line(args->print_args->stream, 0, "")) + goto fail; + } + + /* Print the information in that tree. */ + if (!proto_tree_print(args->print_args->print_dissections, + args->print_args->print_hex, &args->edt, NULL, + args->print_args->stream)) + goto fail; + + /* Print a blank line if we print anything after this (aka more than one packet). */ + args->print_separator = TRUE; + + /* Print a header line if we print any more packet summaries */ + if (args->print_args->print_col_headings) + args->print_header_line = TRUE; + } + + if (args->print_args->print_hex) { + if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) { + if (!print_line(args->print_args->stream, 0, "")) + goto fail; + } + /* Print the full packet data as hex. */ + if (!print_hex_data(args->print_args->stream, &args->edt, args->print_args->hexdump_options)) + goto fail; + + /* Print a blank line if we print anything after this (aka more than one packet). */ + args->print_separator = TRUE; + + /* Print a header line if we print any more packet summaries */ + if (args->print_args->print_col_headings) + args->print_header_line = TRUE; + } /* if (args->print_args->print_dissections != print_dissections_none) */ + + epan_dissect_reset(&args->edt); + + /* do we want to have a formfeed between each packet from now on? */ + if (args->print_args->print_formfeed) { + args->print_formfeed = TRUE; + } + + return TRUE; + +fail: + epan_dissect_reset(&args->edt); + return FALSE; +} + +cf_print_status_t +cf_print_packets(capture_file *cf, print_args_t *print_args, + gboolean show_progress_bar) +{ + print_callback_args_t callback_args; + gint data_width; + char *cp; + int i, cp_off, column_len, line_len; + int num_visible_col = 0, last_visible_col = 0, visible_col_count; + psp_return_t ret; + GList *clp; + fmt_data *cfmt; + gboolean proto_tree_needed; + + callback_args.print_args = print_args; + callback_args.print_header_line = print_args->print_col_headings; + callback_args.header_line_buf = NULL; + callback_args.header_line_buf_len = 256; + callback_args.print_formfeed = FALSE; + callback_args.print_separator = FALSE; + callback_args.line_buf = NULL; + callback_args.line_buf_len = 256; + callback_args.col_widths = NULL; + callback_args.num_visible_cols = 0; + callback_args.visible_cols = NULL; + + if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) { + destroy_print_stream(print_args->stream); + return CF_PRINT_WRITE_ERROR; } - /* Print the information in that tree. */ - if (!proto_tree_print(args->print_args->print_dissections, - args->print_args->print_hex, &args->edt, NULL, - args->print_args->stream)) - goto fail; + if (print_args->print_summary) { + /* We're printing packet summaries. Allocate the header line buffer + and get the column widths. */ + callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1); - /* Print a blank line if we print anything after this (aka more than one packet). */ - args->print_separator = TRUE; + /* Find the number of visible columns and the last visible column */ + for (i = 0; i < prefs.num_cols; i++) { - /* Print a header line if we print any more packet summaries */ - if (args->print_args->print_col_headings) - args->print_header_line = TRUE; - } + clp = g_list_nth(prefs.col_list, i); + if (clp == NULL) /* Sanity check, Invalid column requested */ + continue; - if (args->print_args->print_hex) { - if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) { - if (!print_line(args->print_args->stream, 0, "")) - goto fail; - } - /* Print the full packet data as hex. */ - if (!print_hex_data(args->print_args->stream, &args->edt, args->print_args->hexdump_options)) - goto fail; + cfmt = (fmt_data *) clp->data; + if (cfmt->visible) { + num_visible_col++; + last_visible_col = i; + } + } - /* Print a blank line if we print anything after this (aka more than one packet). */ - args->print_separator = TRUE; + /* if num_visible_col is 0, we are done */ + if (num_visible_col == 0) { + g_free(callback_args.header_line_buf); + return CF_PRINT_OK; + } - /* Print a header line if we print any more packet summaries */ - if (args->print_args->print_col_headings) - args->print_header_line = TRUE; - } /* if (args->print_args->print_dissections != print_dissections_none) */ + /* Find the widths for each of the columns - maximum of the + width of the title and the width of the data - and construct + a buffer with a line containing the column titles. */ + callback_args.num_visible_cols = num_visible_col; + callback_args.col_widths = g_new(gint, num_visible_col); + callback_args.visible_cols = g_new(gint, num_visible_col); + cp = &callback_args.header_line_buf[0]; + line_len = 0; + visible_col_count = 0; + for (i = 0; i < cf->cinfo.num_cols; i++) { + + clp = g_list_nth(prefs.col_list, i); + if (clp == NULL) /* Sanity check, Invalid column requested */ + continue; + + cfmt = (fmt_data *) clp->data; + if (cfmt->visible == FALSE) + continue; + + /* Save the order of visible columns */ + callback_args.visible_cols[visible_col_count] = i; + + /* Don't pad the last column. */ + 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.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; + } - epan_dissect_reset(&args->edt); + /* Find the length of the string for this column. */ + column_len = (int) strlen(cf->cinfo.columns[i].col_title); + if (callback_args.col_widths[visible_col_count] > column_len) + column_len = callback_args.col_widths[visible_col_count]; + + /* Make sure there's room in the line buffer for the column; if not, + double its length. */ + line_len += column_len + 1; /* "+1" for space */ + if (line_len > callback_args.header_line_buf_len) { + cp_off = (int) (cp - callback_args.header_line_buf); + callback_args.header_line_buf_len = 2 * line_len; + callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf, + callback_args.header_line_buf_len + 1); + cp = callback_args.header_line_buf + cp_off; + } - /* do we want to have a formfeed between each packet from now on? */ - if (args->print_args->print_formfeed) { - args->print_formfeed = TRUE; - } + /* Right-justify the packet number column. */ +/* if (cf->cinfo.col_fmt[i] == COL_NUMBER) + snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title); + else*/ + 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++ = ' '; - return TRUE; + visible_col_count++; + } + *cp = '\0'; + + /* Now start out the main line buffer with the same length as the + header line buffer. */ + callback_args.line_buf_len = callback_args.header_line_buf_len; + callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1); + } /* if (print_summary) */ + + /* Create the protocol tree, and make it visible, if we're printing + the dissection or the hex data. + XXX - do we need it if we're just printing the hex data? */ + proto_tree_needed = + callback_args.print_args->print_dissections != print_dissections_none || + callback_args.print_args->print_hex || + have_custom_cols(&cf->cinfo) || have_field_extractors(); + epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed); + + /* Iterate through the list of packets, printing the packets we were + told to print. */ + ret = process_specified_records(cf, &print_args->range, "Printing", + "selected packets", TRUE, print_packet, + &callback_args, show_progress_bar); + epan_dissect_cleanup(&callback_args.edt); + g_free(callback_args.header_line_buf); + g_free(callback_args.line_buf); + g_free(callback_args.col_widths); + g_free(callback_args.visible_cols); + + switch (ret) { + + case PSP_FINISHED: + /* Completed successfully. */ + break; -fail: - epan_dissect_reset(&args->edt); - return FALSE; -} + case PSP_STOPPED: + /* Well, the user decided to abort the printing. -cf_print_status_t -cf_print_packets(capture_file *cf, print_args_t *print_args, - gboolean show_progress_bar) -{ - print_callback_args_t callback_args; - gint data_width; - char *cp; - int i, cp_off, column_len, line_len; - int num_visible_col = 0, last_visible_col = 0, visible_col_count; - psp_return_t ret; - GList *clp; - fmt_data *cfmt; - gboolean proto_tree_needed; - - callback_args.print_args = print_args; - callback_args.print_header_line = print_args->print_col_headings; - callback_args.header_line_buf = NULL; - callback_args.header_line_buf_len = 256; - callback_args.print_formfeed = FALSE; - callback_args.print_separator = FALSE; - callback_args.line_buf = NULL; - callback_args.line_buf_len = 256; - callback_args.col_widths = NULL; - callback_args.num_visible_cols = 0; - callback_args.visible_cols = NULL; - - if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) { - destroy_print_stream(print_args->stream); - return CF_PRINT_WRITE_ERROR; - } - - if (print_args->print_summary) { - /* We're printing packet summaries. Allocate the header line buffer - and get the column widths. */ - callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1); - - /* Find the number of visible columns and the last visible column */ - for (i = 0; i < prefs.num_cols; i++) { - - clp = g_list_nth(prefs.col_list, i); - if (clp == NULL) /* Sanity check, Invalid column requested */ - continue; - - cfmt = (fmt_data *) clp->data; - if (cfmt->visible) { - num_visible_col++; - last_visible_col = i; - } + XXX - note that what got generated before they did that + will get printed if we're piping to a print program; we'd + have to write to a file and then hand that to the print + program to make it actually not print anything. */ + break; + + case PSP_FAILED: + /* Error while printing. + + XXX - note that what got generated before they did that + will get printed if we're piping to a print program; we'd + have to write to a file and then hand that to the print + program to make it actually not print anything. */ + destroy_print_stream(print_args->stream); + return CF_PRINT_WRITE_ERROR; } - /* if num_visible_col is 0, we are done */ - if (num_visible_col == 0) { - g_free(callback_args.header_line_buf); - return CF_PRINT_OK; + if (!print_finale(print_args->stream)) { + destroy_print_stream(print_args->stream); + return CF_PRINT_WRITE_ERROR; } - /* Find the widths for each of the columns - maximum of the - width of the title and the width of the data - and construct - a buffer with a line containing the column titles. */ - callback_args.num_visible_cols = num_visible_col; - callback_args.col_widths = g_new(gint, num_visible_col); - callback_args.visible_cols = g_new(gint, num_visible_col); - cp = &callback_args.header_line_buf[0]; - line_len = 0; - visible_col_count = 0; - for (i = 0; i < cf->cinfo.num_cols; i++) { + if (!destroy_print_stream(print_args->stream)) + return CF_PRINT_WRITE_ERROR; - clp = g_list_nth(prefs.col_list, i); - if (clp == NULL) /* Sanity check, Invalid column requested */ - continue; - - cfmt = (fmt_data *) clp->data; - if (cfmt->visible == FALSE) - continue; - - /* Save the order of visible columns */ - callback_args.visible_cols[visible_col_count] = i; - - /* Don't pad the last column. */ - 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.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.columns[i].col_title); - if (callback_args.col_widths[visible_col_count] > column_len) - column_len = callback_args.col_widths[visible_col_count]; - - /* Make sure there's room in the line buffer for the column; if not, - double its length. */ - line_len += column_len + 1; /* "+1" for space */ - if (line_len > callback_args.header_line_buf_len) { - cp_off = (int) (cp - callback_args.header_line_buf); - callback_args.header_line_buf_len = 2 * line_len; - callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf, - callback_args.header_line_buf_len + 1); - cp = callback_args.header_line_buf + cp_off; - } - - /* Right-justify the packet number column. */ -/* if (cf->cinfo.col_fmt[i] == COL_NUMBER) - snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title); - else*/ - 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++ = ' '; - - visible_col_count++; - } - *cp = '\0'; - - /* Now start out the main line buffer with the same length as the - header line buffer. */ - callback_args.line_buf_len = callback_args.header_line_buf_len; - callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1); - } /* if (print_summary) */ - - /* Create the protocol tree, and make it visible, if we're printing - the dissection or the hex data. - XXX - do we need it if we're just printing the hex data? */ - proto_tree_needed = - callback_args.print_args->print_dissections != print_dissections_none || - callback_args.print_args->print_hex || - have_custom_cols(&cf->cinfo) || have_field_extractors(); - epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed); - - /* Iterate through the list of packets, printing the packets we were - told to print. */ - ret = process_specified_records(cf, &print_args->range, "Printing", - "selected packets", TRUE, print_packet, - &callback_args, show_progress_bar); - epan_dissect_cleanup(&callback_args.edt); - g_free(callback_args.header_line_buf); - g_free(callback_args.line_buf); - g_free(callback_args.col_widths); - g_free(callback_args.visible_cols); - - switch (ret) { - - case PSP_FINISHED: - /* Completed successfully. */ - break; - - case PSP_STOPPED: - /* Well, the user decided to abort the printing. - - XXX - note that what got generated before they did that - will get printed if we're piping to a print program; we'd - have to write to a file and then hand that to the print - program to make it actually not print anything. */ - break; - - case PSP_FAILED: - /* Error while printing. - - XXX - note that what got generated before they did that - will get printed if we're piping to a print program; we'd - have to write to a file and then hand that to the print - program to make it actually not print anything. */ - destroy_print_stream(print_args->stream); - return CF_PRINT_WRITE_ERROR; - } - - if (!print_finale(print_args->stream)) { - destroy_print_stream(print_args->stream); - return CF_PRINT_WRITE_ERROR; - } - - if (!destroy_print_stream(print_args->stream)) - return CF_PRINT_WRITE_ERROR; - - return CF_PRINT_OK; + return CF_PRINT_OK; } typedef struct { - FILE *fh; - epan_dissect_t edt; - print_args_t *print_args; - json_dumper jdumper; + FILE *fh; + epan_dissect_t edt; + print_args_t *print_args; + json_dumper jdumper; } write_packet_callback_args_t; static gboolean write_pdml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, - Buffer *buf, void *argsp) + Buffer *buf, void *argsp) { - write_packet_callback_args_t *args = (write_packet_callback_args_t *)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, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, NULL); + /* Create the protocol tree, but don't fill in the column information. */ + epan_dissect_run(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, NULL); - /* Write out the information in that tree. */ - write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, &cf->cinfo, args->fh, FALSE); + /* Write out the information in that tree. */ + write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, &cf->cinfo, args->fh, FALSE); - epan_dissect_reset(&args->edt); + epan_dissect_reset(&args->edt); - return !ferror(args->fh); + return !ferror(args->fh); } cf_print_status_t cf_write_pdml_packets(capture_file *cf, print_args_t *print_args) { - write_packet_callback_args_t callback_args; - FILE *fh; - psp_return_t ret; - - fh = ws_fopen(print_args->file, "w"); - if (fh == NULL) - return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ + write_packet_callback_args_t callback_args; + FILE *fh; + psp_return_t ret; + + fh = ws_fopen(print_args->file, "w"); + if (fh == NULL) + return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ + + write_pdml_preamble(fh, cf->filename); + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } - write_pdml_preamble(fh, cf->filename); - if (ferror(fh)) { - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } + callback_args.fh = fh; + callback_args.print_args = print_args; + epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE); - callback_args.fh = fh; - callback_args.print_args = print_args; - epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE); + /* Iterate through the list of packets, printing the packets we were + told to print. */ + ret = process_specified_records(cf, &print_args->range, "Writing PDML", + "selected packets", TRUE, + write_pdml_packet, &callback_args, TRUE); - /* Iterate through the list of packets, printing the packets we were - told to print. */ - ret = process_specified_records(cf, &print_args->range, "Writing PDML", - "selected packets", TRUE, - write_pdml_packet, &callback_args, TRUE); + epan_dissect_cleanup(&callback_args.edt); - epan_dissect_cleanup(&callback_args.edt); + switch (ret) { - switch (ret) { + case PSP_FINISHED: + /* Completed successfully. */ + break; - case PSP_FINISHED: - /* Completed successfully. */ - break; + case PSP_STOPPED: + /* Well, the user decided to abort the printing. */ + break; - case PSP_STOPPED: - /* Well, the user decided to abort the printing. */ - break; + case PSP_FAILED: + /* Error while printing. */ + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } - case PSP_FAILED: - /* Error while printing. */ - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } + write_pdml_finale(fh); + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } - write_pdml_finale(fh); - if (ferror(fh)) { + /* XXX - check for an error */ fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - /* XXX - check for an error */ - fclose(fh); - - return CF_PRINT_OK; + return CF_PRINT_OK; } static gboolean write_psml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, - Buffer *buf, void *argsp) + Buffer *buf, void *argsp) { - write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; + 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, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, &cf->cinfo); - epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); + /* Fill in the column information */ + col_custom_prime_edt(&args->edt, &cf->cinfo); + epan_dissect_run(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, &cf->cinfo); + epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); - /* Write out the column information. */ - write_psml_columns(&args->edt, args->fh, FALSE); + /* Write out the column information. */ + write_psml_columns(&args->edt, args->fh, FALSE); - epan_dissect_reset(&args->edt); + epan_dissect_reset(&args->edt); - return !ferror(args->fh); + return !ferror(args->fh); } cf_print_status_t cf_write_psml_packets(capture_file *cf, print_args_t *print_args) { - write_packet_callback_args_t callback_args; - FILE *fh; - psp_return_t ret; + write_packet_callback_args_t callback_args; + FILE *fh; + psp_return_t ret; - gboolean proto_tree_needed; + gboolean proto_tree_needed; - fh = ws_fopen(print_args->file, "w"); - if (fh == NULL) - return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ + fh = ws_fopen(print_args->file, "w"); + if (fh == NULL) + return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ - write_psml_preamble(&cf->cinfo, fh); - if (ferror(fh)) { - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } + write_psml_preamble(&cf->cinfo, fh); + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } - callback_args.fh = fh; - callback_args.print_args = print_args; + callback_args.fh = fh; + callback_args.print_args = print_args; - /* Fill in the column information, only create the protocol tree - if having custom columns or field extractors. */ - proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors(); - epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed); + /* Fill in the column information, only create the protocol tree + if having custom columns or field extractors. */ + proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors(); + epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed); - /* Iterate through the list of packets, printing the packets we were - told to print. */ - ret = process_specified_records(cf, &print_args->range, "Writing PSML", - "selected packets", TRUE, - write_psml_packet, &callback_args, TRUE); + /* Iterate through the list of packets, printing the packets we were + told to print. */ + ret = process_specified_records(cf, &print_args->range, "Writing PSML", + "selected packets", TRUE, + write_psml_packet, &callback_args, TRUE); - epan_dissect_cleanup(&callback_args.edt); + epan_dissect_cleanup(&callback_args.edt); - switch (ret) { + switch (ret) { - case PSP_FINISHED: - /* Completed successfully. */ - break; + case PSP_FINISHED: + /* Completed successfully. */ + break; - case PSP_STOPPED: - /* Well, the user decided to abort the printing. */ - break; + case PSP_STOPPED: + /* Well, the user decided to abort the printing. */ + break; - case PSP_FAILED: - /* Error while printing. */ - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } + case PSP_FAILED: + /* Error while printing. */ + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } - write_psml_finale(fh); - if (ferror(fh)) { - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } + write_psml_finale(fh); + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } - /* XXX - check for an error */ - fclose(fh); + /* XXX - check for an error */ + fclose(fh); - return CF_PRINT_OK; + return CF_PRINT_OK; } static gboolean write_csv_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, - Buffer *buf, void *argsp) + Buffer *buf, void *argsp) { - write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; + 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, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, &cf->cinfo); - epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); + /* Fill in the column information */ + col_custom_prime_edt(&args->edt, &cf->cinfo); + epan_dissect_run(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, &cf->cinfo); + epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); - /* Write out the column information. */ - write_csv_columns(&args->edt, args->fh); + /* Write out the column information. */ + write_csv_columns(&args->edt, args->fh); - epan_dissect_reset(&args->edt); + epan_dissect_reset(&args->edt); - return !ferror(args->fh); + return !ferror(args->fh); } cf_print_status_t cf_write_csv_packets(capture_file *cf, print_args_t *print_args) { - write_packet_callback_args_t callback_args; - gboolean proto_tree_needed; - FILE *fh; - psp_return_t ret; - - fh = ws_fopen(print_args->file, "w"); - if (fh == NULL) - return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ + write_packet_callback_args_t callback_args; + gboolean proto_tree_needed; + FILE *fh; + psp_return_t ret; + + fh = ws_fopen(print_args->file, "w"); + if (fh == NULL) + return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ + + write_csv_column_titles(&cf->cinfo, fh); + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } - write_csv_column_titles(&cf->cinfo, fh); - if (ferror(fh)) { - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } + callback_args.fh = fh; + callback_args.print_args = print_args; - callback_args.fh = fh; - callback_args.print_args = print_args; + /* only create the protocol tree if having custom columns or field extractors. */ + proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors(); + epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed); - /* only create the protocol tree if having custom columns or field extractors. */ - proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors(); - epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed); + /* Iterate through the list of packets, printing the packets we were + told to print. */ + ret = process_specified_records(cf, &print_args->range, "Writing CSV", + "selected packets", TRUE, + write_csv_packet, &callback_args, TRUE); - /* Iterate through the list of packets, printing the packets we were - told to print. */ - ret = process_specified_records(cf, &print_args->range, "Writing CSV", - "selected packets", TRUE, - write_csv_packet, &callback_args, TRUE); + epan_dissect_cleanup(&callback_args.edt); - epan_dissect_cleanup(&callback_args.edt); + switch (ret) { - switch (ret) { + case PSP_FINISHED: + /* Completed successfully. */ + break; - case PSP_FINISHED: - /* Completed successfully. */ - break; + case PSP_STOPPED: + /* Well, the user decided to abort the printing. */ + break; - case PSP_STOPPED: - /* Well, the user decided to abort the printing. */ - break; + case PSP_FAILED: + /* Error while printing. */ + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } - case PSP_FAILED: - /* Error while printing. */ + /* XXX - check for an error */ fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - /* XXX - check for an error */ - fclose(fh); - - return CF_PRINT_OK; + return CF_PRINT_OK; } static gboolean carrays_write_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, - Buffer *buf, void *argsp) + Buffer *buf, void *argsp) { - write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; + write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; - epan_dissect_run(&args->edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, NULL); - write_carrays_hex_data(fdata->num, args->fh, &args->edt); - epan_dissect_reset(&args->edt); + epan_dissect_run(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, NULL); + write_carrays_hex_data(fdata->num, args->fh, &args->edt); + epan_dissect_reset(&args->edt); - return !ferror(args->fh); + return !ferror(args->fh); } cf_print_status_t cf_write_carrays_packets(capture_file *cf, print_args_t *print_args) { - write_packet_callback_args_t callback_args; - FILE *fh; - psp_return_t ret; + write_packet_callback_args_t callback_args; + FILE *fh; + psp_return_t ret; - fh = ws_fopen(print_args->file, "w"); + fh = ws_fopen(print_args->file, "w"); - if (fh == NULL) - return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ + if (fh == NULL) + return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ - if (ferror(fh)) { - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - - callback_args.fh = fh; - callback_args.print_args = print_args; - epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE); - - /* Iterate through the list of packets, printing the packets we were - told to print. */ - ret = process_specified_records(cf, &print_args->range, - "Writing C Arrays", - "selected packets", TRUE, - carrays_write_packet, &callback_args, TRUE); - - epan_dissect_cleanup(&callback_args.edt); - - switch (ret) { - case PSP_FINISHED: - /* Completed successfully. */ - break; - case PSP_STOPPED: - /* Well, the user decided to abort the printing. */ - break; - case PSP_FAILED: - /* Error while printing. */ - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } + + callback_args.fh = fh; + callback_args.print_args = print_args; + epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE); - fclose(fh); - return CF_PRINT_OK; + /* Iterate through the list of packets, printing the packets we were + told to print. */ + ret = process_specified_records(cf, &print_args->range, + "Writing C Arrays", + "selected packets", TRUE, + carrays_write_packet, &callback_args, TRUE); + + epan_dissect_cleanup(&callback_args.edt); + + switch (ret) { + case PSP_FINISHED: + /* Completed successfully. */ + break; + case PSP_STOPPED: + /* Well, the user decided to abort the printing. */ + break; + case PSP_FAILED: + /* Error while printing. */ + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } + + fclose(fh); + return CF_PRINT_OK; } static gboolean write_json_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, - Buffer *buf, void *argsp) + Buffer *buf, void *argsp) { - write_packet_callback_args_t *args = (write_packet_callback_args_t *)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, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, NULL); + /* Create the protocol tree, but don't fill in the column information. */ + epan_dissect_run(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, NULL); - /* Write out the information in that tree. */ - write_json_proto_tree(NULL, args->print_args->print_dissections, - args->print_args->print_hex, NULL, PF_NONE, - &args->edt, &cf->cinfo, proto_node_group_children_by_unique, - &args->jdumper); + /* Write out the information in that tree. */ + write_json_proto_tree(NULL, args->print_args->print_dissections, + args->print_args->print_hex, NULL, PF_NONE, + &args->edt, &cf->cinfo, proto_node_group_children_by_unique, + &args->jdumper); - epan_dissect_reset(&args->edt); + epan_dissect_reset(&args->edt); - return !ferror(args->fh); + return !ferror(args->fh); } cf_print_status_t cf_write_json_packets(capture_file *cf, print_args_t *print_args) { - write_packet_callback_args_t callback_args; - FILE *fh; - psp_return_t ret; - - fh = ws_fopen(print_args->file, "w"); - if (fh == NULL) - return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ + write_packet_callback_args_t callback_args; + FILE *fh; + psp_return_t ret; + + fh = ws_fopen(print_args->file, "w"); + if (fh == NULL) + return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ + + callback_args.jdumper = write_json_preamble(fh); + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } - callback_args.jdumper = write_json_preamble(fh); - if (ferror(fh)) { - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } + callback_args.fh = fh; + callback_args.print_args = print_args; + epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE); - callback_args.fh = fh; - callback_args.print_args = print_args; - epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE); + /* Iterate through the list of packets, printing the packets we were + told to print. */ + ret = process_specified_records(cf, &print_args->range, "Writing JSON", + "selected packets", TRUE, + write_json_packet, &callback_args, TRUE); - /* Iterate through the list of packets, printing the packets we were - told to print. */ - ret = process_specified_records(cf, &print_args->range, "Writing JSON", - "selected packets", TRUE, - write_json_packet, &callback_args, TRUE); + epan_dissect_cleanup(&callback_args.edt); - epan_dissect_cleanup(&callback_args.edt); + switch (ret) { - switch (ret) { + case PSP_FINISHED: + /* Completed successfully. */ + break; - case PSP_FINISHED: - /* Completed successfully. */ - break; + case PSP_STOPPED: + /* Well, the user decided to abort the printing. */ + break; - case PSP_STOPPED: - /* Well, the user decided to abort the printing. */ - break; + case PSP_FAILED: + /* Error while printing. */ + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } - case PSP_FAILED: - /* Error while printing. */ - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } + write_json_finale(&callback_args.jdumper); + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } - write_json_finale(&callback_args.jdumper); - if (ferror(fh)) { + /* XXX - check for an error */ fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - /* XXX - check for an error */ - fclose(fh); - - return CF_PRINT_OK; + return CF_PRINT_OK; } gboolean cf_find_packet_protocol_tree(capture_file *cf, const char *string, - search_direction dir) + search_direction dir) { - match_data mdata; + match_data mdata; - mdata.string = string; - mdata.string_len = strlen(string); - return find_packet(cf, match_protocol_tree, &mdata, dir); + mdata.string = string; + mdata.string_len = strlen(string); + return find_packet(cf, match_protocol_tree, &mdata, dir); } gboolean cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata) { - mdata->frame_matched = FALSE; - mdata->string = convert_string_case(cf->sfilter, cf->case_type); - mdata->string_len = strlen(mdata->string); - mdata->cf = cf; - /* Iterate through all the nodes looking for matching text */ - proto_tree_children_foreach(tree, match_subtree_text, mdata); - return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED; + mdata->frame_matched = FALSE; + mdata->string = convert_string_case(cf->sfilter, cf->case_type); + mdata->string_len = strlen(mdata->string); + mdata->cf = cf; + /* Iterate through all the nodes looking for matching text */ + proto_tree_children_foreach(tree, match_subtree_text, mdata); + return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED; } static match_result match_protocol_tree(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - match_data *mdata = (match_data *)criterion; - epan_dissect_t edt; - - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - /* 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->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, NULL); - - /* Iterate through all the nodes, seeing if they have text that matches. */ - mdata->cf = cf; - mdata->frame_matched = FALSE; - proto_tree_children_foreach(edt.tree, match_subtree_text, mdata); - epan_dissect_cleanup(&edt); - return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED; + match_data *mdata = (match_data *)criterion; + epan_dissect_t edt; + + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + /* 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->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, NULL); + + /* Iterate through all the nodes, seeing if they have text that matches. */ + mdata->cf = cf; + mdata->frame_matched = FALSE; + proto_tree_children_foreach(edt.tree, match_subtree_text, mdata); + epan_dissect_cleanup(&edt); + return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED; } static void match_subtree_text(proto_node *node, gpointer data) { - match_data *mdata = (match_data *) data; - const gchar *string = mdata->string; - size_t string_len = mdata->string_len; - capture_file *cf = mdata->cf; - field_info *fi = PNODE_FINFO(node); - gchar label_str[ITEM_LABEL_LENGTH]; - gchar *label_ptr; - size_t label_len; - guint32 i; - guint8 c_char; - size_t c_match = 0; - - /* dissection with an invisible proto tree? */ - ws_assert(fi); - - if (mdata->frame_matched) { - /* We already had a match; don't bother doing any more work. */ - return; - } - - /* Don't match invisible entries. */ - if (proto_item_is_hidden(node)) - return; - - /* was a free format label produced? */ - if (fi->rep) { - label_ptr = fi->rep->representation; - } else { - /* no, make a generic label */ - label_ptr = label_str; - proto_item_fill_label(fi, label_str); - } - - if (cf->regex) { - if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) { - mdata->frame_matched = TRUE; - mdata->finfo = fi; - return; - } - } else { - /* Does that label match? */ - label_len = strlen(label_ptr); - for (i = 0; i < label_len; i++) { - c_char = label_ptr[i]; - if (cf->case_type) - c_char = g_ascii_toupper(c_char); - if (c_char == string[c_match]) { - c_match++; - if (c_match == string_len) { - /* No need to look further; we have a match */ - mdata->frame_matched = TRUE; - mdata->finfo = fi; - return; + match_data *mdata = (match_data *) data; + const gchar *string = mdata->string; + size_t string_len = mdata->string_len; + capture_file *cf = mdata->cf; + field_info *fi = PNODE_FINFO(node); + gchar label_str[ITEM_LABEL_LENGTH]; + gchar *label_ptr; + size_t label_len; + guint32 i; + guint8 c_char; + size_t c_match = 0; + + /* dissection with an invisible proto tree? */ + ws_assert(fi); + + if (mdata->frame_matched) { + /* We already had a match; don't bother doing any more work. */ + return; + } + + /* Don't match invisible entries. */ + if (proto_item_is_hidden(node)) + return; + + /* was a free format label produced? */ + if (fi->rep) { + label_ptr = fi->rep->representation; + } else { + /* no, make a generic label */ + label_ptr = label_str; + proto_item_fill_label(fi, label_str); + } + + if (cf->regex) { + if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) { + mdata->frame_matched = TRUE; + mdata->finfo = fi; + return; + } + } else { + /* Does that label match? */ + label_len = strlen(label_ptr); + for (i = 0; i < label_len; i++) { + c_char = label_ptr[i]; + if (cf->case_type) + c_char = g_ascii_toupper(c_char); + if (c_char == string[c_match]) { + c_match++; + if (c_match == string_len) { + /* No need to look further; we have a match */ + mdata->frame_matched = TRUE; + mdata->finfo = fi; + return; + } + } else + c_match = 0; } - } else - c_match = 0; } - } - /* Recurse into the subtree, if it exists */ - if (node->first_child != NULL) - proto_tree_children_foreach(node, match_subtree_text, mdata); + /* Recurse into the subtree, if it exists */ + if (node->first_child != NULL) + proto_tree_children_foreach(node, match_subtree_text, mdata); } gboolean cf_find_packet_summary_line(capture_file *cf, const char *string, - search_direction dir) + search_direction dir) { - match_data mdata; + match_data mdata; - mdata.string = string; - mdata.string_len = strlen(string); - return find_packet(cf, match_summary_line, &mdata, dir); + mdata.string = string; + mdata.string_len = strlen(string); + return find_packet(cf, match_summary_line, &mdata, dir); } static match_result match_summary_line(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - match_data *mdata = (match_data *)criterion; - const gchar *string = mdata->string; - size_t string_len = mdata->string_len; - epan_dissect_t edt; - const char *info_column; - size_t info_column_len; - match_result result = MR_NOTMATCHED; - gint colx; - guint32 i; - guint8 c_char; - size_t c_match = 0; - - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - /* Don't bother constructing the protocol tree */ - epan_dissect_init(&edt, cf->epan, FALSE, FALSE); - /* Get the column information */ - epan_dissect_run(&edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, &cf->cinfo); - - /* Find the Info column */ - for (colx = 0; colx < cf->cinfo.num_cols; colx++) { - if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) { - /* Found it. See if we match. */ - info_column = edt.pi.cinfo->columns[colx].col_data; - info_column_len = strlen(info_column); - if (cf->regex) { - if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) { - result = MR_MATCHED; - break; - } - } else { - for (i = 0; i < info_column_len; i++) { - c_char = info_column[i]; - if (cf->case_type) - c_char = g_ascii_toupper(c_char); - if (c_char == string[c_match]) { - c_match++; - if (c_match == string_len) { - result = MR_MATCHED; - break; + match_data *mdata = (match_data *)criterion; + const gchar *string = mdata->string; + size_t string_len = mdata->string_len; + epan_dissect_t edt; + const char *info_column; + size_t info_column_len; + match_result result = MR_NOTMATCHED; + gint colx; + guint32 i; + guint8 c_char; + size_t c_match = 0; + + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + /* Don't bother constructing the protocol tree */ + epan_dissect_init(&edt, cf->epan, FALSE, FALSE); + /* Get the column information */ + epan_dissect_run(&edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, &cf->cinfo); + + /* Find the Info column */ + for (colx = 0; colx < cf->cinfo.num_cols; colx++) { + if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) { + /* Found it. See if we match. */ + info_column = edt.pi.cinfo->columns[colx].col_data; + info_column_len = strlen(info_column); + if (cf->regex) { + if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) { + result = MR_MATCHED; + break; + } + } else { + for (i = 0; i < info_column_len; i++) { + c_char = info_column[i]; + if (cf->case_type) + c_char = g_ascii_toupper(c_char); + if (c_char == string[c_match]) { + c_match++; + if (c_match == string_len) { + result = MR_MATCHED; + break; + } + } else + c_match = 0; + } } - } else - c_match = 0; + break; } - } - break; } - } - epan_dissect_cleanup(&edt); - return result; + epan_dissect_cleanup(&edt); + return result; } typedef struct { @@ -3277,478 +3288,478 @@ typedef struct { gboolean cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size, - search_direction dir) + search_direction dir) { - cbs_t info; - guint8 needles[3]; - ws_mempbrk_pattern pattern; - - info.data = string; - info.data_len = string_size; - - /* Regex, String or hex search? */ - if (cf->regex) { - /* Regular Expression search */ - return find_packet(cf, match_regex, NULL, dir); - } else if (cf->string) { - /* String search - what type of string? */ - if (cf->case_type) { - needles[0] = string[0]; - needles[1] = g_ascii_tolower(needles[0]); - needles[2] = '\0'; - ws_mempbrk_compile(&pattern, needles); - info.pattern = &pattern; - switch (cf->scs_type) { - - case SCS_NARROW_AND_WIDE: - return find_packet(cf, match_narrow_and_wide_case, &info, dir); - - case SCS_NARROW: - return find_packet(cf, match_narrow_case, &info, dir); - - case SCS_WIDE: - return find_packet(cf, match_wide_case, &info, dir); - - default: - ws_assert_not_reached(); - return FALSE; - } + cbs_t info; + guint8 needles[3]; + ws_mempbrk_pattern pattern; + + info.data = string; + info.data_len = string_size; + + /* Regex, String or hex search? */ + if (cf->regex) { + /* Regular Expression search */ + return find_packet(cf, match_regex, NULL, dir); + } else if (cf->string) { + /* String search - what type of string? */ + if (cf->case_type) { + needles[0] = string[0]; + needles[1] = g_ascii_tolower(needles[0]); + needles[2] = '\0'; + ws_mempbrk_compile(&pattern, needles); + info.pattern = &pattern; + switch (cf->scs_type) { + + case SCS_NARROW_AND_WIDE: + return find_packet(cf, match_narrow_and_wide_case, &info, dir); + + case SCS_NARROW: + return find_packet(cf, match_narrow_case, &info, dir); + + case SCS_WIDE: + return find_packet(cf, match_wide_case, &info, dir); + + default: + ws_assert_not_reached(); + return FALSE; + } - } else { - switch (cf->scs_type) { + } else { + switch (cf->scs_type) { - case SCS_NARROW_AND_WIDE: - return find_packet(cf, match_narrow_and_wide, &info, dir); + case SCS_NARROW_AND_WIDE: + return find_packet(cf, match_narrow_and_wide, &info, dir); - case SCS_NARROW: - return find_packet(cf, match_narrow, &info, dir); + case SCS_NARROW: + return find_packet(cf, match_narrow, &info, dir); - case SCS_WIDE: - return find_packet(cf, match_wide, &info, dir); + case SCS_WIDE: + return find_packet(cf, match_wide, &info, dir); - default: - ws_assert_not_reached(); - return FALSE; - } - } - } else - return find_packet(cf, match_binary, &info, dir); + default: + ws_assert_not_reached(); + return FALSE; + } + } + } else + return find_packet(cf, match_binary, &info, dir); } static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - cbs_t *info = (cbs_t *)criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - match_result result; - guint32 buf_len; - guint8 *pd, *buf_start, *buf_end; - guint32 i; - guint8 c_char; - size_t c_match = 0; - - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - result = MR_NOTMATCHED; - buf_len = fdata->cap_len; - buf_start = ws_buffer_start_ptr(buf); - buf_end = buf_start + buf_len; - for (pd = buf_start; pd < buf_end; pd++) { - pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd); - if (pd == NULL) break; - /* Try narrow match at this start location */ - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = pd[i]; - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; + cbs_t *info = (cbs_t *)criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + match_result result; + guint32 buf_len; + guint8 *pd, *buf_start, *buf_end; + guint32 i; + guint8 c_char; + size_t c_match = 0; + + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + result = MR_NOTMATCHED; + buf_len = fdata->cap_len; + buf_start = ws_buffer_start_ptr(buf); + buf_end = buf_start + buf_len; + for (pd = buf_start; pd < buf_end; pd++) { + pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd); + if (pd == NULL) break; + /* Try narrow match at this start location */ + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = pd[i]; + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + } else { + break; + } } - } else { - break; - } - } - - /* Now try wide match at the same start location. */ - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = pd[i]; - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; + + /* Now try wide match at the same start location. */ + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = pd[i]; + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + i++; + if (pd + i >= buf_end || pd[i] != '\0') break; + } else { + break; + } } - i++; - if (pd + i >= buf_end || pd[i] != '\0') break; - } else { - break; - } } - } done: - return result; + return result; } /* Case insensitive match */ static match_result match_narrow_and_wide_case(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - cbs_t *info = (cbs_t *)criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - ws_mempbrk_pattern *pattern = info->pattern; - match_result result; - guint32 buf_len; - guint8 *pd, *buf_start, *buf_end; - guint32 i; - guint8 c_char; - size_t c_match = 0; - - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - ws_assert(pattern != NULL); - - result = MR_NOTMATCHED; - buf_len = fdata->cap_len; - buf_start = ws_buffer_start_ptr(buf); - buf_end = buf_start + buf_len; - for (pd = buf_start; pd < buf_end; pd++) { - pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char); - if (pd == NULL) break; - /* Try narrow match at this start location */ - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = g_ascii_toupper(pd[i]); - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; + cbs_t *info = (cbs_t *)criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + ws_mempbrk_pattern *pattern = info->pattern; + match_result result; + guint32 buf_len; + guint8 *pd, *buf_start, *buf_end; + guint32 i; + guint8 c_char; + size_t c_match = 0; + + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + ws_assert(pattern != NULL); + + result = MR_NOTMATCHED; + buf_len = fdata->cap_len; + buf_start = ws_buffer_start_ptr(buf); + buf_end = buf_start + buf_len; + for (pd = buf_start; pd < buf_end; pd++) { + pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char); + if (pd == NULL) break; + /* Try narrow match at this start location */ + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = g_ascii_toupper(pd[i]); + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + } else { + break; + } } - } else { - break; - } - } - - /* Now try wide match at the same start location. */ - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = g_ascii_toupper(pd[i]); - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; + + /* Now try wide match at the same start location. */ + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = g_ascii_toupper(pd[i]); + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + i++; + if (pd + i >= buf_end || pd[i] != '\0') break; + } else { + break; + } } - i++; - if (pd + i >= buf_end || pd[i] != '\0') break; - } else { - break; - } } - } done: - return result; + return result; } static match_result match_narrow(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - cbs_t *info = (cbs_t *)criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - match_result result; - guint32 buf_len; - guint8 *pd, *buf_start, *buf_end; - guint32 i; - guint8 c_char; - size_t c_match = 0; - - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - result = MR_NOTMATCHED; - buf_len = fdata->cap_len; - buf_start = ws_buffer_start_ptr(buf); - buf_end = buf_start + buf_len; - for (pd = buf_start; pd < buf_end; pd++) { - pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd); - if (pd == NULL) break; - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = pd[i]; - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; + cbs_t *info = (cbs_t *)criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + match_result result; + guint32 buf_len; + guint8 *pd, *buf_start, *buf_end; + guint32 i; + guint8 c_char; + size_t c_match = 0; + + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + result = MR_NOTMATCHED; + buf_len = fdata->cap_len; + buf_start = ws_buffer_start_ptr(buf); + buf_end = buf_start + buf_len; + for (pd = buf_start; pd < buf_end; pd++) { + pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd); + if (pd == NULL) break; + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = pd[i]; + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + } else { + break; + } } - } else { - break; - } } - } done: - return result; + return result; } /* Case insensitive match */ static match_result match_narrow_case(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - cbs_t *info = (cbs_t *)criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - ws_mempbrk_pattern *pattern = info->pattern; - match_result result; - guint32 buf_len; - guint8 *pd, *buf_start, *buf_end; - guint32 i; - guint8 c_char; - size_t c_match = 0; - - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - ws_assert(pattern != NULL); - - result = MR_NOTMATCHED; - buf_len = fdata->cap_len; - buf_start = ws_buffer_start_ptr(buf); - buf_end = buf_start + buf_len; - for (pd = buf_start; pd < buf_end; pd++) { - pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char); - if (pd == NULL) break; - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = g_ascii_toupper(pd[i]); - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; + cbs_t *info = (cbs_t *)criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + ws_mempbrk_pattern *pattern = info->pattern; + match_result result; + guint32 buf_len; + guint8 *pd, *buf_start, *buf_end; + guint32 i; + guint8 c_char; + size_t c_match = 0; + + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + ws_assert(pattern != NULL); + + result = MR_NOTMATCHED; + buf_len = fdata->cap_len; + buf_start = ws_buffer_start_ptr(buf); + buf_end = buf_start + buf_len; + for (pd = buf_start; pd < buf_end; pd++) { + pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char); + if (pd == NULL) break; + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = g_ascii_toupper(pd[i]); + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + } else { + break; + } } - } else { - break; - } } - } done: - return result; + return result; } static match_result match_wide(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - cbs_t *info = (cbs_t *)criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - match_result result; - guint32 buf_len; - guint8 *pd, *buf_start, *buf_end; - guint32 i; - guint8 c_char; - size_t c_match = 0; - - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - result = MR_NOTMATCHED; - buf_len = fdata->cap_len; - buf_start = ws_buffer_start_ptr(buf); - buf_end = buf_start + buf_len; - for (pd = buf_start; pd < buf_end; pd++) { - pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd); - if (pd == NULL) break; - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = pd[i]; - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; + cbs_t *info = (cbs_t *)criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + match_result result; + guint32 buf_len; + guint8 *pd, *buf_start, *buf_end; + guint32 i; + guint8 c_char; + size_t c_match = 0; + + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + result = MR_NOTMATCHED; + buf_len = fdata->cap_len; + buf_start = ws_buffer_start_ptr(buf); + buf_end = buf_start + buf_len; + for (pd = buf_start; pd < buf_end; pd++) { + pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd); + if (pd == NULL) break; + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = pd[i]; + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + i++; + if (pd + i >= buf_end || pd[i] != '\0') break; + } else { + break; + } } - i++; - if (pd + i >= buf_end || pd[i] != '\0') break; - } else { - break; - } } - } done: - return result; + return result; } /* Case insensitive match */ static match_result match_wide_case(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - cbs_t *info = (cbs_t *)criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - ws_mempbrk_pattern *pattern = info->pattern; - match_result result; - guint32 buf_len; - guint8 *pd, *buf_start, *buf_end; - guint32 i; - guint8 c_char; - size_t c_match = 0; - - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - ws_assert(pattern != NULL); - - result = MR_NOTMATCHED; - buf_len = fdata->cap_len; - buf_start = ws_buffer_start_ptr(buf); - buf_end = buf_start + buf_len; - for (pd = buf_start; pd < buf_end; pd++) { - pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char); - if (pd == NULL) break; - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = g_ascii_toupper(pd[i]); - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; + cbs_t *info = (cbs_t *)criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + ws_mempbrk_pattern *pattern = info->pattern; + match_result result; + guint32 buf_len; + guint8 *pd, *buf_start, *buf_end; + guint32 i; + guint8 c_char; + size_t c_match = 0; + + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + ws_assert(pattern != NULL); + + result = MR_NOTMATCHED; + buf_len = fdata->cap_len; + buf_start = ws_buffer_start_ptr(buf); + buf_end = buf_start + buf_len; + for (pd = buf_start; pd < buf_end; pd++) { + pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char); + if (pd == NULL) break; + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = g_ascii_toupper(pd[i]); + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + i++; + if (pd + i >= buf_end || pd[i] != '\0') break; + } else { + break; + } } - i++; - if (pd + i >= buf_end || pd[i] != '\0') break; - } else { - break; - } } - } done: - return result; + return result; } static match_result match_binary(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - cbs_t *info = (cbs_t *)criterion; - const guint8 *binary_data = info->data; - size_t datalen = info->data_len; - match_result result; - guint32 buf_len; - guint8 *pd, *buf_start, *buf_end; - guint32 i; - size_t c_match = 0; - - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - result = MR_NOTMATCHED; - buf_len = fdata->cap_len; - buf_start = ws_buffer_start_ptr(buf); - buf_end = buf_start + buf_len; - /* Not clear if using memcmp() is faster. memmem() on systems that - * have it should be faster, though. - */ - for (pd = buf_start; pd < buf_end; pd++) { - pd = (guint8 *)memchr(pd, binary_data[0], buf_end - pd); - if (pd == NULL) break; - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - if (pd[i] == binary_data[c_match]) { - c_match++; - if (c_match == datalen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; + cbs_t *info = (cbs_t *)criterion; + const guint8 *binary_data = info->data; + size_t datalen = info->data_len; + match_result result; + guint32 buf_len; + guint8 *pd, *buf_start, *buf_end; + guint32 i; + size_t c_match = 0; + + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + result = MR_NOTMATCHED; + buf_len = fdata->cap_len; + buf_start = ws_buffer_start_ptr(buf); + buf_end = buf_start + buf_len; + /* Not clear if using memcmp() is faster. memmem() on systems that + * have it should be faster, though. + */ + for (pd = buf_start; pd < buf_end; pd++) { + pd = (guint8 *)memchr(pd, binary_data[0], buf_end - pd); + if (pd == NULL) break; + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + if (pd[i] == binary_data[c_match]) { + c_match++; + if (c_match == datalen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + } else { + break; + } } - } else { - break; - } } - } done: - return result; + return result; } static match_result match_regex(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion _U_) + wtap_rec *rec, Buffer *buf, void *criterion _U_) { match_result result = MR_NOTMATCHED; GMatchInfo *match_info = NULL; @@ -3760,7 +3771,7 @@ match_regex(capture_file *cf, frame_data *fdata, } if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(buf), fdata->cap_len, - 0, (GRegexMatchFlags) 0, &match_info, NULL)) + 0, (GRegexMatchFlags) 0, &match_info, NULL)) { gint start_pos = 0, end_pos = 0; g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos); @@ -3773,296 +3784,296 @@ match_regex(capture_file *cf, frame_data *fdata, gboolean cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode, - search_direction dir) + search_direction dir) { - return find_packet(cf, match_dfilter, sfcode, dir); + return find_packet(cf, match_dfilter, sfcode, dir); } gboolean cf_find_packet_dfilter_string(capture_file *cf, const char *filter, - search_direction dir) + search_direction dir) { - dfilter_t *sfcode; - gboolean result; - - if (!dfilter_compile(filter, &sfcode, NULL)) { - /* - * XXX - this shouldn't happen, as the filter string is machine - * generated - */ - return FALSE; - } - if (sfcode == NULL) { - /* - * XXX - this shouldn't happen, as the filter string is machine - * generated. - */ - return FALSE; - } - result = find_packet(cf, match_dfilter, sfcode, dir); - dfilter_free(sfcode); - return result; + dfilter_t *sfcode; + gboolean result; + + if (!dfilter_compile(filter, &sfcode, NULL)) { + /* + * XXX - this shouldn't happen, as the filter string is machine + * generated + */ + return FALSE; + } + if (sfcode == NULL) { + /* + * XXX - this shouldn't happen, as the filter string is machine + * generated. + */ + return FALSE; + } + result = find_packet(cf, match_dfilter, sfcode, dir); + dfilter_free(sfcode); + return result; } static match_result match_dfilter(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - dfilter_t *sfcode = (dfilter_t *)criterion; - epan_dissect_t edt; - match_result result; - - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - epan_dissect_init(&edt, cf->epan, TRUE, FALSE); - epan_dissect_prime_with_dfilter(&edt, sfcode); - epan_dissect_run(&edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, NULL); - result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED; - epan_dissect_cleanup(&edt); - return result; + dfilter_t *sfcode = (dfilter_t *)criterion; + epan_dissect_t edt; + match_result result; + + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + epan_dissect_init(&edt, cf->epan, TRUE, FALSE); + epan_dissect_prime_with_dfilter(&edt, sfcode); + epan_dissect_run(&edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, NULL); + result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED; + epan_dissect_cleanup(&edt); + return result; } gboolean cf_find_packet_marked(capture_file *cf, search_direction dir) { - return find_packet(cf, match_marked, NULL, dir); + return find_packet(cf, match_marked, NULL, dir); } static match_result match_marked(capture_file *cf _U_, frame_data *fdata, wtap_rec *rec _U_, - Buffer *buf _U_, void *criterion _U_) + Buffer *buf _U_, void *criterion _U_) { - return fdata->marked ? MR_MATCHED : MR_NOTMATCHED; + return fdata->marked ? MR_MATCHED : MR_NOTMATCHED; } gboolean cf_find_packet_time_reference(capture_file *cf, search_direction dir) { - return find_packet(cf, match_time_reference, NULL, dir); + return find_packet(cf, match_time_reference, NULL, dir); } static match_result match_time_reference(capture_file *cf _U_, frame_data *fdata, wtap_rec *rec _U_, - Buffer *buf _U_, void *criterion _U_) + Buffer *buf _U_, void *criterion _U_) { - return fdata->ref_time ? MR_MATCHED : MR_NOTMATCHED; + return fdata->ref_time ? MR_MATCHED : MR_NOTMATCHED; } static gboolean find_packet(capture_file *cf, ws_match_function match_function, - void *criterion, search_direction dir) + void *criterion, search_direction dir) { - frame_data *start_fd; - guint32 framenum; - guint32 prev_framenum; - frame_data *fdata; - wtap_rec rec; - Buffer buf; - frame_data *new_fd = NULL; - progdlg_t *progbar = NULL; - GTimer *prog_timer = g_timer_new(); - int count; - gboolean succeeded; - float progbar_val; - gchar status_str[100]; - match_result result; - - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); - - start_fd = cf->current_frame; - if (start_fd != NULL) { - prev_framenum = start_fd->num; - } else { - prev_framenum = 0; /* No start packet selected. */ - } - - /* Iterate through the list of packets, starting at the packet we've - picked, calling a routine to run the filter on the packet, see if - it matches, and stop if so. */ - count = 0; - framenum = prev_framenum; - - g_timer_start(prog_timer); - /* Progress so far. */ - progbar_val = 0.0f; - - cf->stop_flag = FALSE; - - for (;;) { - /* 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(cf->window, NULL, NULL, - FALSE, &cf->stop_flag, progbar_val); + frame_data *start_fd; + guint32 framenum; + guint32 prev_framenum; + frame_data *fdata; + wtap_rec rec; + Buffer buf; + frame_data *new_fd = NULL; + progdlg_t *progbar = NULL; + GTimer *prog_timer = g_timer_new(); + int count; + gboolean succeeded; + float progbar_val; + gchar status_str[100]; + match_result result; - /* - * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL - * has elapsed. Calling update_progress_dlg and packets_bar_update will - * likely trigger UI paint events, which might take a while depending on - * the platform and display. Reset our timer *after* painting. - */ - if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { - /* let's not divide by zero. I should never be started - * with count == 0, so let's assert that - */ - ws_assert(cf->count > 0); + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); + + start_fd = cf->current_frame; + if (start_fd != NULL) { + prev_framenum = start_fd->num; + } else { + prev_framenum = 0; /* No start packet selected. */ + } - progbar_val = (gfloat) count / cf->count; + /* Iterate through the list of packets, starting at the packet we've + picked, calling a routine to run the filter on the packet, see if + it matches, and stop if so. */ + count = 0; + framenum = prev_framenum; - snprintf(status_str, sizeof(status_str), - "%4u of %u packets", count, cf->count); - update_progress_dlg(progbar, progbar_val, status_str); + g_timer_start(prog_timer); + /* Progress so far. */ + progbar_val = 0.0f; - g_timer_start(prog_timer); - } + cf->stop_flag = FALSE; - if (cf->stop_flag) { - /* Well, the user decided to abort the search. Go back to the - frame where we started. */ - new_fd = start_fd; - break; - } + for (;;) { + /* 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(cf->window, NULL, NULL, + FALSE, &cf->stop_flag, progbar_val); - /* Go past the current frame. */ - if (dir == SD_BACKWARD) { - /* Go on to the previous frame. */ - if (framenum <= 1) { /* - * XXX - other apps have a bit more of a detailed message - * for this, and instead of offering "OK" and "Cancel", - * they offer things such as "Continue" and "Cancel"; - * we need an API for popping up alert boxes with - * {Verb} and "Cancel". + * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL + * has elapsed. Calling update_progress_dlg and packets_bar_update will + * likely trigger UI paint events, which might take a while depending on + * the platform and display. Reset our timer *after* painting. */ + if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { + /* let's not divide by zero. I should never be started + * with count == 0, so let's assert that + */ + ws_assert(cf->count > 0); - if (prefs.gui_find_wrap) { - statusbar_push_temporary_msg("Search reached the beginning. Continuing at end."); - framenum = cf->count; /* wrap around */ - } else { - statusbar_push_temporary_msg("Search reached the beginning."); - framenum = prev_framenum; /* stay on previous packet */ + progbar_val = (gfloat) count / cf->count; + + snprintf(status_str, sizeof(status_str), + "%4u of %u packets", count, cf->count); + update_progress_dlg(progbar, progbar_val, status_str); + + g_timer_start(prog_timer); } - } else - framenum--; - } else { - /* Go on to the next frame. */ - if (framenum == cf->count) { - if (prefs.gui_find_wrap) { - statusbar_push_temporary_msg("Search reached the end. Continuing at beginning."); - framenum = 1; /* wrap around */ + + if (cf->stop_flag) { + /* Well, the user decided to abort the search. Go back to the + frame where we started. */ + new_fd = start_fd; + break; + } + + /* Go past the current frame. */ + if (dir == SD_BACKWARD) { + /* Go on to the previous frame. */ + if (framenum <= 1) { + /* + * XXX - other apps have a bit more of a detailed message + * for this, and instead of offering "OK" and "Cancel", + * they offer things such as "Continue" and "Cancel"; + * we need an API for popping up alert boxes with + * {Verb} and "Cancel". + */ + + if (prefs.gui_find_wrap) { + statusbar_push_temporary_msg("Search reached the beginning. Continuing at end."); + framenum = cf->count; /* wrap around */ + } else { + statusbar_push_temporary_msg("Search reached the beginning."); + framenum = prev_framenum; /* stay on previous packet */ + } + } else + framenum--; } else { - statusbar_push_temporary_msg("Search reached the end."); - framenum = prev_framenum; /* stay on previous packet */ + /* Go on to the next frame. */ + if (framenum == cf->count) { + if (prefs.gui_find_wrap) { + statusbar_push_temporary_msg("Search reached the end. Continuing at beginning."); + framenum = 1; /* wrap around */ + } else { + statusbar_push_temporary_msg("Search reached the end."); + framenum = prev_framenum; /* stay on previous packet */ + } + } else + framenum++; + } + + fdata = frame_data_sequence_find(cf->provider.frames, framenum); + count++; + + /* Is this packet in the display? */ + if (fdata && fdata->passed_dfilter) { + /* Yes. Does it match the search criterion? */ + result = (*match_function)(cf, fdata, &rec, &buf, criterion); + if (result == MR_ERROR) { + /* Error; our caller has reported the error. Go back to the frame + where we started. */ + new_fd = start_fd; + break; + } else if (result == MR_MATCHED) { + /* Yes. Go to the new frame. */ + new_fd = fdata; + break; + } + wtap_rec_reset(&rec); + } + + if (fdata == start_fd) { + /* We're back to the frame we were on originally, and that frame + doesn't match the search filter. The search failed. */ + break; } - } else - framenum++; } - fdata = frame_data_sequence_find(cf->provider.frames, framenum); - count++; - - /* Is this packet in the display? */ - if (fdata && fdata->passed_dfilter) { - /* Yes. Does it match the search criterion? */ - result = (*match_function)(cf, fdata, &rec, &buf, criterion); - if (result == MR_ERROR) { - /* Error; our caller has reported the error. Go back to the frame - where we started. */ - new_fd = start_fd; - break; - } else if (result == MR_MATCHED) { - /* Yes. Go to the new frame. */ - new_fd = fdata; - break; - } - wtap_rec_reset(&rec); - } - - if (fdata == start_fd) { - /* We're back to the frame we were on originally, and that frame - doesn't match the search filter. The search failed. */ - break; - } - } - - /* We're done scanning the packets; destroy the progress bar if it - was created. */ - if (progbar != NULL) - destroy_progress_dlg(progbar); - g_timer_destroy(prog_timer); - - if (new_fd != NULL) { - /* We found a frame that's displayed and that matches. - Try to find and select the packet summary list row for that frame. */ - gboolean found_row; - - cf->search_in_progress = TRUE; - found_row = packet_list_select_row_from_data(new_fd); - cf->search_in_progress = FALSE; - cf->search_pos = 0; /* Reset the position */ - cf->search_len = 0; /* Reset length */ - if (!found_row) { - /* We didn't find a row corresponding to this frame. - This means that the frame isn't being displayed currently, - 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."); - succeeded = FALSE; /* The search succeeded but we didn't find the row */ + /* We're done scanning the packets; destroy the progress bar if it + was created. */ + if (progbar != NULL) + destroy_progress_dlg(progbar); + g_timer_destroy(prog_timer); + + if (new_fd != NULL) { + /* We found a frame that's displayed and that matches. + Try to find and select the packet summary list row for that frame. */ + gboolean found_row; + + cf->search_in_progress = TRUE; + found_row = packet_list_select_row_from_data(new_fd); + cf->search_in_progress = FALSE; + cf->search_pos = 0; /* Reset the position */ + cf->search_len = 0; /* Reset length */ + if (!found_row) { + /* We didn't find a row corresponding to this frame. + This means that the frame isn't being displayed currently, + 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."); + succeeded = FALSE; /* The search succeeded but we didn't find the row */ + } else + succeeded = TRUE; /* The search succeeded and we found the row */ } else - succeeded = TRUE; /* The search succeeded and we found the row */ - } else - succeeded = FALSE; /* The search failed */ - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - return succeeded; + succeeded = FALSE; /* The search failed */ + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + return succeeded; } gboolean cf_goto_frame(capture_file *cf, guint fnumber) { - frame_data *fdata; - - if (cf == NULL || cf->provider.frames == NULL) { - /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */ - statusbar_push_temporary_msg("There is no file loaded"); - return FALSE; /* we failed to go to that packet */ - } - - fdata = frame_data_sequence_find(cf->provider.frames, fnumber); - - if (fdata == NULL) { - /* we didn't find a packet with that packet number */ - statusbar_push_temporary_msg("There is no packet number %u.", fnumber); - return FALSE; /* we failed to go to that packet */ - } - if (!fdata->passed_dfilter) { - /* that packet currently isn't displayed */ - /* XXX - add it to the set of displayed packets? */ - statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber); - return FALSE; /* we failed to go to that packet */ - } - - if (!packet_list_select_row_from_data(fdata)) { - /* We didn't find a row corresponding to this frame. - This means that the frame isn't being displayed currently, - 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."); - return FALSE; - } - return TRUE; /* we got to that packet */ + frame_data *fdata; + + if (cf == NULL || cf->provider.frames == NULL) { + /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */ + statusbar_push_temporary_msg("There is no file loaded"); + return FALSE; /* we failed to go to that packet */ + } + + fdata = frame_data_sequence_find(cf->provider.frames, fnumber); + + if (fdata == NULL) { + /* we didn't find a packet with that packet number */ + statusbar_push_temporary_msg("There is no packet number %u.", fnumber); + return FALSE; /* we failed to go to that packet */ + } + if (!fdata->passed_dfilter) { + /* that packet currently isn't displayed */ + /* XXX - add it to the set of displayed packets? */ + statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber); + return FALSE; /* we failed to go to that packet */ + } + + if (!packet_list_select_row_from_data(fdata)) { + /* We didn't find a row corresponding to this frame. + This means that the frame isn't being displayed currently, + 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."); + return FALSE; + } + return TRUE; /* we got to that packet */ } /* @@ -4071,99 +4082,99 @@ cf_goto_frame(capture_file *cf, guint fnumber) gboolean cf_goto_framenum(capture_file *cf) { - header_field_info *hfinfo; - guint32 framenum; - - if (cf->finfo_selected) { - hfinfo = cf->finfo_selected->hfinfo; - ws_assert(hfinfo); - if (hfinfo->type == FT_FRAMENUM) { - framenum = fvalue_get_uinteger(&cf->finfo_selected->value); - if (framenum != 0) - return cf_goto_frame(cf, framenum); - } - } - - return FALSE; + header_field_info *hfinfo; + guint32 framenum; + + if (cf->finfo_selected) { + hfinfo = cf->finfo_selected->hfinfo; + ws_assert(hfinfo); + if (hfinfo->type == FT_FRAMENUM) { + framenum = fvalue_get_uinteger(&cf->finfo_selected->value); + if (framenum != 0) + return cf_goto_frame(cf, framenum); + } + } + + return FALSE; } /* Select the packet on a given row. */ void cf_select_packet(capture_file *cf, int row) { - epan_dissect_t *old_edt; - frame_data *fdata; - - /* Get the frame data struct pointer for this frame */ - fdata = packet_list_get_row_data(row); - - if (fdata == NULL) { - return; - } - - /* Get the data in that frame. */ - if (!cf_read_record(cf, fdata, &cf->rec, &cf->buf)) { - return; - } - - /* Record that this frame is the current frame. */ - cf->current_frame = fdata; - cf->current_row = row; - - /* - * The change to defer freeing the current epan_dissect_t was in - * commit a2bb94c3b33d53f42534aceb7cc67aab1d1fb1f9; to quote - * that commit's comment: - * - * Clear GtkTreeStore before freeing edt - * - * When building current data for packet details treeview we store two - * things. - * - Generated string with item label - * - Pointer to node field_info structure - * - * After epan_dissect_{free, cleanup} pointer to field_info node is no - * longer valid so we should clear GtkTreeStore before freeing. - * - * XXX - we're no longer using GTK+; is there a way to ensure that - * *nothing* refers to any of the current frame information before - * we replace it? - */ - old_edt = cf->edt; - /* Create the logical protocol tree. */ - /* We don't need the columns here. */ - cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE); - - tap_build_interesting(cf->edt); - epan_dissect_run(cf->edt, cf->cd_t, &cf->rec, - frame_tvbuff_new_buffer(&cf->provider, cf->current_frame, &cf->buf), - cf->current_frame, NULL); - - dfilter_macro_build_ftv_cache(cf->edt->tree); - - if (old_edt != NULL) - epan_dissect_free(old_edt); + epan_dissect_t *old_edt; + frame_data *fdata; + + /* Get the frame data struct pointer for this frame */ + fdata = packet_list_get_row_data(row); + + if (fdata == NULL) { + return; + } + + /* Get the data in that frame. */ + if (!cf_read_record(cf, fdata, &cf->rec, &cf->buf)) { + return; + } + + /* Record that this frame is the current frame. */ + cf->current_frame = fdata; + cf->current_row = row; + + /* + * The change to defer freeing the current epan_dissect_t was in + * commit a2bb94c3b33d53f42534aceb7cc67aab1d1fb1f9; to quote + * that commit's comment: + * + * Clear GtkTreeStore before freeing edt + * + * When building current data for packet details treeview we store two + * things. + * - Generated string with item label + * - Pointer to node field_info structure + * + * After epan_dissect_{free, cleanup} pointer to field_info node is no + * longer valid so we should clear GtkTreeStore before freeing. + * + * XXX - we're no longer using GTK+; is there a way to ensure that + * *nothing* refers to any of the current frame information before + * we replace it? + */ + old_edt = cf->edt; + /* Create the logical protocol tree. */ + /* We don't need the columns here. */ + cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE); + + tap_build_interesting(cf->edt); + epan_dissect_run(cf->edt, cf->cd_t, &cf->rec, + frame_tvbuff_new_buffer(&cf->provider, cf->current_frame, &cf->buf), + cf->current_frame, NULL); + + dfilter_macro_build_ftv_cache(cf->edt->tree); + + if (old_edt != NULL) + epan_dissect_free(old_edt); } /* Unselect the selected packet, if any. */ void cf_unselect_packet(capture_file *cf) { - epan_dissect_t *old_edt = cf->edt; + epan_dissect_t *old_edt = cf->edt; - /* - * See the comment in cf_select_packet() about deferring the freeing - * of the old cf->edt. - */ - cf->edt = NULL; + /* + * See the comment in cf_select_packet() about deferring the freeing + * of the old cf->edt. + */ + cf->edt = NULL; - /* No packet is selected. */ - cf->current_frame = NULL; - cf->current_row = 0; + /* No packet is selected. */ + cf->current_frame = NULL; + cf->current_row = 0; - /* Destroy the epan_dissect_t for the unselected packet. */ - if (old_edt != NULL) - epan_dissect_free(old_edt); + /* Destroy the epan_dissect_t for the unselected packet. */ + if (old_edt != NULL) + epan_dissect_free(old_edt); } /* @@ -4172,11 +4183,11 @@ cf_unselect_packet(capture_file *cf) void cf_mark_frame(capture_file *cf, frame_data *frame) { - if (! frame->marked) { - frame->marked = TRUE; - if (cf->count > cf->marked_count) - cf->marked_count++; - } + if (! frame->marked) { + frame->marked = TRUE; + if (cf->count > cf->marked_count) + cf->marked_count++; + } } /* @@ -4185,11 +4196,11 @@ cf_mark_frame(capture_file *cf, frame_data *frame) void cf_unmark_frame(capture_file *cf, frame_data *frame) { - if (frame->marked) { - frame->marked = FALSE; - if (cf->marked_count > 0) - cf->marked_count--; - } + if (frame->marked) { + frame->marked = FALSE; + if (cf->marked_count > 0) + cf->marked_count--; + } } /* @@ -4198,11 +4209,11 @@ cf_unmark_frame(capture_file *cf, frame_data *frame) void cf_ignore_frame(capture_file *cf, frame_data *frame) { - if (! frame->ignored) { - frame->ignored = TRUE; - if (cf->count > cf->ignored_count) - cf->ignored_count++; - } + if (! frame->ignored) { + frame->ignored = TRUE; + if (cf->count > cf->ignored_count) + cf->ignored_count++; + } } /* @@ -4211,11 +4222,11 @@ cf_ignore_frame(capture_file *cf, frame_data *frame) void cf_unignore_frame(capture_file *cf, frame_data *frame) { - if (frame->ignored) { - frame->ignored = FALSE; - if (cf->ignored_count > 0) - cf->ignored_count--; - } + if (frame->ignored) { + frame->ignored = FALSE; + if (cf->ignored_count > 0) + cf->ignored_count--; + } } /* @@ -4224,30 +4235,30 @@ cf_unignore_frame(capture_file *cf, frame_data *frame) void cf_update_section_comment(capture_file *cf, gchar *comment) { - wtap_block_t shb_inf; - gchar *shb_comment; - - /* Get the first SHB. */ - /* XXX - support multiple SHBs */ - shb_inf = wtap_file_get_shb(cf->provider.wth, 0); - - /* Get the first comment from the SHB. */ - /* XXX - support multiple comments */ - if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) { - /* There's no comment - add one. */ - wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment)); - } else { - /* See if the comment has changed or not */ - if (strcmp(shb_comment, comment) == 0) { - g_free(comment); - return; - } - - /* The comment has changed, let's update it */ - wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment)); - } - /* Mark the file as having unsaved changes */ - cf->unsaved_changes = TRUE; + wtap_block_t shb_inf; + gchar *shb_comment; + + /* Get the first SHB. */ + /* XXX - support multiple SHBs */ + shb_inf = wtap_file_get_shb(cf->provider.wth, 0); + + /* Get the first comment from the SHB. */ + /* XXX - support multiple comments */ + if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) { + /* There's no comment - add one. */ + wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment)); + } else { + /* See if the comment has changed or not */ + if (strcmp(shb_comment, comment) == 0) { + g_free(comment); + return; + } + + /* The comment has changed, let's update it */ + wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment)); + } + /* Mark the file as having unsaved changes */ + cf->unsaved_changes = TRUE; } /* @@ -4259,28 +4270,28 @@ cf_update_section_comment(capture_file *cf, gchar *comment) wtap_block_t cf_get_packet_block(capture_file *cf, const frame_data *fd) { - /* If this block has been modified, fetch the modified version */ - if (fd->has_modified_block) - return wtap_block_ref(cap_file_provider_get_modified_block(&cf->provider, fd)); - else { - wtap_rec rec; /* Record metadata */ - Buffer buf; /* Record data */ - wtap_block_t block; - - /* fetch record block */ - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); - - if (!cf_read_record(cf, fd, &rec, &buf)) - { /* XXX, what we can do here? */ } - - /* rec.block is owned by the record, steal it before it is gone. */ - block = wtap_block_ref(rec.block); - - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - return block; - } + /* If this block has been modified, fetch the modified version */ + if (fd->has_modified_block) + return wtap_block_ref(cap_file_provider_get_modified_block(&cf->provider, fd)); + else { + wtap_rec rec; /* Record metadata */ + Buffer buf; /* Record data */ + wtap_block_t block; + + /* fetch record block */ + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); + + if (!cf_read_record(cf, fd, &rec, &buf)) + { /* XXX, what we can do here? */ } + + /* rec.block is owned by the record, steal it before it is gone. */ + block = wtap_block_ref(rec.block); + + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + return block; + } } /* @@ -4289,36 +4300,36 @@ cf_get_packet_block(capture_file *cf, const frame_data *fd) gboolean cf_set_modified_block(capture_file *cf, frame_data *fd, const wtap_block_t new_block) { - wtap_block_t pkt_block = cf_get_packet_block(cf, fd); - - /* It's possible to further modify the modified block "in place" by doing - * a call to cf_get_packet_block() that returns an already created modified - * block, modifying that, and calling this function. - * If the caller did that, then the block pointers will be equal. - */ - if (pkt_block == new_block) { - /* No need to save anything here, the caller changes went right - * onto the block. - * Unfortunately we don't have a way to know how many comments were in the block - * before the caller modified it. + wtap_block_t pkt_block = cf_get_packet_block(cf, fd); + + /* It's possible to further modify the modified block "in place" by doing + * a call to cf_get_packet_block() that returns an already created modified + * block, modifying that, and calling this function. + * If the caller did that, then the block pointers will be equal. */ - } - else { - if (pkt_block) - cf->packet_comment_count -= wtap_block_count_option(pkt_block, OPT_COMMENT); + if (pkt_block == new_block) { + /* No need to save anything here, the caller changes went right + * onto the block. + * Unfortunately we don't have a way to know how many comments were in the block + * before the caller modified it. + */ + } + else { + if (pkt_block) + cf->packet_comment_count -= wtap_block_count_option(pkt_block, OPT_COMMENT); - if (new_block) - cf->packet_comment_count += wtap_block_count_option(new_block, OPT_COMMENT); + if (new_block) + cf->packet_comment_count += wtap_block_count_option(new_block, OPT_COMMENT); - cap_file_provider_set_modified_block(&cf->provider, fd, new_block); + cap_file_provider_set_modified_block(&cf->provider, fd, new_block); - expert_update_comment_count(cf->packet_comment_count); - } + expert_update_comment_count(cf->packet_comment_count); + } - /* Either way, we have unsaved changes. */ - wtap_block_unref(pkt_block); - cf->unsaved_changes = TRUE; - return TRUE; + /* Either way, we have unsaved changes. */ + wtap_block_unref(pkt_block); + cf->unsaved_changes = TRUE; + return TRUE; } /* @@ -4327,32 +4338,32 @@ cf_set_modified_block(capture_file *cf, frame_data *fd, const wtap_block_t new_b guint32 cf_comment_types(capture_file *cf) { - guint32 comment_types = 0; - - /* - * Does this file have any sections with at least one comment? - */ - for (guint section_number = 0; - section_number < wtap_file_get_num_shbs(cf->provider.wth); - section_number++) { - wtap_block_t shb_inf; - char *shb_comment; - - shb_inf = wtap_file_get_shb(cf->provider.wth, section_number); - - /* Try to get the first comment from that SHB. */ - if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, - &shb_comment) == WTAP_OPTTYPE_SUCCESS) { - /* We succeeded, so this file has at least one section comment. */ - comment_types |= WTAP_COMMENT_PER_SECTION; - - /* We don't need to search any more. */ - break; - } - } - if (cf->packet_comment_count != 0) - comment_types |= WTAP_COMMENT_PER_PACKET; - return comment_types; + guint32 comment_types = 0; + + /* + * Does this file have any sections with at least one comment? + */ + for (guint section_number = 0; + section_number < wtap_file_get_num_shbs(cf->provider.wth); + section_number++) { + wtap_block_t shb_inf; + char *shb_comment; + + shb_inf = wtap_file_get_shb(cf->provider.wth, section_number); + + /* Try to get the first comment from that SHB. */ + if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, + &shb_comment) == WTAP_OPTTYPE_SUCCESS) { + /* We succeeded, so this file has at least one section comment. */ + comment_types |= WTAP_COMMENT_PER_SECTION; + + /* We don't need to search any more. */ + break; + } + } + if (cf->packet_comment_count != 0) + comment_types |= WTAP_COMMENT_PER_PACKET; + return comment_types; } /* @@ -4361,22 +4372,22 @@ cf_comment_types(capture_file *cf) gboolean cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name) { - /* - * XXX - support multiple resolved address lists, and add to the one - * attached to this file? - */ - if (!add_ip_name_from_string(addr, name)) - return FALSE; + /* + * XXX - support multiple resolved address lists, and add to the one + * attached to this file? + */ + if (!add_ip_name_from_string(addr, name)) + return FALSE; - /* OK, we have unsaved changes. */ - cf->unsaved_changes = TRUE; - return TRUE; + /* OK, we have unsaved changes. */ + cf->unsaved_changes = TRUE; + return TRUE; } typedef struct { - wtap_dumper *pdh; - const char *fname; - int file_type; + wtap_dumper *pdh; + const char *fname; + int file_type; } save_callback_args_t; /* @@ -4388,35 +4399,35 @@ typedef struct { */ static gboolean save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec, - Buffer *buf, void *argsp) + Buffer *buf, void *argsp) { - save_callback_args_t *args = (save_callback_args_t *)argsp; - wtap_rec new_rec; - int err; - gchar *err_info; - wtap_block_t pkt_block; - - /* Copy the record information from what was read in from the file. */ - new_rec = *rec; - - /* Make changes based on anything that the user has done but that - hasn't been saved yet. */ - if (fdata->has_modified_block) - pkt_block = cap_file_provider_get_modified_block(&cf->provider, fdata); - else - pkt_block = rec->block; - new_rec.block = pkt_block; - new_rec.block_was_modified = fdata->has_modified_block ? TRUE : FALSE; - /* XXX - what if times have been shifted? */ - - /* and save the packet */ - if (!wtap_dump(args->pdh, &new_rec, ws_buffer_start_ptr(buf), &err, &err_info)) { - cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num, - args->file_type); - return FALSE; - } + save_callback_args_t *args = (save_callback_args_t *)argsp; + wtap_rec new_rec; + int err; + gchar *err_info; + wtap_block_t pkt_block; + + /* Copy the record information from what was read in from the file. */ + new_rec = *rec; + + /* Make changes based on anything that the user has done but that + hasn't been saved yet. */ + if (fdata->has_modified_block) + pkt_block = cap_file_provider_get_modified_block(&cf->provider, fdata); + else + pkt_block = rec->block; + new_rec.block = pkt_block; + new_rec.block_was_modified = fdata->has_modified_block ? TRUE : FALSE; + /* XXX - what if times have been shifted? */ + + /* and save the packet */ + if (!wtap_dump(args->pdh, &new_rec, ws_buffer_start_ptr(buf), &err, &err_info)) { + cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num, + args->file_type); + return FALSE; + } - return TRUE; + return TRUE; } /* @@ -4426,10 +4437,10 @@ save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec, gboolean cf_can_write_with_wiretap(capture_file *cf) { - /* We don't care whether we support the comments in this file or not; - if we can't, we'll offer the user the option of discarding the - comments. */ - return wtap_dump_can_write(cf->linktypes, 0); + /* We don't care whether we support the comments in this file or not; + if we can't, we'll offer the user the option of discarding the + comments. */ + return wtap_dump_can_write(cf->linktypes, 0); } /* @@ -4455,21 +4466,21 @@ cf_can_write_with_wiretap(capture_file *cf) gboolean cf_can_save(capture_file *cf) { - if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) { - /* Saved changes, and we can write it out with Wiretap. */ - return TRUE; - } + if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) { + /* Saved changes, and we can write it out with Wiretap. */ + return TRUE; + } - if (cf->is_tempfile && !cf->unsaved_changes) { - /* - * Temporary file with no unsaved changes, so we can just do a - * raw binary copy. - */ - return TRUE; - } + if (cf->is_tempfile && !cf->unsaved_changes) { + /* + * Temporary file with no unsaved changes, so we can just do a + * raw binary copy. + */ + return TRUE; + } - /* Nothing to save. */ - return FALSE; + /* Nothing to save. */ + return FALSE; } /* @@ -4494,21 +4505,21 @@ cf_can_save(capture_file *cf) gboolean cf_can_save_as(capture_file *cf) { - if (wtap_dump_can_write(cf->linktypes, 0)) { - /* We can write it out with Wiretap. */ - return TRUE; - } + if (wtap_dump_can_write(cf->linktypes, 0)) { + /* We can write it out with Wiretap. */ + return TRUE; + } - if (cf->is_tempfile && !cf->unsaved_changes) { - /* - * Temporary file with no unsaved changes, so we can just do a - * raw binary copy. - */ - return TRUE; - } + if (cf->is_tempfile && !cf->unsaved_changes) { + /* + * Temporary file with no unsaved changes, so we can just do a + * raw binary copy. + */ + return TRUE; + } - /* Nothing to save. */ - return FALSE; + /* Nothing to save. */ + return FALSE; } /* @@ -4517,11 +4528,11 @@ cf_can_save_as(capture_file *cf) gboolean 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->count>0) || cf->unsaved_changes; + /* + * If this is a temporary file, or a file with unsaved changes, it + * has unsaved data. + */ + return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes; } /* @@ -4530,287 +4541,546 @@ cf_has_unsaved_data(capture_file *cf) static cf_read_status_t rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile) { - wtap_rec rec; - Buffer buf; - int err; - gchar *err_info; - gchar *name_ptr; - gint64 data_offset; - progdlg_t *progbar = NULL; - GTimer *prog_timer = g_timer_new(); - gint64 size; - float progbar_val; - gint64 start_time; - gchar status_str[100]; - guint32 framenum; - frame_data *fdata; - int count = 0; - - /* Close the old handle. */ - wtap_close(cf->provider.wth); - - /* Open the new file. */ - /* 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->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE); - if (cf->provider.wth == NULL) { - cfile_open_failure_alert_box(fname, err, err_info); - return CF_READ_ERROR; - } - - /* We're scanning a file whose contents should be the same as what - we had before, so we don't discard dissection state etc.. */ - cf->f_datalen = 0; - - /* Set the file name because we need it to set the follow stream filter. - XXX - is that still true? We need it for other reasons, though, - in any case. */ - cf->filename = g_strdup(fname); - - /* Indicate whether it's a permanent or temporary file. */ - cf->is_tempfile = is_tempfile; - - /* No user changes yet. */ - cf->unsaved_changes = FALSE; - - cf->cd_t = wtap_file_type_subtype(cf->provider.wth); - cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1); - - cf->snap = wtap_snapshot_length(cf->provider.wth); - - name_ptr = g_filename_display_basename(cf->filename); - - cf_callback_invoke(cf_cb_file_rescan_started, cf); - - /* Record the file's compression type. - XXX - do we know this at open time? */ - cf->compression_type = wtap_get_compression_type(cf->provider.wth); - - /* Find the size of the file. */ - size = wtap_file_size(cf->provider.wth, NULL); - - g_timer_start(prog_timer); - - cf->stop_flag = FALSE; - start_time = g_get_monotonic_time(); - - framenum = 0; - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); - while ((wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, - &data_offset))) { - framenum++; - fdata = frame_data_sequence_find(cf->provider.frames, framenum); - fdata->file_off = data_offset; - if (size >= 0) { - count++; - cf->f_datalen = wtap_read_so_far(cf->provider.wth); - - /* Create the progress bar if necessary. */ - if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) { - progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str)); - progbar = delayed_create_progress_dlg(cf->window, NULL, NULL, - TRUE, &cf->stop_flag, progbar_val); - } - - /* - * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL - * has elapsed. Calling update_progress_dlg and packets_bar_update will - * likely trigger UI paint events, which might take a while depending on - * the platform and display. Reset our timer *after* painting. - */ - if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { - 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 */ - update_progress_dlg(progbar, progbar_val, status_str); - compute_elapsed(cf, start_time); - packets_bar_update(); - g_timer_start(prog_timer); - } + wtap_rec rec; + Buffer buf; + int err; + gchar *err_info; + gchar *name_ptr; + gint64 data_offset; + progdlg_t *progbar = NULL; + GTimer *prog_timer = g_timer_new(); + gint64 size; + float progbar_val; + gint64 start_time; + gchar status_str[100]; + guint32 framenum; + frame_data *fdata; + int count = 0; + + /* Close the old handle. */ + wtap_close(cf->provider.wth); + + /* Open the new file. */ + /* 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->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE); + if (cf->provider.wth == NULL) { + cfile_open_failure_alert_box(fname, err, err_info); + return CF_READ_ERROR; + } + + /* We're scanning a file whose contents should be the same as what + we had before, so we don't discard dissection state etc.. */ + cf->f_datalen = 0; + + /* Set the file name because we need it to set the follow stream filter. + XXX - is that still true? We need it for other reasons, though, + in any case. */ + cf->filename = g_strdup(fname); + + /* Indicate whether it's a permanent or temporary file. */ + cf->is_tempfile = is_tempfile; + + /* No user changes yet. */ + cf->unsaved_changes = FALSE; + + cf->cd_t = wtap_file_type_subtype(cf->provider.wth); + cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1); + + cf->snap = wtap_snapshot_length(cf->provider.wth); + + name_ptr = g_filename_display_basename(cf->filename); + + cf_callback_invoke(cf_cb_file_rescan_started, cf); + + /* Record the file's compression type. + XXX - do we know this at open time? */ + cf->compression_type = wtap_get_compression_type(cf->provider.wth); + + /* Find the size of the file. */ + size = wtap_file_size(cf->provider.wth, NULL); + + g_timer_start(prog_timer); + + cf->stop_flag = FALSE; + start_time = g_get_monotonic_time(); + + framenum = 0; + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); + while ((wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, + &data_offset))) { + framenum++; + fdata = frame_data_sequence_find(cf->provider.frames, framenum); + fdata->file_off = data_offset; + if (size >= 0) { + count++; + cf->f_datalen = wtap_read_so_far(cf->provider.wth); + + /* Create the progress bar if necessary. */ + if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) { + progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str)); + progbar = delayed_create_progress_dlg(cf->window, NULL, NULL, + TRUE, &cf->stop_flag, progbar_val); + } + + /* + * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL + * has elapsed. Calling update_progress_dlg and packets_bar_update will + * likely trigger UI paint events, which might take a while depending on + * the platform and display. Reset our timer *after* painting. + */ + if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { + 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 */ + update_progress_dlg(progbar, progbar_val, status_str); + compute_elapsed(cf, start_time); + packets_bar_update(); + g_timer_start(prog_timer); + } + } + + 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. */ + break; + } + + /* Add this packet's link-layer encapsulation type to cf->linktypes, if + it's not already there. + XXX - yes, this is O(N), so if every packet had a different + link-layer encapsulation type, it'd be O(N^2) to read the file, but + there are probably going to be a small number of encapsulation types + in a file. */ + if (rec.rec_type == REC_TYPE_PACKET) { + cf_add_encapsulation_type(cf, rec.rec_header.packet_header.pkt_encap); + } } + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + + /* Free the display name */ + g_free(name_ptr); + + /* We're done reading the file; destroy the progress bar if it was created. */ + if (progbar != NULL) + destroy_progress_dlg(progbar); + g_timer_destroy(prog_timer); + + /* We're done reading sequentially through the file. */ + cf->state = FILE_READ_DONE; + + /* Close the sequential I/O side, to free up memory it requires. */ + wtap_sequential_close(cf->provider.wth); + + /* compute the time it took to load the file */ + compute_elapsed(cf, start_time); + + /* Set the file encapsulation type now; we don't know what it is until + we've looked at all the packets, as we don't know until then whether + there's more than one type (and thus whether it's + WTAP_ENCAP_PER_PACKET). */ + cf->lnk_t = wtap_file_encap(cf->provider.wth); + + cf_callback_invoke(cf_cb_file_rescan_finished, cf); 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. */ - break; + /* Our caller will give up at this point. */ + return CF_READ_ABORTED; } - /* Add this packet's link-layer encapsulation type to cf->linktypes, if - it's not already there. - XXX - yes, this is O(N), so if every packet had a different - link-layer encapsulation type, it'd be O(N^2) to read the file, but - there are probably going to be a small number of encapsulation types - in a file. */ - if (rec.rec_type == REC_TYPE_PACKET) { - cf_add_encapsulation_type(cf, rec.rec_header.packet_header.pkt_encap); - } - } - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - - /* Free the display name */ - g_free(name_ptr); - - /* We're done reading the file; destroy the progress bar if it was created. */ - if (progbar != NULL) - destroy_progress_dlg(progbar); - g_timer_destroy(prog_timer); - - /* We're done reading sequentially through the file. */ - cf->state = FILE_READ_DONE; - - /* Close the sequential I/O side, to free up memory it requires. */ - wtap_sequential_close(cf->provider.wth); - - /* compute the time it took to load the file */ - compute_elapsed(cf, start_time); - - /* Set the file encapsulation type now; we don't know what it is until - we've looked at all the packets, as we don't know until then whether - there's more than one type (and thus whether it's - WTAP_ENCAP_PER_PACKET). */ - cf->lnk_t = wtap_file_encap(cf->provider.wth); - - cf_callback_invoke(cf_cb_file_rescan_finished, cf); - - if (cf->stop_flag) { - /* Our caller will give up at this point. */ - return CF_READ_ABORTED; - } - - if (err != 0) { - /* Put up a message box noting that the read failed somewhere along - the line. Don't throw out the stuff we managed to read, though, - if any. */ - cfile_read_failure_alert_box(NULL, err, err_info); - return CF_READ_ERROR; - } else - return CF_READ_OK; + if (err != 0) { + /* Put up a message box noting that the read failed somewhere along + the line. Don't throw out the stuff we managed to read, though, + if any. */ + cfile_read_failure_alert_box(NULL, err, err_info); + return CF_READ_ERROR; + } else + return CF_READ_OK; } cf_write_status_t cf_save_records(capture_file *cf, const char *fname, guint save_format, - wtap_compression_type compression_type, - gboolean discard_comments, gboolean dont_reopen) + wtap_compression_type compression_type, + gboolean discard_comments, gboolean dont_reopen) { - gchar *err_info; - gchar *fname_new = NULL; - wtap_dumper *pdh; - frame_data *fdata; - addrinfo_lists_t *addr_lists; - guint framenum; - int err; + gchar *err_info; + gchar *fname_new = NULL; + wtap_dumper *pdh; + frame_data *fdata; + addrinfo_lists_t *addr_lists; + guint framenum; + int err; #ifdef _WIN32 - gchar *display_basename; + gchar *display_basename; #endif - enum { - SAVE_WITH_MOVE, - SAVE_WITH_COPY, - SAVE_WITH_WTAP - } how_to_save; - save_callback_args_t callback_args; - gboolean needs_reload = FALSE; - - /* XXX caller should avoid saving the file while a read is pending - * (e.g. by delaying the save action) */ - if (cf->read_lock) { - ws_warning("cf_save_records(\"%s\") while the file is being read, potential crash ahead", fname); - } - - cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname); - - addr_lists = get_addrinfo_list(); - - if (save_format == cf->cd_t && compression_type == cf->compression_type - && !discard_comments && !cf->unsaved_changes - && (wtap_addrinfo_list_empty(addr_lists) || wtap_file_type_subtype_supports_block(save_format, WTAP_BLOCK_NAME_RESOLUTION) == BLOCK_NOT_SUPPORTED)) { - /* We're saving in the format it's already in, and we're not discarding - comments, and there are no changes we have in memory that aren't saved - to the file, and we have no name resolution information to write or - the file format we're saving in doesn't support writing name - resolution information, so we can just move or copy the raw data. */ - - if (cf->is_tempfile) { - /* The file being saved is a temporary file from a live - capture, so it doesn't need to stay around under that name; - first, try renaming the capture buffer file to the new name. - This acts as a "safe save", in that, if the file already - exists, the existing file will be removed only if the rename - succeeds. - - Sadly, on Windows, as we have the current capture file - open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING - (to cause the rename to remove an existing target), as - done by ws_stdio_rename() (ws_rename() is #defined to - be ws_stdio_rename() on Windows) will fail. - - According to the MSDN documentation for CreateFile(), if, - when we open a capture file, we were to directly do a CreateFile(), - opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then - convert it to a file descriptor with _open_osfhandle(), - that would allow the file to be renamed out from under us. - - However, that doesn't work in practice. Perhaps the problem - is that the process doing the rename is the process that - has the file open. */ + enum { + SAVE_WITH_MOVE, + SAVE_WITH_COPY, + SAVE_WITH_WTAP + } how_to_save; + save_callback_args_t callback_args; + gboolean needs_reload = FALSE; + + /* XXX caller should avoid saving the file while a read is pending + * (e.g. by delaying the save action) */ + if (cf->read_lock) { + ws_warning("cf_save_records(\"%s\") while the file is being read, potential crash ahead", fname); + } + + cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname); + + addr_lists = get_addrinfo_list(); + + if (save_format == cf->cd_t && compression_type == cf->compression_type + && !discard_comments && !cf->unsaved_changes + && (wtap_addrinfo_list_empty(addr_lists) || wtap_file_type_subtype_supports_block(save_format, WTAP_BLOCK_NAME_RESOLUTION) == BLOCK_NOT_SUPPORTED)) { + /* We're saving in the format it's already in, and we're not discarding + comments, and there are no changes we have in memory that aren't saved + to the file, and we have no name resolution information to write or + the file format we're saving in doesn't support writing name + resolution information, so we can just move or copy the raw data. */ + + if (cf->is_tempfile) { + /* The file being saved is a temporary file from a live + capture, so it doesn't need to stay around under that name; + first, try renaming the capture buffer file to the new name. + This acts as a "safe save", in that, if the file already + exists, the existing file will be removed only if the rename + succeeds. + + Sadly, on Windows, as we have the current capture file + open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING + (to cause the rename to remove an existing target), as + done by ws_stdio_rename() (ws_rename() is #defined to + be ws_stdio_rename() on Windows) will fail. + + According to the MSDN documentation for CreateFile(), if, + when we open a capture file, we were to directly do a CreateFile(), + opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then + convert it to a file descriptor with _open_osfhandle(), + that would allow the file to be renamed out from under us. + + However, that doesn't work in practice. Perhaps the problem + is that the process doing the rename is the process that + has the file open. */ #ifndef _WIN32 - if (ws_rename(cf->filename, fname) == 0) { - /* That succeeded - there's no need to copy the source file. */ - how_to_save = SAVE_WITH_MOVE; - } else { - if (errno == EXDEV) { - /* They're on different file systems, so we have to copy the - file. */ - how_to_save = SAVE_WITH_COPY; - } else { - /* The rename failed, but not because they're on different - file systems - put up an error message. (Or should we - just punt and try to copy? The only reason why I'd - expect the rename to fail and the copy to succeed would - be if we didn't have permission to remove the file from - the temporary directory, and that might be fixable - but - is it worth requiring the user to go off and fix it?) */ - cf_rename_failure_alert_box(fname, errno); - goto fail; - } - } + if (ws_rename(cf->filename, fname) == 0) { + /* That succeeded - there's no need to copy the source file. */ + how_to_save = SAVE_WITH_MOVE; + } else { + if (errno == EXDEV) { + /* They're on different file systems, so we have to copy the + file. */ + how_to_save = SAVE_WITH_COPY; + } else { + /* The rename failed, but not because they're on different + file systems - put up an error message. (Or should we + just punt and try to copy? The only reason why I'd + expect the rename to fail and the copy to succeed would + be if we didn't have permission to remove the file from + the temporary directory, and that might be fixable - but + is it worth requiring the user to go off and fix it?) */ + cf_rename_failure_alert_box(fname, errno); + goto fail; + } + } #else - /* Windows - copy the file to its new location. */ - how_to_save = SAVE_WITH_COPY; + /* Windows - copy the file to its new location. */ + how_to_save = SAVE_WITH_COPY; #endif + } else { + /* It's a permanent file, so we should copy it, and not remove the + original. */ + how_to_save = SAVE_WITH_COPY; + } + + if (how_to_save == SAVE_WITH_COPY) { + /* Copy the file, if we haven't moved it. If we're overwriting + an existing file, we do it with a "safe save", by writing + to a new file and, if the write succeeds, renaming the + new file on top of the old file. */ + if (file_exists(fname)) { + fname_new = ws_strdup_printf("%s~", fname); + if (!copy_file_binary_mode(cf->filename, fname_new)) + goto fail; + } else { + if (!copy_file_binary_mode(cf->filename, fname)) + goto fail; + } + } } else { - /* It's a permanent file, so we should copy it, and not remove the - original. */ - how_to_save = SAVE_WITH_COPY; + /* Either we're saving in a different format or we're saving changes, + such as added, modified, or removed comments, that haven't yet + been written to the underlying file; we can't do that by copying + or moving the capture file, we have to do it by writing the packets + out in Wiretap. */ + + wtap_dump_params params; + int encap; + + /* XXX: what free's params.shb_hdr? */ + wtap_dump_params_init(¶ms, cf->provider.wth); + + /* Determine what file encapsulation type we should use. */ + encap = wtap_dump_file_encap_type(cf->linktypes); + params.encap = encap; + + /* Use the snaplen from cf (XXX - does wtap_dump_params_init handle that?) */ + params.snaplen = cf->snap; + + if (file_exists(fname)) { + /* We're overwriting an existing file; write out to a new file, + and, if that succeeds, rename the new file on top of the + old file. That makes this a "safe save", so that we don't + lose the old file if we have a problem writing out the new + file. (If the existing file is the current capture file, + we *HAVE* to do that, otherwise we're overwriting the file + from which we're reading the packets that we're writing!) */ + fname_new = ws_strdup_printf("%s~", fname); + pdh = wtap_dump_open(fname_new, save_format, compression_type, ¶ms, + &err, &err_info); + } else { + pdh = wtap_dump_open(fname, save_format, compression_type, ¶ms, + &err, &err_info); + } + /* XXX idb_inf is documented to be used until wtap_dump_close. */ + g_free(params.idb_inf); + params.idb_inf = NULL; + + if (pdh == NULL) { + cfile_dump_open_failure_alert_box(fname, err, err_info, save_format); + goto fail; + } + + /* Add address resolution */ + wtap_dump_set_addrinfo_list(pdh, addr_lists); + + /* Iterate through the list of packets, processing all the packets. */ + callback_args.pdh = pdh; + callback_args.fname = fname; + callback_args.file_type = save_format; + switch (process_specified_records(cf, NULL, "Saving", "packets", + TRUE, save_record, &callback_args, TRUE)) { + + case PSP_FINISHED: + /* Completed successfully. */ + break; + + case PSP_STOPPED: + /* The user decided to abort the saving. + If we're writing to a temporary file, remove it. + XXX - should we do so even if we're not writing to a + temporary file? */ + wtap_dump_close(pdh, &err, &err_info); + if (fname_new != NULL) + ws_unlink(fname_new); + cf_callback_invoke(cf_cb_file_save_stopped, NULL); + return CF_WRITE_ABORTED; + + case PSP_FAILED: + /* Error while saving. + If we're writing to a temporary file, remove it. */ + if (fname_new != NULL) + ws_unlink(fname_new); + wtap_dump_close(pdh, &err, &err_info); + goto fail; + } + + needs_reload = wtap_dump_get_needs_reload(pdh); + + if (!wtap_dump_close(pdh, &err, &err_info)) { + cfile_close_failure_alert_box(fname, err, err_info); + goto fail; + } + + how_to_save = SAVE_WITH_WTAP; } - if (how_to_save == SAVE_WITH_COPY) { - /* Copy the file, if we haven't moved it. If we're overwriting - an existing file, we do it with a "safe save", by writing - to a new file and, if the write succeeds, renaming the - new file on top of the old file. */ - if (file_exists(fname)) { - fname_new = ws_strdup_printf("%s~", fname); - if (!copy_file_binary_mode(cf->filename, fname_new)) - goto fail; - } else { - if (!copy_file_binary_mode(cf->filename, fname)) - goto fail; - } - } - } else { - /* Either we're saving in a different format or we're saving changes, - such as added, modified, or removed comments, that haven't yet - been written to the underlying file; we can't do that by copying - or moving the capture file, we have to do it by writing the packets - out in Wiretap. */ - - wtap_dump_params params; - int encap; + if (fname_new != NULL) { + /* We wrote out to fname_new, and should rename it on top of + fname. fname_new is now closed, so that should be possible even + on Windows. However, on Windows, we first need to close whatever + file descriptors we have open for fname. */ +#ifdef _WIN32 + wtap_fdclose(cf->provider.wth); +#endif + /* Now do the rename. */ + if (ws_rename(fname_new, fname) == -1) { + /* Well, the rename failed. */ + cf_rename_failure_alert_box(fname, errno); +#ifdef _WIN32 + /* Attempt to reopen the random file descriptor using the + current file's filename. (At this point, the sequential + file descriptor is closed.) */ + if (!wtap_fdreopen(cf->provider.wth, cf->filename, &err)) { + /* Oh, well, we're screwed. */ + display_basename = g_filename_display_basename(cf->filename); + simple_error_message_box( + file_open_error_message(err, FALSE), display_basename); + g_free(display_basename); + } +#endif + goto fail; + } + } + + /* If this was a temporary file, and we didn't do the save by doing + a move, so the tempoary file is still around under its old name, + remove it. */ + if (cf->is_tempfile && how_to_save != SAVE_WITH_MOVE) { + /* If this fails, there's not much we can do, so just ignore errors. */ + ws_unlink(cf->filename); + } + + cf_callback_invoke(cf_cb_file_save_finished, NULL); + cf->unsaved_changes = FALSE; + + if (!dont_reopen) { + switch (how_to_save) { + + case SAVE_WITH_MOVE: + /* We just moved the file, so the wtap structure refers to the + new file, and all the information other than the filename + and the "is temporary" status applies to the new file; just + update that. */ + g_free(cf->filename); + cf->filename = g_strdup(fname); + cf->is_tempfile = FALSE; + cf_callback_invoke(cf_cb_file_fast_save_finished, cf); + break; + + case SAVE_WITH_COPY: + /* We just copied the file, so all the information other than + the wtap structure, the filename, and the "is temporary" + status applies to the new file; just update that. */ + wtap_close(cf->provider.wth); + /* 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->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE); + if (cf->provider.wth == NULL) { + cfile_open_failure_alert_box(fname, err, err_info); + cf_close(cf); + } else { + g_free(cf->filename); + cf->filename = g_strdup(fname); + cf->is_tempfile = FALSE; + } + cf_callback_invoke(cf_cb_file_fast_save_finished, cf); + break; + + case SAVE_WITH_WTAP: + /* Open and read the file we saved to. + + XXX - this is somewhat of a waste; we already have the + packets, all this gets us is updated file type information + (which we could just stuff into "cf"), and having the new + file be the one we have opened and from which we're reading + the data, and it means we have to spend time opening and + reading the file, which could be a significant amount of + time if the file is large. + + If the capture-file-writing code were to return the + seek offset of each packet it writes, we could save that + in the frame_data structure for the frame, and just open + the file without reading it again... + + ...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; + /* There are cases when SAVE_WITH_WTAP can result in new packets + being written to the file, e.g ERF records + In that case, we need to reload the whole file */ + if(needs_reload) { + if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) { + if (cf_read(cf, TRUE) != CF_READ_OK) { + /* The rescan failed; just close the file. Either + a dialog was popped up for the failure, so the + user knows what happened, or they stopped the + rescan, in which case they know what happened. */ + /* XXX: This is inconsistent with normal open/reload behaviour. */ + cf_close(cf); + } + } + } + else { + if (rescan_file(cf, fname, FALSE) != CF_READ_OK) { + /* The rescan failed; just close the file. Either + a dialog was popped up for the failure, so the + user knows what happened, or they stopped the + rescan, in which case they know what happened. */ + cf_close(cf); + } + } + break; + } + + /* If we were told to discard the comments, do so. */ + if (discard_comments) { + /* Remove SHB comment, if any. */ + wtap_write_shb_comment(cf->provider.wth, NULL); + + /* remove all user comments */ + for (framenum = 1; framenum <= cf->count; framenum++) { + fdata = frame_data_sequence_find(cf->provider.frames, framenum); + + // XXX: This also ignores non-comment options like verdict + fdata->has_modified_block = FALSE; + } + + if (cf->provider.frames_modified_blocks) { + g_tree_destroy(cf->provider.frames_modified_blocks); + cf->provider.frames_modified_blocks = NULL; + } + + cf->packet_comment_count = 0; + } + } + return CF_WRITE_OK; + +fail: + if (fname_new != NULL) { + /* We were trying to write to a temporary file; get rid of it if it + exists. (We don't care whether this fails, as, if it fails, + there's not much we can do about it. I guess if it failed for + a reason other than "it doesn't exist", we could report an + error, so the user knows there's a junk file that they might + want to clean up.) */ + ws_unlink(fname_new); + g_free(fname_new); + } + cf_callback_invoke(cf_cb_file_save_failed, NULL); + return CF_WRITE_ERROR; +} + +cf_write_status_t +cf_export_specified_packets(capture_file *cf, const char *fname, + packet_range_t *range, guint save_format, + wtap_compression_type compression_type) +{ + gchar *fname_new = NULL; + int err; + gchar *err_info; + wtap_dumper *pdh; + save_callback_args_t callback_args; + wtap_dump_params params; + int encap; + + packet_range_process_init(range); + + /* We're writing out specified packets from the specified capture + file to another file. Even if all captured packets are to be + written, don't special-case the operation - read each packet + and then write it out if it's one of the specified ones. */ /* XXX: what free's params.shb_hdr? */ wtap_dump_params_init(¶ms, cf->provider.wth); @@ -4823,362 +5093,103 @@ cf_save_records(capture_file *cf, const char *fname, guint save_format, params.snaplen = cf->snap; if (file_exists(fname)) { - /* We're overwriting an existing file; write out to a new file, - and, if that succeeds, rename the new file on top of the - old file. That makes this a "safe save", so that we don't - lose the old file if we have a problem writing out the new - file. (If the existing file is the current capture file, - we *HAVE* to do that, otherwise we're overwriting the file - from which we're reading the packets that we're writing!) */ - fname_new = ws_strdup_printf("%s~", fname); - pdh = wtap_dump_open(fname_new, save_format, compression_type, ¶ms, - &err, &err_info); + /* We're overwriting an existing file; write out to a new file, + and, if that succeeds, rename the new file on top of the + old file. That makes this a "safe save", so that we don't + lose the old file if we have a problem writing out the new + file. (If the existing file is the current capture file, + we *HAVE* to do that, otherwise we're overwriting the file + from which we're reading the packets that we're writing!) */ + fname_new = ws_strdup_printf("%s~", fname); + pdh = wtap_dump_open(fname_new, save_format, compression_type, ¶ms, + &err, &err_info); } else { - pdh = wtap_dump_open(fname, save_format, compression_type, ¶ms, - &err, &err_info); + pdh = wtap_dump_open(fname, save_format, compression_type, ¶ms, + &err, &err_info); } /* XXX idb_inf is documented to be used until wtap_dump_close. */ g_free(params.idb_inf); params.idb_inf = NULL; if (pdh == NULL) { - cfile_dump_open_failure_alert_box(fname, err, err_info, save_format); - goto fail; + cfile_dump_open_failure_alert_box(fname, err, err_info, save_format); + goto fail; } /* Add address resolution */ - wtap_dump_set_addrinfo_list(pdh, addr_lists); + wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list()); - /* Iterate through the list of packets, processing all the packets. */ + /* Iterate through the list of packets, processing the packets we were + told to process. + + XXX - we've already called "packet_range_process_init(range)", but + "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_records(cf, NULL, "Saving", "packets", - TRUE, save_record, &callback_args, TRUE)) { - - case PSP_FINISHED: - /* Completed successfully. */ - break; - - case PSP_STOPPED: - /* The user decided to abort the saving. - If we're writing to a temporary file, remove it. - XXX - should we do so even if we're not writing to a - temporary file? */ - wtap_dump_close(pdh, &err, &err_info); - if (fname_new != NULL) - ws_unlink(fname_new); - cf_callback_invoke(cf_cb_file_save_stopped, NULL); - return CF_WRITE_ABORTED; + switch (process_specified_records(cf, range, "Writing", "specified records", + TRUE, save_record, &callback_args, TRUE)) { - case PSP_FAILED: - /* Error while saving. - If we're writing to a temporary file, remove it. */ - if (fname_new != NULL) - ws_unlink(fname_new); - wtap_dump_close(pdh, &err, &err_info); - goto fail; - } + case PSP_FINISHED: + /* Completed successfully. */ + break; - needs_reload = wtap_dump_get_needs_reload(pdh); + case PSP_STOPPED: + /* The user decided to abort the saving. + If we're writing to a temporary file, remove it. + XXX - should we do so even if we're not writing to a + temporary file? */ + wtap_dump_close(pdh, &err, &err_info); + if (fname_new != NULL) { + ws_unlink(fname_new); + g_free(fname_new); + } + return CF_WRITE_ABORTED; + break; - if (!wtap_dump_close(pdh, &err, &err_info)) { - cfile_close_failure_alert_box(fname, err, err_info); - goto fail; + case PSP_FAILED: + /* Error while saving. */ + wtap_dump_close(pdh, &err, &err_info); + /* + * We don't report any error from closing; the error that caused + * process_specified_records() to fail has already been reported. + */ + goto fail; } - how_to_save = SAVE_WITH_WTAP; - } + if (!wtap_dump_close(pdh, &err, &err_info)) { + cfile_close_failure_alert_box(fname, err, err_info); + goto fail; + } - if (fname_new != NULL) { - /* We wrote out to fname_new, and should rename it on top of - fname. fname_new is now closed, so that should be possible even - on Windows. However, on Windows, we first need to close whatever - file descriptors we have open for fname. */ -#ifdef _WIN32 - wtap_fdclose(cf->provider.wth); -#endif - /* Now do the rename. */ - if (ws_rename(fname_new, fname) == -1) { - /* Well, the rename failed. */ - cf_rename_failure_alert_box(fname, errno); -#ifdef _WIN32 - /* Attempt to reopen the random file descriptor using the - current file's filename. (At this point, the sequential - file descriptor is closed.) */ - if (!wtap_fdreopen(cf->provider.wth, cf->filename, &err)) { - /* Oh, well, we're screwed. */ - display_basename = g_filename_display_basename(cf->filename); - simple_error_message_box( - file_open_error_message(err, FALSE), display_basename); - g_free(display_basename); - } -#endif - goto fail; - } - } - - /* If this was a temporary file, and we didn't do the save by doing - a move, so the tempoary file is still around under its old name, - remove it. */ - if (cf->is_tempfile && how_to_save != SAVE_WITH_MOVE) { - /* If this fails, there's not much we can do, so just ignore errors. */ - ws_unlink(cf->filename); - } - - cf_callback_invoke(cf_cb_file_save_finished, NULL); - cf->unsaved_changes = FALSE; - - if (!dont_reopen) { - switch (how_to_save) { - - case SAVE_WITH_MOVE: - /* We just moved the file, so the wtap structure refers to the - new file, and all the information other than the filename - and the "is temporary" status applies to the new file; just - update that. */ - g_free(cf->filename); - cf->filename = g_strdup(fname); - cf->is_tempfile = FALSE; - cf_callback_invoke(cf_cb_file_fast_save_finished, cf); - break; - - case SAVE_WITH_COPY: - /* We just copied the file, so all the information other than - the wtap structure, the filename, and the "is temporary" - status applies to the new file; just update that. */ - wtap_close(cf->provider.wth); - /* 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->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE); - if (cf->provider.wth == NULL) { - cfile_open_failure_alert_box(fname, err, err_info); - cf_close(cf); - } else { - g_free(cf->filename); - cf->filename = g_strdup(fname); - cf->is_tempfile = FALSE; - } - cf_callback_invoke(cf_cb_file_fast_save_finished, cf); - break; - - case SAVE_WITH_WTAP: - /* Open and read the file we saved to. - - XXX - this is somewhat of a waste; we already have the - packets, all this gets us is updated file type information - (which we could just stuff into "cf"), and having the new - file be the one we have opened and from which we're reading - the data, and it means we have to spend time opening and - reading the file, which could be a significant amount of - time if the file is large. - - If the capture-file-writing code were to return the - seek offset of each packet it writes, we could save that - in the frame_data structure for the frame, and just open - the file without reading it again... - - ...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; - /* There are cases when SAVE_WITH_WTAP can result in new packets - being written to the file, e.g ERF records - In that case, we need to reload the whole file */ - if(needs_reload) { - if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) { - if (cf_read(cf, TRUE) != CF_READ_OK) { - /* The rescan failed; just close the file. Either - a dialog was popped up for the failure, so the - user knows what happened, or they stopped the - rescan, in which case they know what happened. */ - /* XXX: This is inconsistent with normal open/reload behaviour. */ - cf_close(cf); - } + if (fname_new != NULL) { + /* We wrote out to fname_new, and should rename it on top of + fname; fname is now closed, so that should be possible even + on Windows. Do the rename. */ + if (ws_rename(fname_new, fname) == -1) { + /* Well, the rename failed. */ + cf_rename_failure_alert_box(fname, errno); + goto fail; } - } - else { - if (rescan_file(cf, fname, FALSE) != CF_READ_OK) { - /* The rescan failed; just close the file. Either - a dialog was popped up for the failure, so the - user knows what happened, or they stopped the - rescan, in which case they know what happened. */ - cf_close(cf); - } - } - break; + g_free(fname_new); } - /* If we were told to discard the comments, do so. */ - if (discard_comments) { - /* Remove SHB comment, if any. */ - wtap_write_shb_comment(cf->provider.wth, NULL); - - /* remove all user comments */ - for (framenum = 1; framenum <= cf->count; framenum++) { - fdata = frame_data_sequence_find(cf->provider.frames, framenum); - - // XXX: This also ignores non-comment options like verdict - fdata->has_modified_block = FALSE; - } - - if (cf->provider.frames_modified_blocks) { - g_tree_destroy(cf->provider.frames_modified_blocks); - cf->provider.frames_modified_blocks = NULL; - } - - cf->packet_comment_count = 0; - } - } - return CF_WRITE_OK; + return CF_WRITE_OK; fail: - if (fname_new != NULL) { - /* We were trying to write to a temporary file; get rid of it if it - exists. (We don't care whether this fails, as, if it fails, - there's not much we can do about it. I guess if it failed for - a reason other than "it doesn't exist", we could report an - error, so the user knows there's a junk file that they might - want to clean up.) */ - ws_unlink(fname_new); - g_free(fname_new); - } - cf_callback_invoke(cf_cb_file_save_failed, NULL); - return CF_WRITE_ERROR; -} - -cf_write_status_t -cf_export_specified_packets(capture_file *cf, const char *fname, - packet_range_t *range, guint save_format, - wtap_compression_type compression_type) -{ - gchar *fname_new = NULL; - int err; - gchar *err_info; - wtap_dumper *pdh; - save_callback_args_t callback_args; - wtap_dump_params params; - int encap; - - packet_range_process_init(range); - - /* We're writing out specified packets from the specified capture - file to another file. Even if all captured packets are to be - written, don't special-case the operation - read each packet - and then write it out if it's one of the specified ones. */ - - /* XXX: what free's params.shb_hdr? */ - wtap_dump_params_init(¶ms, cf->provider.wth); - - /* Determine what file encapsulation type we should use. */ - encap = wtap_dump_file_encap_type(cf->linktypes); - params.encap = encap; - - /* Use the snaplen from cf (XXX - does wtap_dump_params_init handle that?) */ - params.snaplen = cf->snap; - - if (file_exists(fname)) { - /* We're overwriting an existing file; write out to a new file, - and, if that succeeds, rename the new file on top of the - old file. That makes this a "safe save", so that we don't - lose the old file if we have a problem writing out the new - file. (If the existing file is the current capture file, - we *HAVE* to do that, otherwise we're overwriting the file - from which we're reading the packets that we're writing!) */ - fname_new = ws_strdup_printf("%s~", fname); - pdh = wtap_dump_open(fname_new, save_format, compression_type, ¶ms, - &err, &err_info); - } else { - pdh = wtap_dump_open(fname, save_format, compression_type, ¶ms, - &err, &err_info); - } - /* XXX idb_inf is documented to be used until wtap_dump_close. */ - g_free(params.idb_inf); - params.idb_inf = NULL; - - if (pdh == NULL) { - cfile_dump_open_failure_alert_box(fname, err, err_info, save_format); - goto fail; - } - - /* Add address resolution */ - wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list()); - - /* Iterate through the list of packets, processing the packets we were - told to process. - - XXX - we've already called "packet_range_process_init(range)", but - "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_records(cf, range, "Writing", "specified records", - TRUE, save_record, &callback_args, TRUE)) { - - case PSP_FINISHED: - /* Completed successfully. */ - break; - - case PSP_STOPPED: - /* The user decided to abort the saving. - If we're writing to a temporary file, remove it. - XXX - should we do so even if we're not writing to a - temporary file? */ - wtap_dump_close(pdh, &err, &err_info); - if (fname_new != NULL) { + if (fname_new != NULL) { + /* We were trying to write to a temporary file; get rid of it if it + exists. (We don't care whether this fails, as, if it fails, + there's not much we can do about it. I guess if it failed for + a reason other than "it doesn't exist", we could report an + error, so the user knows there's a junk file that they might + want to clean up.) */ ws_unlink(fname_new); g_free(fname_new); - } - return CF_WRITE_ABORTED; - break; - - case PSP_FAILED: - /* Error while saving. */ - wtap_dump_close(pdh, &err, &err_info); - /* - * We don't report any error from closing; the error that caused - * process_specified_records() to fail has already been reported. - */ - goto fail; - } - - if (!wtap_dump_close(pdh, &err, &err_info)) { - cfile_close_failure_alert_box(fname, err, err_info); - goto fail; - } - - if (fname_new != NULL) { - /* We wrote out to fname_new, and should rename it on top of - fname; fname is now closed, so that should be possible even - on Windows. Do the rename. */ - if (ws_rename(fname_new, fname) == -1) { - /* Well, the rename failed. */ - cf_rename_failure_alert_box(fname, errno); - goto fail; } - g_free(fname_new); - } - - return CF_WRITE_OK; - -fail: - if (fname_new != NULL) { - /* We were trying to write to a temporary file; get rid of it if it - exists. (We don't care whether this fails, as, if it fails, - there's not much we can do about it. I guess if it failed for - a reason other than "it doesn't exist", we could report an - error, so the user knows there's a junk file that they might - want to clean up.) */ - ws_unlink(fname_new); - g_free(fname_new); - } - return CF_WRITE_ERROR; + return CF_WRITE_ERROR; } /* @@ -5189,102 +5200,90 @@ fail: static void cf_rename_failure_alert_box(const char *filename, int err) { - gchar *display_basename; - - display_basename = g_filename_display_basename(filename); - switch (err) { - - case ENOENT: - /* XXX - should check whether the source exists and, if not, - report it as the problem and, if so, report the destination - as the problem. */ - simple_error_message_box("The path to the file \"%s\" doesn't exist.", - display_basename); - break; - - case EACCES: - /* XXX - if we're doing a rename after a safe save, we should - probably say something else. */ - simple_error_message_box("You don't have permission to move the capture file to \"%s\".", - display_basename); - break; - - default: - /* XXX - this should probably mention both the source and destination - pathnames. */ - simple_error_message_box("The file \"%s\" could not be moved: %s.", - display_basename, wtap_strerror(err)); - break; - } - g_free(display_basename); + gchar *display_basename; + + display_basename = g_filename_display_basename(filename); + switch (err) { + + case ENOENT: + /* XXX - should check whether the source exists and, if not, + report it as the problem and, if so, report the destination + as the problem. */ + simple_error_message_box("The path to the file \"%s\" doesn't exist.", + display_basename); + break; + + case EACCES: + /* XXX - if we're doing a rename after a safe save, we should + probably say something else. */ + simple_error_message_box("You don't have permission to move the capture file to \"%s\".", + display_basename); + break; + + default: + /* XXX - this should probably mention both the source and destination + pathnames. */ + simple_error_message_box("The file \"%s\" could not be moved: %s.", + display_basename, wtap_strerror(err)); + break; + } + g_free(display_basename); } /* Reload the current capture file. */ cf_status_t -cf_reload(capture_file *cf) { - gchar *filename; - gboolean is_tempfile; - cf_status_t cf_status = CF_OK; - int err; - - if (cf->read_lock) { - ws_warning("Failing cf_reload(\"%s\") since a read is in progress", cf->filename); - return CF_ERROR; - } - - /* If the file could be opened, "cf_open()" calls "cf_close()" - to get rid of state for the old capture file before filling in state - for the new capture file. "cf_close()" will remove the file if - it's a temporary file; we don't want that to happen (for one thing, - it'd prevent subsequent reopens from working). Remember whether it's - a temporary file, mark it as not being a temporary file, and then - reopen it as the type of file it was. - - Also, "cf_close()" will free "cf->filename", so we must make - a copy of it first. */ - filename = g_strdup(cf->filename); - is_tempfile = cf->is_tempfile; - cf->is_tempfile = FALSE; - if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) { - switch (cf_read(cf, TRUE)) { - - case CF_READ_OK: - case CF_READ_ERROR: - /* Just because we got an error, that doesn't mean we were unable - to read any of the file; we handle what we could get from the - file. */ - break; - - case CF_READ_ABORTED: - /* The user bailed out of re-reading the capture file; the - capture file has been closed. */ - break; - } - } else { - /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile". - Instead, the file was left open, so we should restore "cf->is_tempfile" - ourselves. - - XXX - change the menu? Presumably "cf_open()" will do that; - make sure it does! */ - cf->is_tempfile = is_tempfile; - cf_status = CF_ERROR; - } - /* "cf_open()" made a copy of the file name we handed it, so - we should free up our copy. */ - g_free(filename); - return cf_status; -} +cf_reload(capture_file *cf) +{ + gchar *filename; + gboolean is_tempfile; + cf_status_t cf_status = CF_OK; + int err; -/* - * Editor modelines - * - * Local Variables: - * c-basic-offset: 2 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * ex: set shiftwidth=2 tabstop=8 expandtab: - * :indentSize=2:tabSize=8:noTabs=true: - */ + if (cf->read_lock) { + ws_warning("Failing cf_reload(\"%s\") since a read is in progress", cf->filename); + return CF_ERROR; + } + + /* If the file could be opened, "cf_open()" calls "cf_close()" + to get rid of state for the old capture file before filling in state + for the new capture file. "cf_close()" will remove the file if + it's a temporary file; we don't want that to happen (for one thing, + it'd prevent subsequent reopens from working). Remember whether it's + a temporary file, mark it as not being a temporary file, and then + reopen it as the type of file it was. + + Also, "cf_close()" will free "cf->filename", so we must make + a copy of it first. */ + filename = g_strdup(cf->filename); + is_tempfile = cf->is_tempfile; + cf->is_tempfile = FALSE; + if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) { + switch (cf_read(cf, TRUE)) { + + case CF_READ_OK: + case CF_READ_ERROR: + /* Just because we got an error, that doesn't mean we were unable + to read any of the file; we handle what we could get from the + file. */ + break; + + case CF_READ_ABORTED: + /* The user bailed out of re-reading the capture file; the + capture file has been closed. */ + break; + } + } else { + /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile". + Instead, the file was left open, so we should restore "cf->is_tempfile" + ourselves. + + XXX - change the menu? Presumably "cf_open()" will do that; + make sure it does! */ + cf->is_tempfile = is_tempfile; + cf_status = CF_ERROR; + } + /* "cf_open()" made a copy of the file name we handed it, so + we should free up our copy. */ + g_free(filename); + return cf_status; +} -- cgit v1.2.3