/* file.c
* File I/O routines
*
- * $Id: file.c,v 1.388 2004/07/08 10:36:26 guy Exp $
+ * $Id$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
#include <epan/filesystem.h>
#include "color.h"
+#include "color_filters.h"
#include "column.h"
#include <epan/packet.h>
-#include "range.h"
+#include "packet-range.h"
#include "print.h"
#include "file.h"
#include "menu.h"
#include <epan/epan_dissect.h>
#include "tap.h"
#include "tap_dfilter_dlg.h"
-#include "packet-data.h"
+#include <epan/dissectors/packet-data.h>
/* Win32 needs the O_BINARY flag for open() */
#ifndef O_BINARY
typedef struct {
print_args_t *print_args;
- FILE *print_fh;
gboolean print_header_line;
char *header_line_buf;
int header_line_buf_len;
int column_len;
int cp_off;
gboolean proto_tree_needed;
+ char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
+ char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
- /* Create the protocol tree if we're printing the dissection or the hex
- data. */
+ /* 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 =
args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex;
-
- /* Fill in the column information.
- XXX - do we need to do so if we're not printing it? */
edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
- epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
- epan_dissect_fill_in_columns(edt);
+
+ /* Fill in the column information if we're printing the summary
+ information. */
+ if (args->print_args->print_summary) {
+ epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
+ epan_dissect_fill_in_columns(edt);
+ } else
+ epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
if (args->print_formfeed) {
- print_formfeed(args->print_fh, args->print_args->format);
+ if (!new_page(args->print_args->stream))
+ goto fail;
} else {
- if (args->print_separator)
- print_line(args->print_fh, 0, args->print_args->format, "");
+ if (args->print_separator) {
+ if (!print_line(args->print_args->stream, 0, ""))
+ goto fail;
+ }
}
- if (args->print_args->print_summary || args->print_args->format == PR_FMT_PS) {
+ /*
+ * We generate bookmarks, if the output format supports them.
+ * The name is "__frameN__".
+ */
+ sprintf(bookmark_name, "__frame%u__", fdata->num);
+
+ if (args->print_args->print_summary) {
if (args->print_header_line) {
- print_line(args->print_fh, 0, args->print_args->format,
- args->header_line_buf);
+ 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];
}
*cp = '\0';
- print_packet_header(args->print_fh, args->print_args->format, fdata->num, args->line_buf);
+ /*
+ * 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 (args->print_args->print_summary) {
- print_line(args->print_fh, 0, args->print_args->format, args->line_buf);
- }
+ 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.
+ */
+ sprintf(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. */
- print_line(args->print_fh, 0, args->print_args->format, "");
+ if (!print_line(args->print_args->stream, 0, ""))
+ goto fail;
}
/* Print the information in that tree. */
- proto_tree_print(args->print_args, edt, args->print_fh);
+ if (!proto_tree_print(args->print_args, edt, 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;
if (args->print_args->print_hex) {
/* Print the full packet data as hex. */
- print_hex_data(args->print_fh, args->print_args->format, edt);
+ if (!print_hex_data(args->print_args->stream, edt))
+ 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 */
args->print_header_line = TRUE;
- } /* if (print_summary) */
+ } /* if (args->print_args->print_dissections != print_dissections_none) */
epan_dissect_free(edt);
args->print_formfeed = TRUE;
}
- return !ferror(args->print_fh);
+ return TRUE;
+
+fail:
+ epan_dissect_free(edt);
+ return FALSE;
}
pp_return_t
int line_len;
psp_return_t ret;
- if(print_args->to_file) {
- callback_args.print_fh = open_print_dest(print_args->to_file,
- print_args->file);
- } else {
- callback_args.print_fh = open_print_dest(print_args->to_file,
- print_args->cmd);
- }
- if (callback_args.print_fh == NULL)
- return PP_OPEN_ERROR; /* attempt to open destination failed */
-
- print_preamble(callback_args.print_fh, print_args->format, cf->filename);
- if (ferror(callback_args.print_fh)) {
- close_print_dest(print_args->to_file, callback_args.print_fh);
- return PP_WRITE_ERROR;
- }
-
callback_args.print_args = print_args;
callback_args.print_header_line = TRUE;
callback_args.header_line_buf = NULL;
callback_args.line_buf = NULL;
callback_args.line_buf_len = 256;
callback_args.col_widths = NULL;
- if (print_args->print_summary || print_args->format == PR_FMT_PS) {
+
+ if (!print_preamble(print_args->stream, cf->filename)) {
+ destroy_print_stream(print_args->stream);
+ return PP_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 = g_malloc(callback_args.header_line_buf_len + 1);
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. */
- close_print_dest(print_args->to_file, callback_args.print_fh);
+ destroy_print_stream(print_args->stream);
return PP_WRITE_ERROR;
}
- print_finale(callback_args.print_fh, print_args->format);
- if (ferror(callback_args.print_fh)) {
- close_print_dest(print_args->to_file, callback_args.print_fh);
+ if (!print_finale(print_args->stream)) {
+ destroy_print_stream(print_args->stream);
return PP_WRITE_ERROR;
}
- /* XXX - check for an error */
- close_print_dest(print_args->to_file, callback_args.print_fh);
+ if (!destroy_print_stream(print_args->stream))
+ return PP_WRITE_ERROR;
return PP_OK;
}
* we need an API for popping up alert boxes with
* {Verb} and "Cancel".
*/
- simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
- "%sBeginning of capture exceeded!%s\n\n"
- "Search is continued from the end of the capture.",
- simple_dialog_primary_start(), simple_dialog_primary_end());
- fdata = cf->plist_end; /* wrap around */
+
+ if (prefs.gui_find_wrap)
+ {
+ simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
+ "%sBeginning of capture exceeded!%s\n\n"
+ "Search is continued from the end of the capture.",
+ simple_dialog_primary_start(), simple_dialog_primary_end());
+ fdata = cf->plist_end; /* wrap around */
+ }
+ else
+ {
+ simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
+ "%sBeginning of capture exceeded!%s\n\n"
+ "Try searching forwards.",
+ simple_dialog_primary_start(), simple_dialog_primary_end());
+ fdata = start_fd; /* stay on previous packet */
+ }
}
} else {
/* Go on to the next frame. */
fdata = fdata->next;
if (fdata == NULL) {
- simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
- "%sEnd of capture exceeded!%s\n\n"
- "Search is continued from the start of the capture.",
- simple_dialog_primary_start(), simple_dialog_primary_end());
- fdata = cf->plist; /* wrap around */
+ if (prefs.gui_find_wrap)
+ {
+ simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
+ "%sEnd of capture exceeded!%s\n\n"
+ "Search is continued from the start of the capture.",
+ simple_dialog_primary_start(), simple_dialog_primary_end());
+ fdata = cf->plist; /* wrap around */
+ }
+ else
+ {
+ simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
+ "%sEnd of capture exceeded!%s\n\n"
+ "Try searching backwards.",
+ simple_dialog_primary_start(), simple_dialog_primary_end());
+ fdata = start_fd; /* stay on previous packet */
+ }
}
}
return TRUE; /* we got to that packet */
}
+/*
+ * Go to frame specified by currently selected protocol tree item.
+ */
+void
+goto_framenum(capture_file *cf)
+{
+ header_field_info *hfinfo;
+ guint32 framenum;
+
+ if (cf->finfo_selected) {
+ hfinfo = cf->finfo_selected->hfinfo;
+ g_assert(hfinfo);
+ if (hfinfo->type == FT_FRAMENUM) {
+ framenum = fvalue_get_integer(&cf->finfo_selected->value);
+ if (framenum != 0)
+ goto_frame(cf, framenum);
+ }
+ }
+}
+
/* Select the packet on a given row. */
void
select_packet(capture_file *cf, int row)
void
mark_frame(capture_file *cf, frame_data *frame)
{
- frame->flags.marked = TRUE;
- cf->marked_count++;
+ if (! frame->flags.marked) {
+ frame->flags.marked = TRUE;
+ if (cf->count > cf->marked_count)
+ cf->marked_count++;
+ }
}
/*
void
unmark_frame(capture_file *cf, frame_data *frame)
{
- frame->flags.marked = FALSE;
- cf->marked_count--;
+ if (frame->flags.marked) {
+ frame->flags.marked = FALSE;
+ if (cf->marked_count > 0)
+ cf->marked_count--;
+ }
}
typedef struct {
}
}
+/* Reload the current capture file. */
+void
+cf_reload() {
+ gchar *filename;
+ gboolean is_tempfile;
+
+ /* 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 "cfile.filename", so we must make
+ a copy of it first. */
+ filename = g_strdup(cfile.filename);
+ is_tempfile = cfile.is_tempfile;
+ cfile.is_tempfile = FALSE;
+ if (cf_open(filename, is_tempfile, &cfile) == 0) {
+ switch (cf_read(&cfile)) {
+
+ case READ_SUCCESS:
+ case 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 READ_ABORTED:
+ /* The user bailed out of re-reading the capture file; the
+ capture file has been closed - just free the capture file name
+ string and return (without changing the last containing
+ directory). */
+ g_free(filename);
+ return;
+ }
+ } else {
+ /* The open failed, so "cfile.is_tempfile" wasn't set to "is_tempfile".
+ Instead, the file was left open, so we should restore "cfile.is_tempfile"
+ ourselves.
+
+ XXX - change the menu? Presumably "cf_open()" will do that;
+ make sure it does! */
+ cfile.is_tempfile = is_tempfile;
+ }
+ /* "cf_open()" made a copy of the file name we handed it, so
+ we should free up our copy. */
+ g_free(filename);
+}
/* Copies a file in binary mode, for those operating systems that care about
* such things.