/* file.c
* File I/O routines
*
- * $Id: file.c,v 1.366 2004/02/22 22:33:59 guy Exp $
+ * $Id$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+/* With MSVC and a libethereal.dll this file needs to import some variables
+ in a special way. Therefore _NEED_VAR_IMPORT_ is defined. */
+#define _NEED_VAR_IMPORT_
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <epan/filesystem.h>
#include "color.h"
-#include "column.h"
+#include "color_filters.h"
+#include <epan/column.h>
#include <epan/packet.h>
-#include "range.h"
+#include "packet-range.h"
#include "print.h"
#include "file.h"
#include "menu.h"
#include "util.h"
+#include "merge.h"
#include "alert_box.h"
#include "simple_dialog.h"
#include "progress_dlg.h"
#include "ui_util.h"
#include "statusbar.h"
-#include "prefs.h"
+#include <epan/prefs.h>
#include <epan/dfilter/dfilter.h>
#include <epan/conversation.h>
#include "globals.h"
#include <epan/epan_dissect.h>
-#include "tap.h"
+#include <epan/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
+#define O_BINARY 0
+#endif
#ifdef HAVE_LIBPCAP
gboolean auto_scroll_live;
XXX - is this the right number? */
#define FRAME_DATA_CHUNK_SIZE 1024
-typedef struct {
- int level;
- FILE *fh;
- GSList *src_list;
- gboolean print_all_levels;
- gboolean print_hex_for_data;
- char_enc encoding;
- gint format; /* text or PostScript */
-} print_data;
int
cf_open(char *fname, gboolean is_tempfile, capture_file *cf)
set_menus_for_capture_in_progress(FALSE);
set_menus_for_selected_tree_row(cf);
+ reset_tap_listeners();
+
/* We have no file open. */
cf->state = FILE_CLOSED;
}
bump that value by this amount. */
progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
packet_list_freeze();
stop_flag = FALSE;
switch (err) {
case WTAP_ERR_UNSUPPORTED_ENCAP:
- errmsg = "The capture file is for a network type that Ethereal doesn't support.";
+ snprintf(errmsg_errno, sizeof(errmsg_errno),
+ "The capture file has a packet with a network type that Ethereal doesn't support.\n(%s)",
+ err_info);
+ g_free(err_info);
+ errmsg = errmsg_errno;
break;
case WTAP_ERR_CANT_READ:
- errmsg = "An attempt to read from the file failed for"
+ errmsg = "An attempt to read from the capture file failed for"
" some unknown reason.";
break;
snprintf(errmsg_errno, sizeof(errmsg_errno),
"The capture file appears to be damaged or corrupt.\n(%s)",
err_info);
+ g_free(err_info);
errmsg = errmsg_errno;
break;
cf_start_tail(char *fname, gboolean is_tempfile, capture_file *cf)
{
int err;
+ gchar *capture_msg;
err = cf_open(fname, is_tempfile, cf);
if (err == 0) {
packets (yes, I know, we don't have any *yet*). */
set_menus_for_captured_packets(TRUE);
- statusbar_push_file_msg(" <live capture in progress>");
+ capture_msg = g_strdup_printf(" %s: <live capture in progress>", cf->iface);
+
+ statusbar_push_file_msg(capture_msg);
+
+ g_free(capture_msg);
}
return err;
}
}
}
-int
-filter_packets(capture_file *cf, gchar *dftext)
+gboolean
+cf_merge_files(const char *out_filename, int out_fd, int in_file_count,
+ char *const *in_filenames, int file_type, gboolean do_append)
+{
+ merge_in_file_t *in_files;
+ wtap *wth;
+ wtap_dumper *pdh;
+ int open_err, read_err, write_err, close_err;
+ gchar *err_info;
+ int err_fileno;
+ int i;
+ char errmsg_errno[1024+1];
+ gchar err_str[2048+1];
+ char *errmsg;
+ gboolean got_read_error = FALSE, got_write_error = FALSE;
+ long data_offset;
+ progdlg_t *progbar = NULL;
+ gboolean stop_flag;
+ /*
+ * XXX - should be "off_t", but Wiretap would need more work to handle
+ * the full size of "off_t" on platforms where it's more than a "long"
+ * as well.
+ */
+ long f_len, file_pos;
+ float prog_val;
+ GTimeVal start_time;
+ gchar status_str[100];
+ int progbar_nextstep;
+ int progbar_quantum;
+
+ /* open the input files */
+ if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
+ &open_err, &err_info, &err_fileno)) {
+ free(in_files);
+ cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
+ FALSE, 0);
+ return FALSE;
+ }
+
+ pdh = wtap_dump_fdopen(out_fd, file_type,
+ merge_select_frame_type(in_file_count, in_files),
+ merge_max_snapshot_length(in_file_count, in_files), &open_err);
+ if (pdh == NULL) {
+ merge_close_in_files(in_file_count, in_files);
+ free(in_files);
+ cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
+ file_type);
+ return FALSE;
+ }
+
+ /* Get the sum of the sizes of all the files. */
+ f_len = 0;
+ for (i = 0; i < in_file_count; i++)
+ f_len += in_files[i].size;
+
+ /* Update the progress bar when it gets to this value. */
+ progbar_nextstep = 0;
+ /* When we reach the value that triggers a progress bar update,
+ bump that value by this amount. */
+ progbar_quantum = f_len/N_PROGBAR_UPDATES;
+
+ stop_flag = FALSE;
+ g_get_current_time(&start_time);
+
+ /* do the merge (or append) */
+ for (;;) {
+ if (do_append)
+ wth = merge_append_read_packet(in_file_count, in_files, &read_err,
+ &err_info);
+ else
+ wth = merge_read_packet(in_file_count, in_files, &read_err,
+ &err_info);
+ if (wth == NULL) {
+ if (read_err != 0)
+ got_read_error = TRUE;
+ break;
+ }
+
+ /* Get the sum of the data offsets in all of the files. */
+ data_offset = 0;
+ for (i = 0; i < in_file_count; i++)
+ data_offset += in_files[i].data_offset;
+
+ if (data_offset >= progbar_nextstep) {
+ /* Get the sum of the seek positions in all of the files. */
+ file_pos = 0;
+ for (i = 0; i < in_file_count; i++)
+ file_pos += lseek(wtap_fd(in_files[i].wth), 0, SEEK_CUR);
+ prog_val = (gfloat) file_pos / (gfloat) f_len;
+ if (prog_val > 1.0) {
+ /* Some file probably grew while we were reading it.
+ That "shouldn't happen", so we'll just clip the progress
+ value at 1.0. */
+ prog_val = 1.0;
+ }
+ if (progbar == NULL) {
+ /* Create the progress bar if necessary */
+ progbar = delayed_create_progress_dlg("Merging", "files",
+ &stop_flag, &start_time, prog_val);
+ }
+ if (progbar != NULL) {
+ g_snprintf(status_str, sizeof(status_str),
+ "%luKB of %luKB", file_pos / 1024, f_len / 1024);
+ update_progress_dlg(progbar, prog_val, status_str);
+ }
+ progbar_nextstep += progbar_quantum;
+ }
+
+ if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
+ wtap_buf_ptr(wth), &write_err)) {
+ got_write_error = TRUE;
+ break;
+ }
+ }
+
+ /* We're done merging the files; destroy the progress bar if it was created. */
+ if (progbar != NULL)
+ destroy_progress_dlg(progbar);
+
+ merge_close_in_files(in_file_count, in_files);
+ if (!got_read_error && !got_write_error) {
+ if (!wtap_dump_close(pdh, &write_err))
+ got_write_error = TRUE;
+ } else
+ wtap_dump_close(pdh, &close_err);
+
+ if (got_read_error) {
+ /*
+ * Find the file on which we got the error, and report the error.
+ */
+ for (i = 0; i < in_file_count; i++) {
+ if (in_files[i].state == GOT_ERROR) {
+ /* Put up a message box noting that a read failed somewhere along
+ the line. */
+ switch (read_err) {
+
+ case WTAP_ERR_UNSUPPORTED_ENCAP:
+ snprintf(errmsg_errno, sizeof(errmsg_errno),
+ "The capture file %%s has a packet with a network type that Ethereal doesn't support.\n(%s)",
+ err_info);
+ g_free(err_info);
+ errmsg = errmsg_errno;
+ break;
+
+ case WTAP_ERR_CANT_READ:
+ errmsg = "An attempt to read from the capture file %s failed for"
+ " some unknown reason.";
+ break;
+
+ case WTAP_ERR_SHORT_READ:
+ errmsg = "The capture file %s appears to have been cut short"
+ " in the middle of a packet.";
+ break;
+
+ case WTAP_ERR_BAD_RECORD:
+ snprintf(errmsg_errno, sizeof(errmsg_errno),
+ "The capture file %%s appears to be damaged or corrupt.\n(%s)",
+ err_info);
+ g_free(err_info);
+ errmsg = errmsg_errno;
+ break;
+
+ default:
+ snprintf(errmsg_errno, sizeof(errmsg_errno),
+ "An error occurred while reading the"
+ " capture file %%s: %s.", wtap_strerror(read_err));
+ errmsg = errmsg_errno;
+ break;
+ }
+ snprintf(err_str, sizeof err_str, errmsg, in_files[i].filename);
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
+ }
+ }
+ }
+
+ if (got_write_error) {
+ /* Put up an alert box for the write error. */
+ cf_write_failure_alert_box(out_filename, write_err);
+ }
+
+ return (!got_read_error && !got_write_error);
+}
+
+gboolean
+filter_packets(capture_file *cf, gchar *dftext, gboolean force)
{
dfilter_t *dfcode;
char *filter_new = dftext ? dftext : "";
char *filter_old = cf->dfilter ? cf->dfilter : "";
-
- /* if new filter equals old one, do nothing */
- if (strcmp(filter_new, filter_old) == 0) {
- return 1;
+ /* if new filter equals old one, do nothing unless told to do so */
+ if (!force && strcmp(filter_new, filter_old) == 0) {
+ return TRUE;
}
if (dftext == NULL) {
dftext = g_strdup(dftext);
if (!dfilter_compile(dftext, &dfcode)) {
/* The attempt failed; report an error. */
+ gchar *safe_dftext = simple_dialog_format_message(dftext);
+ gchar *safe_dfilter_error_msg = simple_dialog_format_message(
+ dfilter_error_msg);
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"%s%s%s\n"
"\n"
- "The display filter \"%s\" is not a valid display filter.\n"
+ "The following display filter is not a valid display filter:\n%s\n"
"See the help for a description of the display filter syntax.",
- simple_dialog_primary_start(), dfilter_error_msg,
- simple_dialog_primary_end(), dftext);
+ simple_dialog_primary_start(), safe_dfilter_error_msg,
+ simple_dialog_primary_end(), safe_dftext);
+ g_free(safe_dfilter_error_msg);
+ g_free(safe_dftext);
g_free(dftext);
- return 0;
+ return FALSE;
}
/* Was it empty? */
} else {
rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
}
- return 1;
+ return TRUE;
}
void
ret = PSP_FAILED;
break;
}
+ /* Process the packet */
if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
/* Callback failed. We assume it reported the error appropriately. */
ret = PSP_FAILED;
typedef struct {
print_args_t *print_args;
- FILE *print_fh;
+ 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;
int line_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, 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;
+ edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
+
+ /* Fill in the column information if we're printing the summary
+ information. */
if (args->print_args->print_summary) {
- /* Fill in the column information, but don't bother creating
- the logical protocol tree. */
- edt = epan_dissect_new(FALSE, FALSE);
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) {
+ if (!new_page(args->print_args->stream))
+ goto fail;
+ } 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__".
+ */
+ sprintf(bookmark_name, "__frame%u__", fdata->num);
+
+ if (args->print_args->print_summary) {
+ 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 < cf->cinfo.num_cols; i++) {
*cp++ = ' ';
}
*cp = '\0';
- print_line(args->print_fh, 0, args->print_args->format, 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 (!print_line(args->print_args->stream, 0, args->line_buf))
+ goto fail;
} else {
- if (args->print_separator)
- print_line(args->print_fh, 0, args->print_args->format, "");
+ /*
+ * 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) */
- /* 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, pseudo_header, pd, fdata, NULL);
+ 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. */
- proto_tree_print(args->print_args, edt, args->print_fh);
+ if (!proto_tree_print(args->print_args, edt, args->print_args->stream))
+ goto fail;
- if (args->print_args->print_hex) {
- /* Print the full packet data as hex. */
- print_hex_data(args->print_fh, args->print_args->format, edt);
- }
+ /* 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;
+ }
- /* Print a blank line if we print anything after this. */
+ if (args->print_args->print_hex) {
+ /* Print the full packet data as hex. */
+ 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;
- } /* if (print_summary) */
+
+ /* Print a header line if we print any more packet summaries */
+ args->print_header_line = TRUE;
+ } /* if (args->print_args->print_dissections != print_dissections_none) */
+
epan_dissect_free(edt);
- return !ferror(args->print_fh);
+ /* 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_free(edt);
+ return FALSE;
}
pp_return_t
int line_len;
psp_return_t ret;
- callback_args.print_fh = open_print_dest(print_args->to_file,
- print_args->dest);
- if (callback_args.print_fh == NULL)
- return PP_OPEN_ERROR; /* attempt to open destination failed */
-
- print_preamble(callback_args.print_fh, print_args->format);
- 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.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;
+
+ 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 line buffer at
- its initial length. */
- callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
+ /* 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);
/* Find the widths for each of the columns - maximum of the
- width of the title and the width of the data - and print
- the column titles. */
+ width of the title and the width of the data - and construct
+ a buffer with a line containing the column titles. */
callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
- cp = &callback_args.line_buf[0];
+ cp = &callback_args.header_line_buf[0];
line_len = 0;
for (i = 0; i < cf->cinfo.num_cols; i++) {
/* Don't pad the last column. */
/* 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.line_buf_len) {
- cp_off = cp - callback_args.line_buf;
- callback_args.line_buf_len = 2 * line_len;
- callback_args.line_buf = g_realloc(callback_args.line_buf,
- callback_args.line_buf_len + 1);
- cp = callback_args.line_buf + cp_off;
+ if (line_len > callback_args.header_line_buf_len) {
+ cp_off = cp - callback_args.header_line_buf;
+ callback_args.header_line_buf_len = 2 * line_len;
+ callback_args.header_line_buf = 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)
+/* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
sprintf(cp, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
- else
+ else*/
sprintf(cp, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
cp += column_len;
if (i != cf->cinfo.num_cols - 1)
*cp++ = ' ';
}
*cp = '\0';
- print_line(callback_args.print_fh, 0, print_args->format,
- callback_args.line_buf);
+
+ /* 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 = g_malloc(callback_args.line_buf_len + 1);
} /* if (print_summary) */
/* Iterate through the list of packets, printing the packets we were
"selected packets", print_packet,
&callback_args);
- if (callback_args.col_widths != NULL)
- g_free(callback_args.col_widths);
+ if (callback_args.header_line_buf != NULL)
+ g_free(callback_args.header_line_buf);
if (callback_args.line_buf != NULL)
g_free(callback_args.line_buf);
+ if (callback_args.col_widths != NULL)
+ g_free(callback_args.col_widths);
switch (ret) {
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;
}
- 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;
+}
+
+static gboolean
+write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
+ union wtap_pseudo_header *pseudo_header, const guint8 *pd,
+ void *argsp)
+{
+ FILE *fh = argsp;
+ epan_dissect_t *edt;
+
+ /* Create the protocol tree, but don't fill in the column information. */
+ edt = epan_dissect_new(TRUE, TRUE);
+ epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
+
+ /* Write out the information in that tree. */
+ proto_tree_write_pdml(edt, fh);
+
+ epan_dissect_free(edt);
+
+ return !ferror(fh);
+}
+
+pp_return_t
+write_pdml_packets(capture_file *cf, print_args_t *print_args)
+{
+ FILE *fh;
+ psp_return_t ret;
+
+ fh = fopen(print_args->file, "w");
+ if (fh == NULL)
+ return PP_OPEN_ERROR; /* attempt to open destination failed */
+
+ write_pdml_preamble(fh);
+ if (ferror(fh)) {
+ fclose(fh);
+ return PP_WRITE_ERROR;
+ }
+
+ /* Iterate through the list of packets, printing the packets we were
+ told to print. */
+ ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
+ "selected packets", write_pdml_packet,
+ fh);
+
+ 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 PP_WRITE_ERROR;
+ }
+
+ write_pdml_finale(fh);
+ if (ferror(fh)) {
+ fclose(fh);
+ return PP_WRITE_ERROR;
+ }
+
+ /* XXX - check for an error */
+ fclose(fh);
+
+ return PP_OK;
+}
+
+static gboolean
+write_psml_packet(capture_file *cf, frame_data *fdata,
+ union wtap_pseudo_header *pseudo_header, const guint8 *pd,
+ void *argsp)
+{
+ FILE *fh = argsp;
+ epan_dissect_t *edt;
+
+ /* Fill in the column information, but don't create the protocol tree. */
+ edt = epan_dissect_new(FALSE, FALSE);
+ epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
+
+ /* Write out the information in that tree. */
+ proto_tree_write_psml(edt, fh);
+
+ epan_dissect_free(edt);
+
+ return !ferror(fh);
+}
+
+pp_return_t
+write_psml_packets(capture_file *cf, print_args_t *print_args)
+{
+ FILE *fh;
+ psp_return_t ret;
+
+ fh = fopen(print_args->file, "w");
+ if (fh == NULL)
+ return PP_OPEN_ERROR; /* attempt to open destination failed */
+
+ write_psml_preamble(fh);
+ if (ferror(fh)) {
+ fclose(fh);
+ return PP_WRITE_ERROR;
+ }
+
+ /* Iterate through the list of packets, printing the packets we were
+ told to print. */
+ ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
+ "selected packets", write_psml_packet,
+ fh);
+
+ 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 PP_WRITE_ERROR;
+ }
+
+ write_psml_finale(fh);
+ if (ferror(fh)) {
+ fclose(fh);
+ return PP_WRITE_ERROR;
+ }
+
+ /* XXX - check for an error */
+ fclose(fh);
return PP_OK;
}
}
/* Don't match invisible entries. */
- if (!fi->visible)
+ if (PROTO_ITEM_IS_HIDDEN(node))
return;
/* was a free format label produced? */
info.data_len = string_size;
/* String or hex search? */
- if (cf->ascii) {
+ if (cf->string) {
/* String search - what type of string? */
switch (cf->scs_type) {
* we need an API for popping up alert boxes with
* {Verb} and "Cancel".
*/
- simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTN_OK,
- "You have searched up to the beginning of the capture.\n"
- "Do you want to continue the search from the end of the capture?");
- 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_CONFIRMATION, ESD_BTN_OK,
- "You have searched up to the end of the capture.\n"
- "Do you want to continue the search from the beginning of the capture?");
- 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 {
/* 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. */
-#ifndef WIN32
+#ifndef _WIN32
if (rename(cf->filename, fname) == 0) {
/* That succeeded - there's no need to copy the source file. */
from_filename = NULL;
switch (err) {
- case WTAP_ERR_UNSUPPORTED:
case WTAP_ERR_UNSUPPORTED_ENCAP:
+ snprintf(errmsg_errno, sizeof(errmsg_errno),
+ "The file \"%%s\" has a packet with a network type that Ethereal doesn't support.\n(%s)",
+ err_info);
+ break;
+
case WTAP_ERR_BAD_RECORD:
snprintf(errmsg_errno, sizeof(errmsg_errno),
"An error occurred while reading from the file \"%%s\": %s.\n(%s)",
}
}
+/* 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.