/* file.c
* File I/O routines
*
- * $Id: file.c,v 1.233 2001/03/23 14:43:59 jfoster Exp $
+ * $Id: file.c,v 1.270 2002/04/24 05:48:43 guy Exp $
*
* Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
- *
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
# include <netinet/in.h>
#endif
-#include <epan.h>
+#include <epan/epan.h>
+#include <epan/filesystem.h>
#include "gtk/main.h"
#include "color.h"
#include "gtk/color_utils.h"
#include "column.h"
-#include "packet.h"
+#include <epan/packet.h>
#include "print.h"
#include "file.h"
#include "menu.h"
#include "util.h"
#include "simple_dialog.h"
+#include "progress_dlg.h"
#include "ui_util.h"
+#include "statusbar.h"
#include "prefs.h"
#include "gtk/proto_draw.h"
-#include "dfilter/dfilter.h"
-#include "conversation.h"
+#include "gtk/packet_win.h"
+#include <epan/dfilter/dfilter.h>
+#include <epan/conversation.h>
#include "globals.h"
#include "gtk/colors.h"
+#include <epan/epan_dissect.h>
-extern GtkWidget *packet_list, *info_bar, *byte_nb_ptr, *tree_view;
-extern guint file_ctx;
+extern GtkWidget *packet_list, *byte_nb_ptr, *tree_view;
-gboolean auto_scroll_live = FALSE;
+#ifdef HAVE_LIBPCAP
+gboolean auto_scroll_live;
+#endif
static guint32 firstsec, firstusec;
static guint32 prevsec, prevusec;
-static void read_packet(capture_file *cf, int offset);
+static void read_packet(capture_file *cf, long offset);
static void rescan_packets(capture_file *cf, const char *action,
gboolean refilter, gboolean redissect);
{
wtap *wth;
int err;
- FILE_T fh;
int fd;
struct stat cf_stat;
goto fail;
/* Find the size of the file. */
- fh = wtap_file(wth);
fd = wtap_fd(wth);
if (fstat(fd, &cf_stat) < 0) {
err = errno;
/* The open succeeded. Close whatever capture file we had open,
and fill in the information for this file. */
- close_cap_file(cf, info_bar);
+ close_cap_file(cf);
- /* Initialize the table of conversations. */
- epan_conversation_init();
-
- /* Initialize protocol-specific variables */
- init_all_protocols();
+ /* Initialize all data structures used for dissection. */
+ init_dissection();
/* We're about to start reading the file. */
cf->state = FILE_READ_IN_PROGRESS;
cf->cd_t = wtap_file_type(cf->wth);
cf->count = 0;
+ cf->marked_count = 0;
cf->drops_known = FALSE;
cf->drops = 0;
cf->esec = 0;
cf->eusec = 0;
cf->snap = wtap_snapshot_length(cf->wth);
+ if (cf->snap == 0) {
+ /* Snapshot length not known. */
+ cf->has_snap = FALSE;
+ cf->snap = WTAP_MAX_PACKET_SIZE;
+ } else
+ cf->has_snap = TRUE;
cf->progbar_quantum = 0;
cf->progbar_nextstep = 0;
firstsec = 0, firstusec = 0;
/* Reset everything to a pristine state */
void
-close_cap_file(capture_file *cf, void *w)
+close_cap_file(capture_file *cf)
{
/* Die if we're in the middle of reading a file. */
g_assert(cf->state != FILE_READ_IN_PROGRESS);
/* Clear any file-related status bar messages.
XXX - should be "clear *ALL* file-related status bar messages;
will there ever be more than one on the stack? */
- gtk_statusbar_pop(GTK_STATUSBAR(w), file_ctx);
+ statusbar_pop_file_msg();
/* Restore the standard title bar message. */
set_main_window_name("The Ethereal Network Analyzer");
done_msg = g_malloc(msg_len);
snprintf(done_msg, msg_len, done_fmt_nodrops, name_ptr);
}
- gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
+ statusbar_push_file_msg(done_msg);
g_free(done_msg);
msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
read_status_t
read_cap_file(capture_file *cf, int *err)
{
- gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
- size_t msg_len;
- char *errmsg;
- char errmsg_errno[1024+1];
- gchar err_str[2048+1];
- int data_offset;
- progdlg_t *progbar;
- gboolean stop_flag;
- int file_pos;
- float prog_val;
+ gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
+ size_t msg_len;
+ char *errmsg;
+ char errmsg_errno[1024+1];
+ gchar err_str[2048+1];
+ long data_offset;
+ progdlg_t *progbar;
+ gboolean stop_flag;
+ int file_pos;
+ float prog_val;
+ int fd;
+ struct stat cf_stat;
name_ptr = get_basename(cf->filename);
msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
load_msg = g_malloc(msg_len);
snprintf(load_msg, msg_len, load_fmt, name_ptr);
- gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
+ statusbar_push_file_msg(load_msg);
/* Update the progress bar when it gets to this value. */
cf->progbar_nextstep = 0;
if (data_offset >= cf->progbar_nextstep) {
file_pos = lseek(cf->filed, 0, SEEK_CUR);
prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
+ if (prog_val > 1.0) {
+ /* The file probably grew while we were reading it.
+ Update "cf->f_len", and try again. */
+ fd = wtap_fd(cf->wth);
+ if (fstat(fd, &cf_stat) >= 0) {
+ cf->f_len = cf_stat.st_size;
+ prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
+ }
+ /* If it's still > 1, either the "fstat()" 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 (prog_val > 1.0)
+ prog_val = 1.0;
+ }
update_progress_dlg(progbar, prog_val);
cf->progbar_nextstep += cf->progbar_quantum;
}
destroy_progress_dlg(progbar);
cf->state = FILE_READ_ABORTED; /* so that we're allowed to close it */
gtk_clist_thaw(GTK_CLIST(packet_list)); /* undo our freeze */
- close_cap_file(cf, info_bar);
+ close_cap_file(cf);
return (READ_ABORTED);
}
read_packet(cf, data_offset);
/* Close the sequential I/O side, to free up memory it requires. */
wtap_sequential_close(cf->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();
+
/* 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
cf->current_frame = cf->first_displayed;
thaw_clist(cf);
- gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
+ statusbar_pop_file_msg();
set_display_filename(cf);
/* Enable menu items that make sense if you have a capture file you've
}
}
- gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
- " <live capture in progress>");
+ statusbar_push_file_msg(" <live capture in progress>");
}
return err;
}
read_status_t
continue_tail_cap_file(capture_file *cf, int to_read, int *err)
{
- int data_offset = 0;
+ long data_offset = 0;
gtk_clist_freeze(GTK_CLIST(packet_list));
read_status_t
finish_tail_cap_file(capture_file *cf, int *err)
{
- int data_offset;
+ long data_offset;
gtk_clist_freeze(GTK_CLIST(packet_list));
it's probably exited), so we can just close the capture
file; we return READ_ABORTED so our caller can do whatever
is appropriate when that happens. */
- close_cap_file(cf, info_bar);
+ close_cap_file(cf);
return READ_ABORTED;
}
sequential I/O side, to free up memory it requires. */
wtap_sequential_close(cf->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();
+
/* 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
cf->lnk_t = wtap_file_encap(cf->wth);
/* Pop the "<live capture in progress>" message off the status bar. */
- gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
+ statusbar_pop_file_msg();
set_display_filename(cf);
gboolean refilter)
{
apply_color_filter_args args;
- gint i, row;
- proto_tree *protocol_tree = NULL;
+ gint row;
+ gboolean create_proto_tree = FALSE;
epan_dissect_t *edt;
GdkColor fg, bg;
firstusec = fdata->abs_usecs;
}
- fdata->cinfo = &cf->cinfo;
- for (i = 0; i < fdata->cinfo->num_cols; i++) {
- fdata->cinfo->col_buf[i][0] = '\0';
- fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
- }
-
/* If either
we have a display filter and are re-applying it;
a protocol tree against which a filter expression can be
evaluated. */
if ((cf->dfcode != NULL && refilter) || filter_list != NULL)
- protocol_tree = proto_tree_create_root();
+ create_proto_tree = TRUE;
/* Dissect the frame. */
- edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree);
+ edt = epan_dissect_new(create_proto_tree, FALSE);
+
+ if (cf->dfcode != NULL && refilter) {
+ epan_dissect_prime_dfilter(edt, cf->dfcode);
+ }
+ if (filter_list) {
+ filter_list_prime_edt(edt);
+ }
+ epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
+
/* If we have a display filter, apply it if we're refiltering, otherwise
leave the "passed_dfilter" flag alone.
}
}
- /* There are no more filters to apply, so we don't need any protocol
- tree; free it if we created it. */
- if (protocol_tree != NULL)
- proto_tree_free(protocol_tree);
-
- epan_dissect_free(edt);
if (fdata->flags.passed_dfilter) {
/* This frame passed the display filter, so add it to the clist. */
/* 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 (cf->esec < fdata->rel_secs
- || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
+ if ((gint32)cf->esec < fdata->rel_secs
+ || ((gint32)cf->esec == fdata->rel_secs && (gint32)cf->eusec < fdata->rel_usecs)) {
cf->esec = fdata->rel_secs;
cf->eusec = fdata->rel_usecs;
}
prevsec = fdata->abs_secs;
prevusec = fdata->abs_usecs;
- fill_in_columns(fdata);
+ epan_dissect_fill_in_columns(edt);
/* If we haven't yet seen the first frame, this is it.
/* This is the last frame we've seen so far. */
cf->last_displayed = fdata;
- row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
+ row = gtk_clist_append(GTK_CLIST(packet_list), cf->cinfo.col_data);
gtk_clist_set_row_data(GTK_CLIST(packet_list), row, fdata);
if (fdata->flags.marked) {
to the clist, and thus has no row. */
row = -1;
}
- fdata->cinfo = NULL;
+ epan_dissect_free(edt);
return row;
}
static void
-read_packet(capture_file *cf, int offset)
+read_packet(capture_file *cf, long offset)
{
const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
const u_char *buf = wtap_buf_ptr(cf->wth);
frame_data *fdata;
int passed;
- proto_tree *protocol_tree;
frame_data *plist_end;
epan_dissect_t *edt;
fdata->flags.encoding = CHAR_ASCII;
fdata->flags.visited = 0;
fdata->flags.marked = 0;
- fdata->cinfo = NULL;
passed = TRUE;
if (cf->rfcode) {
- protocol_tree = proto_tree_create_root();
- edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree);
+ edt = epan_dissect_new(TRUE, FALSE);
+ epan_dissect_prime_dfilter(edt, cf->rfcode);
+ epan_dissect_run(edt, pseudo_header, buf, fdata, NULL);
passed = dfilter_apply_edt(cf->rfcode, edt);
- proto_tree_free(protocol_tree);
epan_dissect_free(edt);
}
if (passed) {
gboolean stop_flag;
guint32 progbar_quantum;
guint32 progbar_nextstep;
- int count;
+ unsigned int count;
+ int err;
frame_data *selected_frame;
int selected_row;
int row;
which might cause the state information to be constructed differently
by that dissector. */
- /* Initialize the table of conversations. */
- epan_conversation_init();
-
- /* Initialize protocol-specific variables */
- init_all_protocols();
+ /* Initialize all data structures used for dissection. */
+ init_dissection();
}
/* Freeze the packet list while we redo it, so we don't get any
/* 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_all_protocols()"), and null out the GSList pointer. */
+ * "init_dissection()"), and null out the GSList pointer. */
fdata->flags.visited = 0;
if (fdata->pfd) {
g_slist_free(fdata->pfd);
+ fdata->pfd = NULL;
}
- fdata->pfd = NULL;
- if (fdata->data_src) { /* release data source list */
- g_slist_free(fdata->data_src);
- }
- fdata->data_src = NULL;
+ free_data_sources(fdata); /* release data source list */
}
+ /* XXX - do something with "err" */
wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
- cf->pd, fdata->cap_len);
+ cf->pd, fdata->cap_len, &err);
row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
refilter);
fdata->flags.visited = 0;
if (fdata->pfd) {
g_slist_free(fdata->pfd);
+ fdata->pfd = NULL;
}
- fdata->pfd = NULL;
- if (fdata->data_src) {
- g_slist_free(fdata->data_src);
- }
- fdata->data_src = NULL;
+ free_data_sources(fdata); /* release data source list */
}
}
guint32 progbar_quantum;
guint32 progbar_nextstep;
guint32 count;
- proto_tree *protocol_tree;
+ int err;
gint *col_widths = NULL;
gint data_width;
gboolean print_separator;
print_separator = FALSE;
- /* The protocol tree will be "visible", i.e., printed, only if we're
- not printing a summary. */
- proto_tree_is_visible = !print_args->print_summary;
-
/* Update the progress bar when it gets to this value. */
progbar_nextstep = 0;
/* When we reach the value that triggers a progress bar update,
}
count++;
-
- if (fdata->flags.passed_dfilter) {
+ /* Check to see if we are suppressing unmarked packets, if so,
+ * suppress them and then proceed to check for visibility.
+ */
+ if (((print_args->suppress_unmarked && fdata->flags.marked ) ||
+ !(print_args->suppress_unmarked)) && fdata->flags.passed_dfilter) {
+ /* XXX - do something with "err" */
wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
- cf->pd, fdata->cap_len);
+ cf->pd, fdata->cap_len, &err);
if (print_args->print_summary) {
/* Fill in the column information, but don't bother creating
the logical protocol tree. */
- fdata->cinfo = &cf->cinfo;
- for (i = 0; i < fdata->cinfo->num_cols; i++) {
- fdata->cinfo->col_buf[i][0] = '\0';
- fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
- }
- edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, NULL);
- fill_in_columns(fdata);
+ edt = epan_dissect_new(FALSE, FALSE);
+ epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
+ epan_dissect_fill_in_columns(edt);
cp = &line_buf[0];
line_len = 0;
for (i = 0; i < cf->cinfo.num_cols; i++) {
if (print_separator)
print_line(cf->print_fh, print_args->format, "\n");
- /* Create the logical protocol tree. */
- protocol_tree = proto_tree_create_root();
- edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
+ /* Create the logical protocol tree, complete with the display
+ representation of the items; we don't need the columns here,
+ however. */
+ edt = epan_dissect_new(TRUE, TRUE);
+ epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
/* Print the information in that tree. */
- proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
- cf->pd, fdata, cf->print_fh);
-
- proto_tree_free(protocol_tree);
+ proto_tree_print(print_args, (GNode *)edt->tree,
+ fdata, cf->print_fh);
if (print_args->print_hex) {
/* Print the full packet data as hex. */
cf->print_fh = NULL;
- proto_tree_is_visible = FALSE;
-
return TRUE;
}
gboolean stop_flag;
guint32 progbar_quantum;
guint32 progbar_nextstep;
- int count;
+ unsigned int count;
int row;
int i;
GtkStyle *pl_style;
+ /* Are there any columns with time stamps in the "command-line-specified"
+ format?
+
+ XXX - we have to force the "column is writable" flag on, as it
+ might be off from the last frame that was dissected. */
+ col_set_writable(&cf->cinfo, TRUE);
+ if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
+ /* No, there aren't any columns in that format, so we have no work
+ to do. */
+ return;
+ }
+
/* Freeze the packet list while we redo it, so we don't get any
screen updates while it happens. */
freeze_clist(cf);
if (row != -1) {
/* This packet is in the summary list, on row "row". */
- /* XXX - there really should be a way of checking "cf->cinfo" for this;
- the answer isn't going to change from packet to packet, so we should
- simply skip all the "change_time_formats()" work if we're not
- changing anything. */
- fdata->cinfo = &cf->cinfo;
- if (check_col(fdata, COL_CLS_TIME)) {
- /* There are columns that show the time in the "command-line-specified"
- format; update them. */
- for (i = 0; i < cf->cinfo.num_cols; i++) {
- if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
- /* This is one of the columns that shows the time in
- "command-line-specified" format; update it. */
- cf->cinfo.col_buf[i][0] = '\0';
- col_set_cls_time(fdata, i);
- gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
- cf->cinfo.col_data[i]);
- }
+ for (i = 0; i < cf->cinfo.num_cols; i++) {
+ if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
+ /* This is one of the columns that shows the time in
+ "command-line-specified" format; update it. */
+ cf->cinfo.col_buf[i][0] = '\0';
+ col_set_cls_time(fdata, &cf->cinfo, i);
+ gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
+ cf->cinfo.col_data[i]);
}
}
}
thaw_clist(cf);
}
-static void
-clear_tree_and_hex_views(void)
-{
- /* Clear the hex dump. */
-
- GtkWidget *byte_view;
- int i;
-
-/* Get the current tab scroll window, then get the text widget */
-/* from the E_BYTE_VIEW_TEXT_INFO_KEY data field */
-
- i = gtk_notebook_get_current_page( GTK_NOTEBOOK(byte_nb_ptr));
-
- if ( i >= 0){
- byte_view = gtk_notebook_get_nth_page( GTK_NOTEBOOK(byte_nb_ptr), i);
- byte_view = gtk_object_get_data(GTK_OBJECT(byte_view), E_BYTE_VIEW_TEXT_INFO_KEY);
-
- gtk_text_freeze(GTK_TEXT(byte_view));
- gtk_text_set_point(GTK_TEXT(byte_view), 0);
- gtk_text_forward_delete(GTK_TEXT(byte_view),
- gtk_text_get_length(GTK_TEXT(byte_view)));
- gtk_text_thaw(GTK_TEXT(byte_view));
- }
- /* Remove all nodes in ctree. This is how it's done in testgtk.c in GTK+ */
- gtk_clist_clear ( GTK_CLIST(tree_view) );
-
-}
-
gboolean
find_packet(capture_file *cf, dfilter_t *sfcode)
{
gboolean stop_flag;
guint32 progbar_quantum;
guint32 progbar_nextstep;
- int count;
- proto_tree *protocol_tree;
+ unsigned int count;
+ int err;
gboolean frame_matched;
int row;
epan_dissect_t *edt;
/* Is this packet in the display? */
if (fdata->flags.passed_dfilter) {
/* Yes. Does it match the search filter? */
- protocol_tree = proto_tree_create_root();
+ /* XXX - do something with "err" */
wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
- cf->pd, fdata->cap_len);
- edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
+ cf->pd, fdata->cap_len, &err);
+ edt = epan_dissect_new(TRUE, FALSE);
+ epan_dissect_prime_dfilter(edt, sfcode);
+ epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
frame_matched = dfilter_apply_edt(sfcode, edt);
- proto_tree_free(protocol_tree);
- epan_dissect_free(edt);
+ epan_dissect_free(edt);
if (frame_matched) {
new_fd = fdata;
break; /* found it! */
select_packet(capture_file *cf, int row)
{
frame_data *fdata;
- tvbuff_t *bv_tvb;
- int i;
+ int err;
/* Get the frame data struct pointer for this frame */
fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
cf->current_frame = fdata;
/* Get the data in that frame. */
+ /* XXX - do something with "err" */
wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
- cf->pd, fdata->cap_len);
+ cf->pd, fdata->cap_len, &err);
/* Create the logical protocol tree. */
- if (cf->protocol_tree)
- proto_tree_free(cf->protocol_tree);
- cf->protocol_tree = proto_tree_create_root();
- proto_tree_is_visible = TRUE;
- cf->edt = epan_dissect_new(&cf->pseudo_header, cf->pd, cf->current_frame,
- cf->protocol_tree);
- proto_tree_is_visible = FALSE;
-
- /* Display the GUI protocol tree and hex dump. */
- clear_tree_and_hex_views();
-
- i = 0;
- while((bv_tvb = g_slist_nth_data ( cf->current_frame->data_src, i++))){
- add_byte_view( tvb_get_name( bv_tvb), tvb_get_ptr(bv_tvb, 0, -1), tvb_length(bv_tvb));
+ if (cf->edt != NULL) {
+ epan_dissect_free(cf->edt);
+ cf->edt = NULL;
}
-
- proto_tree_draw(cf->protocol_tree, tree_view);
-
- set_notebook_page( byte_nb_ptr, 0);
+ /* We don't need the columns here. */
+ cf->edt = epan_dissect_new(TRUE, TRUE);
+ epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
+ NULL);
+
+ /* Display the GUI protocol tree and hex dump.
+ XXX - why do we dump core if we call "proto_tree_draw()"
+ before calling "add_byte_views()"? */
+ add_byte_views(cf->current_frame, cf->edt->tree, tree_view,
+ byte_nb_ptr);
+ proto_tree_draw(cf->edt->tree, tree_view);
/* A packet is selected. */
set_menus_for_selected_packet(TRUE);
void
unselect_packet(capture_file *cf)
{
- /* Destroy the protocol tree for that packet. */
- if (cf->protocol_tree != NULL) {
- proto_tree_free(cf->protocol_tree);
- cf->protocol_tree = NULL;
+ /* Destroy the epan_dissect_t for the unselected packet. */
+ if (cf->edt != NULL) {
epan_dissect_free(cf->edt);
+ cf->edt = NULL;
}
- finfo_selected = NULL;
-
/* Clear out the display of that packet. */
clear_tree_and_hex_views();
/* No packet is selected. */
set_menus_for_selected_packet(FALSE);
+
+ /* No protocol tree means no selected field. */
+ unselect_field();
}
/* Set the selected row and the focus row of the packet list to the specified
gtk_clist_select_row(GTK_CLIST(packet_list), row, -1);
}
+/* Unset the selected protocol tree field, if any. */
+void
+unselect_field(void)
+{
+ statusbar_pop_field_msg();
+ finfo_selected = NULL;
+ set_menus_for_selected_tree_row(FALSE);
+}
+
+/*
+ * Mark a particular frame.
+ */
+void
+mark_frame(capture_file *cf, frame_data *frame)
+{
+ frame->flags.marked = TRUE;
+ cf->marked_count++;
+}
+
+/*
+ * Unmark a particular frame.
+ */
+void
+unmark_frame(capture_file *cf, frame_data *frame)
+{
+ frame->flags.marked = FALSE;
+ cf->marked_count--;
+}
+
static void
freeze_clist(capture_file *cf)
{
msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
save_msg = g_malloc(msg_len);
snprintf(save_msg, msg_len, save_fmt, name_ptr);
- gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
+ statusbar_push_file_msg(save_msg);
g_free(save_msg);
if (!save_filtered && !save_marked && save_format == cf->cd_t) {
do_copy = TRUE;
from_filename = cf->filename;
}
- /* Copy the file, if we haven't moved it. */
+
+ /* Check that the from file is not the same as to file */
+
if (do_copy) {
+
+ /* Copy the file, if we haven't moved it. */
+ if (strncmp(from_filename, fname, sizeof(cf->filename)) == 0) {
+ simple_dialog(ESD_TYPE_WARN, NULL,
+ "Can't save over current capture file: %s!", from_filename);
+ goto done;
+ }
+
if (!copy_binary_file(from_filename, fname)) {
goto done;
}
hdr.caplen = fdata->cap_len;
hdr.len = fdata->pkt_len;
hdr.pkt_encap = fdata->lnk_t;
- wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
- pd, fdata->cap_len);
+ if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
+ pd, fdata->cap_len, &err)) {
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ file_read_error_message(err), cf->filename);
+ wtap_dump_close(pdh, &err);
+ goto done;
+ }
if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
simple_dialog(ESD_TYPE_CRIT, NULL,
done:
/* Pop the "Saving:" message off the status bar. */
- gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
+ statusbar_pop_file_msg();
if (err == 0) {
if (!save_filtered && !save_marked) {
/* We saved the entire capture, not just some packets from it.
case WTAP_ERR_SHORT_READ:
errmsg = "The file \"%s\" appears to have been cut short"
- " in the middle of a packet.";
+ " in the middle of a packet or other data.";
break;
case WTAP_ERR_SHORT_WRITE: