Allow the user to save either all of the current capture, or only the
packets that are currently being displayed from that capture. Centralize the code to control whether "File:Save" and "File:Save As" are enabled (and *always* have "File:Save As" enabled if you have a capture; "File:Save" is enabled only if you have a live capture you've not yet saved, although it does the same thing as "File:Save As"). Have the "save_file" member of a "capture_file" structure represent *only* the file currently being *written* to by a capture, and, if there is no capture currently in progress, have it be NULL; the name of the file currently being *displayed" is in the "filename" member, and an "is_tempfile" member indicates whether it's a temporary file for a live capture or not. Have "close_cap_file()" delete the current capture file if it's a temporary capture file that hasn't been saved (in its entirety - saving selected frames doesn't count). Do the same (if there *is* a current capture file) when exiting. The "Ready to load or capture" message is the only statusbar message in the "main" context; "close_cap_file()" should never pop it, it should only pop whatever message exists in the "file" context, and thus has no need to take, as an argument, the context for the message it should pop. Update the man page to reflect the new behavior of "File:Save" and "File:Save As", and to reflect recent changes to "Display:Match Selected". svn path=/trunk/; revision=1170
This commit is contained in:
parent
191f4cd467
commit
dc548e7458
41
capture.c
41
capture.c
|
@ -1,7 +1,7 @@
|
||||||
/* capture.c
|
/* capture.c
|
||||||
* Routines for packet capture windows
|
* Routines for packet capture windows
|
||||||
*
|
*
|
||||||
* $Id: capture.c,v 1.83 1999/11/29 01:54:00 guy Exp $
|
* $Id: capture.c,v 1.84 1999/11/30 20:49:45 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@zing.org>
|
* By Gerald Combs <gerald@zing.org>
|
||||||
|
@ -120,7 +120,7 @@ void
|
||||||
do_capture(char *capfile_name)
|
do_capture(char *capfile_name)
|
||||||
{
|
{
|
||||||
char tmpname[128+1];
|
char tmpname[128+1];
|
||||||
gboolean is_temp_file;
|
gboolean is_tempfile;
|
||||||
u_char c;
|
u_char c;
|
||||||
int i;
|
int i;
|
||||||
guint byte_count;
|
guint byte_count;
|
||||||
|
@ -131,12 +131,12 @@ do_capture(char *capfile_name)
|
||||||
if (capfile_name != NULL) {
|
if (capfile_name != NULL) {
|
||||||
/* Try to open/create the specified file for use as a capture buffer. */
|
/* Try to open/create the specified file for use as a capture buffer. */
|
||||||
cf.save_file_fd = open(capfile_name, O_RDWR|O_TRUNC|O_CREAT, 0600);
|
cf.save_file_fd = open(capfile_name, O_RDWR|O_TRUNC|O_CREAT, 0600);
|
||||||
is_temp_file = FALSE;
|
is_tempfile = FALSE;
|
||||||
} else {
|
} else {
|
||||||
/* Choose a random name for the capture buffer */
|
/* Choose a random name for the capture buffer */
|
||||||
cf.save_file_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
|
cf.save_file_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
|
||||||
capfile_name = g_strdup(tmpname);
|
capfile_name = g_strdup(tmpname);
|
||||||
is_temp_file = TRUE;
|
is_tempfile = TRUE;
|
||||||
}
|
}
|
||||||
if (cf.save_file_fd == -1) {
|
if (cf.save_file_fd == -1) {
|
||||||
simple_dialog(ESD_TYPE_WARN, NULL,
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
|
@ -144,15 +144,9 @@ do_capture(char *capfile_name)
|
||||||
"could not be opened: %s.", capfile_name, strerror(errno));
|
"could not be opened: %s.", capfile_name, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
close_cap_file(&cf, info_bar, file_ctx);
|
close_cap_file(&cf, info_bar);
|
||||||
if (cf.save_file != NULL) {
|
g_assert(cf.save_file == NULL);
|
||||||
/* If the current file is a temporary capture file, remove it. */
|
|
||||||
if (!cf.user_saved)
|
|
||||||
unlink(cf.save_file); /* silently ignore error */
|
|
||||||
g_free(cf.save_file);
|
|
||||||
}
|
|
||||||
cf.save_file = capfile_name;
|
cf.save_file = capfile_name;
|
||||||
cf.user_saved = !is_temp_file;
|
|
||||||
|
|
||||||
if (sync_mode) { /* use fork() for capture */
|
if (sync_mode) { /* use fork() for capture */
|
||||||
int fork_child;
|
int fork_child;
|
||||||
|
@ -192,7 +186,6 @@ do_capture(char *capfile_name)
|
||||||
} else {
|
} else {
|
||||||
/* Parent process - read messages from the child process over the
|
/* Parent process - read messages from the child process over the
|
||||||
sync pipe. */
|
sync pipe. */
|
||||||
cf.filename = cf.save_file;
|
|
||||||
close(sync_pipe[1]);
|
close(sync_pipe[1]);
|
||||||
|
|
||||||
/* Read a byte count from "sync_pipe[0]", terminated with a
|
/* Read a byte count from "sync_pipe[0]", terminated with a
|
||||||
|
@ -210,6 +203,7 @@ do_capture(char *capfile_name)
|
||||||
XXX - reap the child process and report the status in detail. */
|
XXX - reap the child process and report the status in detail. */
|
||||||
close(sync_pipe[0]);
|
close(sync_pipe[0]);
|
||||||
unlink(cf.save_file);
|
unlink(cf.save_file);
|
||||||
|
g_free(cf.save_file);
|
||||||
cf.save_file = NULL;
|
cf.save_file = NULL;
|
||||||
simple_dialog(ESD_TYPE_WARN, NULL, "Capture child process died");
|
simple_dialog(ESD_TYPE_WARN, NULL, "Capture child process died");
|
||||||
return;
|
return;
|
||||||
|
@ -222,6 +216,7 @@ do_capture(char *capfile_name)
|
||||||
and report the failure. */
|
and report the failure. */
|
||||||
close(sync_pipe[0]);
|
close(sync_pipe[0]);
|
||||||
unlink(cf.save_file);
|
unlink(cf.save_file);
|
||||||
|
g_free(cf.save_file);
|
||||||
cf.save_file = NULL;
|
cf.save_file = NULL;
|
||||||
simple_dialog(ESD_TYPE_WARN, NULL,
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
"Capture child process sent us a bad message");
|
"Capture child process sent us a bad message");
|
||||||
|
@ -231,7 +226,7 @@ do_capture(char *capfile_name)
|
||||||
}
|
}
|
||||||
if (byte_count == 0) {
|
if (byte_count == 0) {
|
||||||
/* Success. Open the capture file, and set up to read it. */
|
/* Success. Open the capture file, and set up to read it. */
|
||||||
err = start_tail_cap_file(cf.save_file, &cf);
|
err = start_tail_cap_file(cf.save_file, is_tempfile, &cf);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
/* We were able to open and set up to read the capture file;
|
/* We were able to open and set up to read the capture file;
|
||||||
arrange that our callback be called whenever it's possible
|
arrange that our callback be called whenever it's possible
|
||||||
|
@ -254,6 +249,7 @@ do_capture(char *capfile_name)
|
||||||
|
|
||||||
/* Don't unlink the save file - leave it around, for debugging
|
/* Don't unlink the save file - leave it around, for debugging
|
||||||
purposes. */
|
purposes. */
|
||||||
|
g_free(cf.save_file);
|
||||||
cf.save_file = NULL;
|
cf.save_file = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -281,6 +277,7 @@ do_capture(char *capfile_name)
|
||||||
|
|
||||||
/* Get rid of the save file - the capture never started. */
|
/* Get rid of the save file - the capture never started. */
|
||||||
unlink(cf.save_file);
|
unlink(cf.save_file);
|
||||||
|
g_free(cf.save_file);
|
||||||
cf.save_file = NULL;
|
cf.save_file = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,14 +291,16 @@ do_capture(char *capfile_name)
|
||||||
}
|
}
|
||||||
if (capture_succeeded) {
|
if (capture_succeeded) {
|
||||||
/* Capture succeeded; read in the capture file. */
|
/* Capture succeeded; read in the capture file. */
|
||||||
if ((err = open_cap_file(cf.save_file, &cf)) == 0) {
|
if ((err = open_cap_file(cf.save_file, is_tempfile, &cf)) == 0) {
|
||||||
/* Set the read filter to NULL. */
|
/* Set the read filter to NULL. */
|
||||||
cf.rfcode = NULL;
|
cf.rfcode = NULL;
|
||||||
err = read_cap_file(&cf);
|
err = read_cap_file(&cf);
|
||||||
set_menu_sensitivity("/File/Save", TRUE);
|
|
||||||
set_menu_sensitivity("/File/Save As...", FALSE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* We're not doing a capture any more, so we don't have a save
|
||||||
|
file. */
|
||||||
|
g_free(cf.save_file);
|
||||||
|
cf.save_file = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,6 +431,12 @@ cap_file_input_cb(gpointer data, gint source, GdkInputCondition condition)
|
||||||
/* Read what remains of the capture file, and finish the capture.
|
/* Read what remains of the capture file, and finish the capture.
|
||||||
XXX - do something if this fails? */
|
XXX - do something if this fails? */
|
||||||
err = finish_tail_cap_file(cf);
|
err = finish_tail_cap_file(cf);
|
||||||
|
|
||||||
|
/* We're not doing a capture any more, so we don't have a save
|
||||||
|
file. */
|
||||||
|
g_free(cf->save_file);
|
||||||
|
cf->save_file = NULL;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,6 +743,8 @@ error:
|
||||||
/* We couldn't even start the capture, so get rid of the capture
|
/* We couldn't even start the capture, so get rid of the capture
|
||||||
file. */
|
file. */
|
||||||
unlink(cf.save_file); /* silently ignore error */
|
unlink(cf.save_file); /* silently ignore error */
|
||||||
|
g_free(cf.save_file);
|
||||||
|
cf.save_file = NULL;
|
||||||
if (capture_child) {
|
if (capture_child) {
|
||||||
/* This is the child process for a sync mode capture.
|
/* This is the child process for a sync mode capture.
|
||||||
Send the error message to our parent, so they can display a
|
Send the error message to our parent, so they can display a
|
||||||
|
|
|
@ -177,6 +177,12 @@ allows a filter to be specified; when the capture file is read, the
|
||||||
filter is applied to all packets read from the file, and packets not
|
filter is applied to all packets read from the file, and packets not
|
||||||
matching the filter are discarded.
|
matching the filter are discarded.
|
||||||
|
|
||||||
|
=item File:Save, File:Save As
|
||||||
|
|
||||||
|
Save the current capture, or the packets currently displayed from that
|
||||||
|
capture, to a file. A check box lets you select whether to save all
|
||||||
|
packets, or just those that have passed the current display filter.
|
||||||
|
|
||||||
=item File:Print
|
=item File:Print
|
||||||
|
|
||||||
Prints, for all the packets in the current capture, the packet number,
|
Prints, for all the packets in the current capture, the packet number,
|
||||||
|
@ -217,9 +223,12 @@ live capture is in progress.
|
||||||
=item Display:Match Selected
|
=item Display:Match Selected
|
||||||
|
|
||||||
Creates and applies a display filter based on the data that is currently
|
Creates and applies a display filter based on the data that is currently
|
||||||
highlighted in the protocol tree. The display filter is based on absolute
|
highlighted in the protocol tree. If that data is a field that can be
|
||||||
offset within the packet, so could be unreliable if the packet contains
|
tested in a display filter expression, the display filter will test that
|
||||||
protocols with variable-length headers, like source-routed token-ring.
|
field; otherwise, the display filter will be based on absolute offset
|
||||||
|
within the packet, and so could be unreliable if the packet contains
|
||||||
|
protocols with variable-length headers, such as a source-routed
|
||||||
|
token-ring packet.
|
||||||
|
|
||||||
=item Display:Colorize Display
|
=item Display:Colorize Display
|
||||||
|
|
||||||
|
|
424
file.c
424
file.c
|
@ -1,7 +1,7 @@
|
||||||
/* file.c
|
/* file.c
|
||||||
* File I/O routines
|
* File I/O routines
|
||||||
*
|
*
|
||||||
* $Id: file.c,v 1.127 1999/11/30 07:27:36 guy Exp $
|
* $Id: file.c,v 1.128 1999/11/30 20:49:46 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@zing.org>
|
* By Gerald Combs <gerald@zing.org>
|
||||||
|
@ -108,11 +108,15 @@ static void wtap_dispatch_cb(u_char *, const struct wtap_pkthdr *, int,
|
||||||
static void freeze_clist(capture_file *cf);
|
static void freeze_clist(capture_file *cf);
|
||||||
static void thaw_clist(capture_file *cf);
|
static void thaw_clist(capture_file *cf);
|
||||||
|
|
||||||
|
static char *file_rename_error_message(int err);
|
||||||
|
static char *file_close_error_message(int err);
|
||||||
|
|
||||||
/* Update the progress bar this many times when reading a file. */
|
/* Update the progress bar this many times when reading a file. */
|
||||||
#define N_PROGBAR_UPDATES 100
|
#define N_PROGBAR_UPDATES 100
|
||||||
|
|
||||||
int
|
int
|
||||||
open_cap_file(char *fname, capture_file *cf) {
|
open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
|
||||||
|
{
|
||||||
wtap *wth;
|
wtap *wth;
|
||||||
int err;
|
int err;
|
||||||
FILE_T fh;
|
FILE_T fh;
|
||||||
|
@ -134,7 +138,7 @@ open_cap_file(char *fname, capture_file *cf) {
|
||||||
|
|
||||||
/* The open succeeded. Close whatever capture file we had open,
|
/* The open succeeded. Close whatever capture file we had open,
|
||||||
and fill in the information for this file. */
|
and fill in the information for this file. */
|
||||||
close_cap_file(cf, info_bar, file_ctx);
|
close_cap_file(cf, info_bar);
|
||||||
|
|
||||||
/* Initialize the table of conversations. */
|
/* Initialize the table of conversations. */
|
||||||
conversation_init();
|
conversation_init();
|
||||||
|
@ -147,11 +151,20 @@ open_cap_file(char *fname, capture_file *cf) {
|
||||||
cf->filed = fd;
|
cf->filed = fd;
|
||||||
cf->f_len = cf_stat.st_size;
|
cf->f_len = cf_stat.st_size;
|
||||||
|
|
||||||
/* set the file name because we need it to set the follow stream filter */
|
/* 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);
|
cf->filename = g_strdup(fname);
|
||||||
|
|
||||||
|
/* Indicate whether it's a permanent or temporary file. */
|
||||||
|
cf->is_tempfile = is_tempfile;
|
||||||
|
|
||||||
|
/* If it's a temporary capture buffer file, mark it as not saved. */
|
||||||
|
cf->user_saved = !is_tempfile;
|
||||||
|
|
||||||
cf->cd_t = wtap_file_type(cf->wth);
|
cf->cd_t = wtap_file_type(cf->wth);
|
||||||
cf->cd_t_desc = wtap_file_type_string(cf->wth);
|
cf->cd_t_desc = wtap_file_type_string(cf->wth);
|
||||||
|
cf->first_packet = TRUE;
|
||||||
cf->count = 0;
|
cf->count = 0;
|
||||||
cf->drops = 0;
|
cf->drops = 0;
|
||||||
cf->esec = 0;
|
cf->esec = 0;
|
||||||
|
@ -173,7 +186,8 @@ fail:
|
||||||
|
|
||||||
/* Reset everything to a pristine state */
|
/* Reset everything to a pristine state */
|
||||||
void
|
void
|
||||||
close_cap_file(capture_file *cf, void *w, guint context) {
|
close_cap_file(capture_file *cf, void *w)
|
||||||
|
{
|
||||||
frame_data *fd, *fd_next;
|
frame_data *fd, *fd_next;
|
||||||
|
|
||||||
if (cf->fh) {
|
if (cf->fh) {
|
||||||
|
@ -184,6 +198,17 @@ close_cap_file(capture_file *cf, void *w, guint context) {
|
||||||
wtap_close(cf->wth);
|
wtap_close(cf->wth);
|
||||||
cf->wth = NULL;
|
cf->wth = NULL;
|
||||||
}
|
}
|
||||||
|
/* We have no file open... */
|
||||||
|
if (cf->filename != NULL) {
|
||||||
|
/* If it's a temporary file, remove it. */
|
||||||
|
if (cf->is_tempfile)
|
||||||
|
unlink(cf->filename);
|
||||||
|
g_free(cf->filename);
|
||||||
|
cf->filename = NULL;
|
||||||
|
}
|
||||||
|
/* ...which means we have nothing to save. */
|
||||||
|
cf->user_saved = FALSE;
|
||||||
|
|
||||||
for (fd = cf->plist; fd != NULL; fd = fd_next) {
|
for (fd = cf->plist; fd != NULL; fd = fd_next) {
|
||||||
fd_next = fd->next;
|
fd_next = fd->next;
|
||||||
g_free(fd);
|
g_free(fd);
|
||||||
|
@ -196,10 +221,15 @@ close_cap_file(capture_file *cf, void *w, guint context) {
|
||||||
cf->plist_end = NULL;
|
cf->plist_end = NULL;
|
||||||
unselect_packet(cf); /* nothing to select */
|
unselect_packet(cf); /* nothing to select */
|
||||||
|
|
||||||
|
/* Clear the packet list. */
|
||||||
gtk_clist_freeze(GTK_CLIST(packet_list));
|
gtk_clist_freeze(GTK_CLIST(packet_list));
|
||||||
gtk_clist_clear(GTK_CLIST(packet_list));
|
gtk_clist_clear(GTK_CLIST(packet_list));
|
||||||
gtk_clist_thaw(GTK_CLIST(packet_list));
|
gtk_clist_thaw(GTK_CLIST(packet_list));
|
||||||
gtk_statusbar_pop(GTK_STATUSBAR(w), context);
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
/* Disable all menu items that make sense only if you have a capture. */
|
/* Disable all menu items that make sense only if you have a capture. */
|
||||||
set_menu_sensitivity("/File/Save", FALSE);
|
set_menu_sensitivity("/File/Save", FALSE);
|
||||||
|
@ -227,7 +257,7 @@ set_statusbar_filename(capture_file *cf)
|
||||||
gchar *done_fmt = " File: %s Drops: %u";
|
gchar *done_fmt = " File: %s Drops: %u";
|
||||||
gchar *done_msg;
|
gchar *done_msg;
|
||||||
|
|
||||||
if (cf->user_saved || !cf->save_file) {
|
if (!cf->is_tempfile) {
|
||||||
/* Get the last component of the file name, and put that in the
|
/* Get the last component of the file name, and put that in the
|
||||||
status bar. */
|
status bar. */
|
||||||
if ((name_ptr = (gchar *) strrchr(cf->filename, '/')) == NULL)
|
if ((name_ptr = (gchar *) strrchr(cf->filename, '/')) == NULL)
|
||||||
|
@ -248,7 +278,8 @@ set_statusbar_filename(capture_file *cf)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
read_cap_file(capture_file *cf) {
|
read_cap_file(capture_file *cf)
|
||||||
|
{
|
||||||
gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
|
gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
|
||||||
int success;
|
int success;
|
||||||
int err;
|
int err;
|
||||||
|
@ -292,13 +323,17 @@ read_cap_file(capture_file *cf) {
|
||||||
gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
|
gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
|
||||||
|
|
||||||
gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
|
gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
|
||||||
|
|
||||||
set_statusbar_filename(cf);
|
set_statusbar_filename(cf);
|
||||||
|
|
||||||
/* Enable menu items that make sense if you have a capture. */
|
/* Enable menu items that make sense if you have a capture file you've
|
||||||
|
finished reading. */
|
||||||
|
set_menu_sensitivity("/File/Save", !cf->user_saved);
|
||||||
|
set_menu_sensitivity("/File/Save As...", TRUE);
|
||||||
set_menu_sensitivity("/File/Close", TRUE);
|
set_menu_sensitivity("/File/Close", TRUE);
|
||||||
set_menu_sensitivity("/File/Reload", TRUE);
|
set_menu_sensitivity("/File/Reload", TRUE);
|
||||||
set_menu_sensitivity("/File/Print...", TRUE);
|
set_menu_sensitivity("/File/Print...", TRUE);
|
||||||
|
|
||||||
|
/* Enable menu items that make sense if you have some captured packets. */
|
||||||
set_menu_sensitivity("/Display/Options...", TRUE);
|
set_menu_sensitivity("/Display/Options...", TRUE);
|
||||||
set_menu_sensitivity("/Display/Match Selected", TRUE);
|
set_menu_sensitivity("/Display/Match Selected", TRUE);
|
||||||
set_menu_sensitivity("/Display/Colorize Display...", TRUE);
|
set_menu_sensitivity("/Display/Colorize Display...", TRUE);
|
||||||
|
@ -343,13 +378,23 @@ read_cap_file(capture_file *cf) {
|
||||||
|
|
||||||
#ifdef HAVE_LIBPCAP
|
#ifdef HAVE_LIBPCAP
|
||||||
int
|
int
|
||||||
start_tail_cap_file(char *fname, capture_file *cf) {
|
start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
|
||||||
|
{
|
||||||
int err;
|
int err;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
err = open_cap_file(fname, cf);
|
err = open_cap_file(fname, is_tempfile, cf);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
|
/* Disable menu items that make sense only if you have a capture
|
||||||
|
file you've finished reading. */
|
||||||
set_menu_sensitivity("/File/Open...", FALSE);
|
set_menu_sensitivity("/File/Open...", FALSE);
|
||||||
|
|
||||||
|
/* Disable menu items that make sense only if you're not currently
|
||||||
|
running a capture. */
|
||||||
|
set_menu_sensitivity("/Capture/Start...", FALSE);
|
||||||
|
|
||||||
|
/* Enable menu items that make sense if you have some captured
|
||||||
|
packets (yes, I know, we don't have any *yet*). */
|
||||||
set_menu_sensitivity("/Display/Options...", TRUE);
|
set_menu_sensitivity("/Display/Options...", TRUE);
|
||||||
set_menu_sensitivity("/Display/Match Selected", TRUE);
|
set_menu_sensitivity("/Display/Match Selected", TRUE);
|
||||||
set_menu_sensitivity("/Display/Colorize Display...", TRUE);
|
set_menu_sensitivity("/Display/Colorize Display...", TRUE);
|
||||||
|
@ -358,7 +403,6 @@ start_tail_cap_file(char *fname, capture_file *cf) {
|
||||||
set_menu_sensitivity("/Tools/Follow TCP Stream", TRUE);
|
set_menu_sensitivity("/Tools/Follow TCP Stream", TRUE);
|
||||||
set_menu_sensitivity("/Tools/Graph", TRUE);
|
set_menu_sensitivity("/Tools/Graph", TRUE);
|
||||||
set_menu_sensitivity("/Tools/Summary", TRUE);
|
set_menu_sensitivity("/Tools/Summary", TRUE);
|
||||||
set_menu_sensitivity("/Capture/Start...", FALSE);
|
|
||||||
|
|
||||||
for (i = 0; i < cf->cinfo.num_cols; i++) {
|
for (i = 0; i < cf->cinfo.num_cols; i++) {
|
||||||
if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
|
if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
|
||||||
|
@ -417,6 +461,9 @@ finish_tail_cap_file(capture_file *cf)
|
||||||
wtap_close(cf->wth);
|
wtap_close(cf->wth);
|
||||||
cf->wth = NULL;
|
cf->wth = NULL;
|
||||||
|
|
||||||
|
/* Pop the "<live capture in progress>" message off the status bar. */
|
||||||
|
gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
|
||||||
|
|
||||||
set_statusbar_filename(cf);
|
set_statusbar_filename(cf);
|
||||||
|
|
||||||
/* Restore the "File/Open" menu item. */
|
/* Restore the "File/Open" menu item. */
|
||||||
|
@ -424,7 +471,8 @@ finish_tail_cap_file(capture_file *cf)
|
||||||
|
|
||||||
/* Enable menu items that make sense if you have a capture file
|
/* Enable menu items that make sense if you have a capture file
|
||||||
you've finished reading. */
|
you've finished reading. */
|
||||||
set_menu_sensitivity("/File/Save", TRUE);
|
set_menu_sensitivity("/File/Save", !cf->user_saved);
|
||||||
|
set_menu_sensitivity("/File/Save As...", TRUE);
|
||||||
set_menu_sensitivity("/File/Close", TRUE);
|
set_menu_sensitivity("/File/Close", TRUE);
|
||||||
set_menu_sensitivity("/File/Reload", TRUE);
|
set_menu_sensitivity("/File/Reload", TRUE);
|
||||||
set_menu_sensitivity("/File/Print...", TRUE);
|
set_menu_sensitivity("/File/Print...", TRUE);
|
||||||
|
@ -852,6 +900,19 @@ wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
|
||||||
gtk_main_iteration();
|
gtk_main_iteration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cf->first_packet) {
|
||||||
|
/* Tentatively make the encapsulation type the type of the first
|
||||||
|
packet. */
|
||||||
|
cf->lnk_t = phdr->pkt_encap;
|
||||||
|
} else {
|
||||||
|
/* If this packet's encapsulation type isn't the same as the type
|
||||||
|
type we've chosen so far, make the type for this file
|
||||||
|
WTAP_ENCAP_PER_PACKET, because there is no single encapsulation
|
||||||
|
type for the entire file. */
|
||||||
|
if (cf->lnk_t != phdr->pkt_encap)
|
||||||
|
cf->lnk_t = WTAP_ENCAP_PER_PACKET;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate the next list entry, and add it to the list. */
|
/* Allocate the next list entry, and add it to the list. */
|
||||||
fdata = (frame_data *) g_malloc(sizeof(frame_data));
|
fdata = (frame_data *) g_malloc(sizeof(frame_data));
|
||||||
|
|
||||||
|
@ -1509,92 +1570,201 @@ thaw_clist(capture_file *cf)
|
||||||
gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
|
gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tries to mv a file. If unsuccessful, tries to cp the file.
|
|
||||||
* Returns 0 on failure to do either, 1 on success of either
|
|
||||||
*/
|
|
||||||
int
|
int
|
||||||
file_mv(char *from, char *to)
|
save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
|
||||||
|
guint save_format)
|
||||||
{
|
{
|
||||||
|
gchar *from_filename;
|
||||||
|
gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
|
||||||
|
gchar *err_fmt = " Error: Could not save to '%s'";
|
||||||
|
size_t msg_len;
|
||||||
|
int err;
|
||||||
|
gboolean do_copy;
|
||||||
|
int from_fd, to_fd, nread, nwritten;
|
||||||
|
wtap_dumper *pdh;
|
||||||
|
frame_data *fd;
|
||||||
|
struct wtap_pkthdr hdr;
|
||||||
|
guint8 pd[65536];
|
||||||
|
|
||||||
#define COPY_BUFFER_SIZE 8192
|
if ((name_ptr = (gchar *) strrchr(fname, '/')) == NULL)
|
||||||
|
name_ptr = fname;
|
||||||
|
else
|
||||||
|
name_ptr++;
|
||||||
|
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);
|
||||||
|
g_free(save_msg);
|
||||||
|
|
||||||
int retval;
|
if (!save_filtered && save_format == cf->cd_t) {
|
||||||
|
/* We're not filtering packets, and we're saving it in the format
|
||||||
|
it's already in, so we can just move or copy the raw data. */
|
||||||
|
|
||||||
#ifndef WIN32
|
/* In this branch, we set "err" only if we get an error, so we
|
||||||
/* try a hard link */
|
must first clear it. */
|
||||||
retval = link(from, to);
|
err = 0;
|
||||||
|
if (cf->is_tempfile) {
|
||||||
/* or try a copy */
|
/* The file being saved is a temporary file from a live
|
||||||
if (retval < 0) {
|
capture, so it doesn't need to stay around under that name;
|
||||||
#endif
|
first, try renaming the capture buffer file to the new name. */
|
||||||
retval = file_cp(from, to);
|
if (rename(cf->filename, fname) == 0) {
|
||||||
if (!retval) {
|
/* That succeeded - there's no need to copy the source file. */
|
||||||
return 0;
|
from_filename = NULL;
|
||||||
}
|
do_copy = FALSE;
|
||||||
#ifndef WIN32
|
} else {
|
||||||
|
if (errno == EXDEV) {
|
||||||
|
/* They're on different file systems, so we have to copy the
|
||||||
|
file. */
|
||||||
|
do_copy = TRUE;
|
||||||
|
from_filename = cf->filename;
|
||||||
|
} 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?) */
|
||||||
|
err = errno;
|
||||||
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
|
file_rename_error_message(err), fname);
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
|
} else {
|
||||||
|
/* It's a permanent file, so we should copy it, and not remove the
|
||||||
|
original. */
|
||||||
|
do_copy = TRUE;
|
||||||
|
from_filename = cf->filename;
|
||||||
|
}
|
||||||
|
|
||||||
unlink(from);
|
/* Copy the file, if we haven't moved it. */
|
||||||
return 1;
|
if (do_copy) {
|
||||||
}
|
/* Copy the raw bytes of the file. */
|
||||||
|
from_fd = open(from_filename, O_RDONLY);
|
||||||
|
if (from_fd < 0) {
|
||||||
|
err = errno;
|
||||||
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
|
file_open_error_message(err, TRUE), from_filename);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/* Copies a file.
|
to_fd = creat(fname, 0644);
|
||||||
* Returns 0 on failure to do either, 1 on success of either
|
if (to_fd < 0) {
|
||||||
*/
|
err = errno;
|
||||||
int
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
file_cp(char *from, char *to)
|
file_open_error_message(err, TRUE), fname);
|
||||||
{
|
close(from_fd);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
#define COPY_BUFFER_SIZE 8192
|
while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
|
||||||
|
nwritten = write(to_fd, pd, nread);
|
||||||
int from_fd, to_fd, nread, nwritten;
|
if (nwritten < nread) {
|
||||||
char *buffer;
|
if (nwritten < 0)
|
||||||
|
err = errno;
|
||||||
buffer = g_malloc(COPY_BUFFER_SIZE);
|
else
|
||||||
|
err = WTAP_ERR_SHORT_WRITE;
|
||||||
from_fd = open(from, O_RDONLY);
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
if (from_fd < 0) {
|
file_write_error_message(err), fname);
|
||||||
simple_dialog(ESD_TYPE_WARN, NULL,
|
close(from_fd);
|
||||||
file_open_error_message(errno, TRUE), from);
|
close(to_fd);
|
||||||
return 0;
|
goto done;
|
||||||
}
|
|
||||||
|
|
||||||
to_fd = creat(to, 0644);
|
|
||||||
if (to_fd < 0) {
|
|
||||||
simple_dialog(ESD_TYPE_WARN, NULL,
|
|
||||||
file_open_error_message(errno, TRUE), to);
|
|
||||||
close(from_fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while( (nread = read(from_fd, buffer, COPY_BUFFER_SIZE)) > 0) {
|
|
||||||
nwritten = write(to_fd, buffer, nread);
|
|
||||||
if (nwritten < nread) {
|
|
||||||
if (nwritten < 0) {
|
|
||||||
simple_dialog(ESD_TYPE_WARN, NULL,
|
|
||||||
file_write_error_message(errno), to);
|
|
||||||
} else {
|
|
||||||
simple_dialog(ESD_TYPE_WARN, NULL,
|
|
||||||
"The file \"%s\" could not be saved: tried writing %d, wrote %d.\n",
|
|
||||||
to, nread, nwritten);
|
|
||||||
}
|
|
||||||
close(from_fd);
|
|
||||||
close(to_fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nread < 0) {
|
|
||||||
simple_dialog(ESD_TYPE_WARN, NULL,
|
|
||||||
file_read_error_message(errno), from);
|
|
||||||
close(from_fd);
|
|
||||||
close(to_fd);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (nread < 0) {
|
||||||
|
err = errno;
|
||||||
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
|
file_read_error_message(err), from_filename);
|
||||||
close(from_fd);
|
close(from_fd);
|
||||||
close(to_fd);
|
close(to_fd);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
close(from_fd);
|
||||||
|
if (close(to_fd) < 0) {
|
||||||
|
err = errno;
|
||||||
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
|
file_close_error_message(err), fname);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Either we're filtering packets, or we're saving in a different
|
||||||
|
format; we can't do that by copying or moving the capture file,
|
||||||
|
we have to do it by writing the packets out in Wiretap. */
|
||||||
|
pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
|
||||||
|
if (pdh == NULL) {
|
||||||
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
|
file_open_error_message(err, TRUE), fname);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
/* XXX - have a way to save only the packets currently selected by
|
||||||
|
the display filter.
|
||||||
|
|
||||||
|
If we do that, should we make that file the current file? If so,
|
||||||
|
it means we can no longer get at the other packets. What does
|
||||||
|
NetMon do? */
|
||||||
|
for (fd = cf->plist; fd != NULL; fd = fd->next) {
|
||||||
|
/* XXX - do a progress bar */
|
||||||
|
if (!save_filtered || fd->passed_dfilter) {
|
||||||
|
/* Either we're saving all frames, or we're saving filtered frames
|
||||||
|
and this one passed the display filter - save it. */
|
||||||
|
hdr.ts.tv_sec = fd->abs_secs;
|
||||||
|
hdr.ts.tv_usec = fd->abs_usecs;
|
||||||
|
hdr.caplen = fd->cap_len;
|
||||||
|
hdr.len = fd->pkt_len;
|
||||||
|
hdr.pkt_encap = fd->lnk_t;
|
||||||
|
wtap_seek_read(cf->cd_t, cf->fh, fd->file_off, pd, fd->cap_len);
|
||||||
|
|
||||||
|
if (!wtap_dump(pdh, &hdr, pd, &err)) {
|
||||||
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
|
file_write_error_message(err), fname);
|
||||||
|
wtap_dump_close(pdh, &err);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wtap_dump_close(pdh, &err)) {
|
||||||
|
simple_dialog(ESD_TYPE_WARN, NULL,
|
||||||
|
file_close_error_message(err), fname);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
/* Pop the "Saving:" message off the status bar. */
|
||||||
|
gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
|
||||||
|
if (err == 0) {
|
||||||
|
if (!save_filtered) {
|
||||||
|
/* We saved the entire capture, not just some packets from it.
|
||||||
|
Open and read the file we saved it 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. */
|
||||||
|
cf->user_saved = TRUE;
|
||||||
|
|
||||||
|
if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
|
||||||
|
/* XXX - report errors if this fails? */
|
||||||
|
err = read_cap_file(cf);
|
||||||
|
set_menu_sensitivity("/File/Save", FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msg_len = strlen(name_ptr) + strlen(err_fmt) + 2;
|
||||||
|
save_msg = g_malloc(msg_len);
|
||||||
|
snprintf(save_msg, msg_len, err_fmt, name_ptr);
|
||||||
|
gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
|
||||||
|
g_free(save_msg);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
|
@ -1611,9 +1781,21 @@ file_open_error_message(int err, int for_writing)
|
||||||
|
|
||||||
case WTAP_ERR_FILE_UNKNOWN_FORMAT:
|
case WTAP_ERR_FILE_UNKNOWN_FORMAT:
|
||||||
case WTAP_ERR_UNSUPPORTED:
|
case WTAP_ERR_UNSUPPORTED:
|
||||||
|
/* Seen only when opening a capture file for reading. */
|
||||||
errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
|
errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
|
||||||
|
/* Seen only when opening a capture file for writing. */
|
||||||
|
errmsg = "Ethereal does not support writing capture files in that format.";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WTAP_ERR_UNSUPPORTED_ENCAP:
|
||||||
|
case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
|
||||||
|
/* Seen only when opening a capture file for writing. */
|
||||||
|
errmsg = "Ethereal cannot save this capture in that format.";
|
||||||
|
break;
|
||||||
|
|
||||||
case WTAP_ERR_BAD_RECORD:
|
case WTAP_ERR_BAD_RECORD:
|
||||||
errmsg = "The file \"%s\" appears to be damaged or corrupt.";
|
errmsg = "The file \"%s\" appears to be damaged or corrupt.";
|
||||||
break;
|
break;
|
||||||
|
@ -1630,6 +1812,10 @@ file_open_error_message(int err, int for_writing)
|
||||||
" in the middle of a packet.";
|
" in the middle of a packet.";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WTAP_ERR_SHORT_WRITE:
|
||||||
|
errmsg = "A full header couldn't be written to the file \"%s\".";
|
||||||
|
break;
|
||||||
|
|
||||||
case ENOENT:
|
case ENOENT:
|
||||||
if (for_writing)
|
if (for_writing)
|
||||||
errmsg = "The path to the file \"%s\" does not exist.";
|
errmsg = "The path to the file \"%s\" does not exist.";
|
||||||
|
@ -1653,6 +1839,31 @@ file_open_error_message(int err, int for_writing)
|
||||||
return errmsg;
|
return errmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
file_rename_error_message(int err)
|
||||||
|
{
|
||||||
|
char *errmsg;
|
||||||
|
static char errmsg_errno[1024+1];
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
|
||||||
|
case ENOENT:
|
||||||
|
errmsg = "The path to the file \"%s\" does not exist.";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EACCES:
|
||||||
|
errmsg = "You do not have permission to move the capture file to \"%s\".";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
sprintf(errmsg_errno, "The file \"%%s\" could not be moved: %s.",
|
||||||
|
wtap_strerror(err));
|
||||||
|
errmsg = errmsg_errno;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return errmsg;
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
file_read_error_message(int err)
|
file_read_error_message(int err)
|
||||||
{
|
{
|
||||||
|
@ -1689,3 +1900,42 @@ file_write_error_message(int err)
|
||||||
}
|
}
|
||||||
return errmsg;
|
return errmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for write errors - if the file is being written to an NFS server,
|
||||||
|
a write error may not show up until the file is closed, as NFS clients
|
||||||
|
might not send writes to the server until the "write()" call finishes,
|
||||||
|
so that the write may fail on the server but the "write()" may succeed. */
|
||||||
|
static char *
|
||||||
|
file_close_error_message(int err)
|
||||||
|
{
|
||||||
|
char *errmsg;
|
||||||
|
static char errmsg_errno[1024+1];
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
|
||||||
|
case WTAP_ERR_CANT_CLOSE:
|
||||||
|
errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WTAP_ERR_SHORT_WRITE:
|
||||||
|
errmsg = "Not all the data could be written to the file \"%s\".";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENOSPC:
|
||||||
|
errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef EDQUOT
|
||||||
|
case EDQUOT:
|
||||||
|
errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
sprintf(errmsg_errno, "An error occurred while closing the file \"%%s\": %s.",
|
||||||
|
wtap_strerror(err));
|
||||||
|
errmsg = errmsg_errno;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return errmsg;
|
||||||
|
}
|
||||||
|
|
14
file.h
14
file.h
|
@ -1,7 +1,7 @@
|
||||||
/* file.h
|
/* file.h
|
||||||
* Definitions for file structures and routines
|
* Definitions for file structures and routines
|
||||||
*
|
*
|
||||||
* $Id: file.h,v 1.57 1999/11/30 07:27:37 guy Exp $
|
* $Id: file.h,v 1.58 1999/11/30 20:49:47 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@zing.org>
|
* By Gerald Combs <gerald@zing.org>
|
||||||
|
@ -77,9 +77,13 @@ typedef struct _capture_file {
|
||||||
FILE_T fh; /* File handle for capture file */
|
FILE_T fh; /* File handle for capture file */
|
||||||
int filed; /* File descriptor of capture file */
|
int filed; /* File descriptor of capture file */
|
||||||
gchar *filename; /* Name of capture file */
|
gchar *filename; /* Name of capture file */
|
||||||
|
gboolean is_tempfile; /* Is capture file a temporary file? */
|
||||||
|
gboolean user_saved;/* If capture file is temporary, has it been saved by user yet? */
|
||||||
long f_len; /* Length of capture file */
|
long f_len; /* Length of capture file */
|
||||||
guint16 cd_t; /* File type of capture file */
|
guint16 cd_t; /* File type of capture file */
|
||||||
const gchar *cd_t_desc; /* Description of that file type */
|
const gchar *cd_t_desc; /* Description of that file type */
|
||||||
|
gboolean first_packet; /* TRUE if we're looking at the first packet */
|
||||||
|
int lnk_t; /* Link-layer type with which to save capture */
|
||||||
guint32 vers; /* Version. For tcpdump minor is appended to major */
|
guint32 vers; /* Version. For tcpdump minor is appended to major */
|
||||||
guint32 count; /* Packet count */
|
guint32 count; /* Packet count */
|
||||||
gfloat unfiltered_count; /* used for dfilter progress bar */
|
gfloat unfiltered_count; /* used for dfilter progress bar */
|
||||||
|
@ -93,7 +97,6 @@ typedef struct _capture_file {
|
||||||
gchar *iface; /* Interface */
|
gchar *iface; /* Interface */
|
||||||
gchar *save_file; /* File that user saved capture to */
|
gchar *save_file; /* File that user saved capture to */
|
||||||
int save_file_fd; /* File descriptor for saved file */
|
int save_file_fd; /* File descriptor for saved file */
|
||||||
gint user_saved;/* Was capture file saved by user yet? */
|
|
||||||
wtap *wth; /* Wiretap session */
|
wtap *wth; /* Wiretap session */
|
||||||
dfilter *rfcode; /* Compiled read filter program */
|
dfilter *rfcode; /* Compiled read filter program */
|
||||||
gchar *dfilter; /* Display filter string */
|
gchar *dfilter; /* Display filter string */
|
||||||
|
@ -118,13 +121,14 @@ typedef struct _capture_file {
|
||||||
FILE *print_fh; /* File we're printing to */
|
FILE *print_fh; /* File we're printing to */
|
||||||
} capture_file;
|
} capture_file;
|
||||||
|
|
||||||
int open_cap_file(char *, capture_file *);
|
int open_cap_file(char *, gboolean, capture_file *);
|
||||||
void close_cap_file(capture_file *, void *, guint);
|
void close_cap_file(capture_file *, void *);
|
||||||
int read_cap_file(capture_file *);
|
int read_cap_file(capture_file *);
|
||||||
int start_tail_cap_file(char *, capture_file *);
|
int start_tail_cap_file(char *, gboolean, capture_file *);
|
||||||
int continue_tail_cap_file(capture_file *, int);
|
int continue_tail_cap_file(capture_file *, int);
|
||||||
int finish_tail_cap_file(capture_file *);
|
int finish_tail_cap_file(capture_file *);
|
||||||
/* size_t read_frame_header(capture_file *); */
|
/* size_t read_frame_header(capture_file *); */
|
||||||
|
int save_cap_file(char *, capture_file *, gboolean, guint);
|
||||||
|
|
||||||
int filter_packets(capture_file *cf, gchar *dfilter);
|
int filter_packets(capture_file *cf, gchar *dfilter);
|
||||||
void colorize_packets(capture_file *);
|
void colorize_packets(capture_file *);
|
||||||
|
|
135
gtk/file_dlg.c
135
gtk/file_dlg.c
|
@ -1,7 +1,7 @@
|
||||||
/* file_dlg.c
|
/* file_dlg.c
|
||||||
* Dialog boxes for handling files
|
* Dialog boxes for handling files
|
||||||
*
|
*
|
||||||
* $Id: file_dlg.c,v 1.11 1999/10/20 22:36:05 gram Exp $
|
* $Id: file_dlg.c,v 1.12 1999/11/30 20:50:14 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@zing.org>
|
* By Gerald Combs <gerald@zing.org>
|
||||||
|
@ -64,8 +64,9 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define FILTER_CB_KEY "filter_check_button"
|
||||||
|
|
||||||
static void file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs);
|
static void file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs);
|
||||||
static void file_save_ok_cb(GtkWidget *w, GtkFileSelection *fs);
|
|
||||||
static void file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs);
|
static void file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs);
|
||||||
|
|
||||||
/* Open a file */
|
/* Open a file */
|
||||||
|
@ -130,7 +131,7 @@ file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to open the capture file. */
|
/* Try to open the capture file. */
|
||||||
if ((err = open_cap_file(cf_name, &cf)) != 0) {
|
if ((err = open_cap_file(cf_name, FALSE, &cf)) != 0) {
|
||||||
/* We couldn't open it; don't dismiss the open dialog box,
|
/* We couldn't open it; don't dismiss the open dialog box,
|
||||||
just leave it around so that the user can, after they
|
just leave it around so that the user can, after they
|
||||||
dismiss the alert box popped up for the open error,
|
dismiss the alert box popped up for the open error,
|
||||||
|
@ -166,44 +167,46 @@ file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
|
||||||
else {
|
else {
|
||||||
last_open_dir = NULL;
|
last_open_dir = NULL;
|
||||||
}
|
}
|
||||||
set_menu_sensitivity("/File/Save", FALSE);
|
|
||||||
set_menu_sensitivity("/File/Save As...", TRUE);
|
|
||||||
g_free(cf_name);
|
g_free(cf_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close a file */
|
/* Close a file */
|
||||||
void
|
void
|
||||||
file_close_cmd_cb(GtkWidget *widget, gpointer data) {
|
file_close_cmd_cb(GtkWidget *widget, gpointer data) {
|
||||||
close_cap_file(&cf, info_bar, file_ctx);
|
close_cap_file(&cf, info_bar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
file_save_cmd_cb(GtkWidget *w, gpointer data) {
|
file_save_cmd_cb(GtkWidget *w, gpointer data) {
|
||||||
file_sel = gtk_file_selection_new ("Ethereal: Save Capture File");
|
file_sel = gtk_file_selection_new ("Ethereal: Save Capture File");
|
||||||
|
|
||||||
/* Connect the ok_button to file_save_ok_cb function and pass along a
|
|
||||||
pointer to the file selection box widget */
|
|
||||||
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button),
|
|
||||||
"clicked", (GtkSignalFunc) file_save_ok_cb, file_sel );
|
|
||||||
|
|
||||||
/* Connect the cancel_button to destroy the widget */
|
/* If the file's already been saved, do nothing. */
|
||||||
gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION
|
if (cf.user_saved)
|
||||||
(file_sel)->cancel_button), "clicked", (GtkSignalFunc)
|
return;
|
||||||
gtk_widget_destroy, GTK_OBJECT (file_sel));
|
|
||||||
|
|
||||||
gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), "");
|
/* Do a "Save As". */
|
||||||
|
file_save_as_cmd_cb(w, data);
|
||||||
gtk_widget_show(file_sel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
file_save_as_cmd_cb(GtkWidget *w, gpointer data) {
|
file_save_as_cmd_cb(GtkWidget *w, gpointer data) {
|
||||||
|
GtkWidget *ok_bt, *filter_cb;
|
||||||
|
|
||||||
file_sel = gtk_file_selection_new ("Ethereal: Save Capture File As");
|
file_sel = gtk_file_selection_new ("Ethereal: Save Capture File As");
|
||||||
|
|
||||||
/* Connect the ok_button to file_save_as_ok_cb function and pass along a
|
/* Connect the ok_button to file_save_as_ok_cb function and pass along a
|
||||||
pointer to the file selection box widget */
|
pointer to the file selection box widget */
|
||||||
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button),
|
ok_bt = GTK_FILE_SELECTION (file_sel)->ok_button;
|
||||||
"clicked", (GtkSignalFunc) file_save_as_ok_cb, file_sel );
|
gtk_signal_connect (GTK_OBJECT (ok_bt), "clicked",
|
||||||
|
(GtkSignalFunc) file_save_as_ok_cb, file_sel );
|
||||||
|
|
||||||
|
filter_cb = gtk_check_button_new_with_label("Save only packets currently being displayed");
|
||||||
|
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(filter_cb), FALSE);
|
||||||
|
gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_sel)->action_area),
|
||||||
|
filter_cb, FALSE, FALSE, 0);
|
||||||
|
gtk_widget_show(filter_cb);
|
||||||
|
|
||||||
|
gtk_object_set_data(GTK_OBJECT(ok_bt), FILTER_CB_KEY, filter_cb);
|
||||||
|
|
||||||
/* Connect the cancel_button to destroy the widget */
|
/* Connect the cancel_button to destroy the widget */
|
||||||
gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION
|
gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION
|
||||||
|
@ -214,46 +217,27 @@ file_save_as_cmd_cb(GtkWidget *w, gpointer data) {
|
||||||
gtk_widget_show(file_sel);
|
gtk_widget_show(file_sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
file_save_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
|
|
||||||
gchar *cf_name;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
|
|
||||||
gtk_widget_hide(GTK_WIDGET (fs));
|
|
||||||
gtk_widget_destroy(GTK_WIDGET (fs));
|
|
||||||
|
|
||||||
if (!file_mv(cf.save_file, cf_name))
|
|
||||||
return;
|
|
||||||
|
|
||||||
g_free(cf.save_file);
|
|
||||||
cf.save_file = g_strdup(cf_name);
|
|
||||||
cf.user_saved = 1;
|
|
||||||
if ((err = open_cap_file(cf_name, &cf)) == 0) {
|
|
||||||
err = read_cap_file(&cf);
|
|
||||||
set_menu_sensitivity("/File/Save", FALSE);
|
|
||||||
set_menu_sensitivity("/File/Save As...", TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
|
file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
|
||||||
gchar *cf_name;
|
gchar *cf_name;
|
||||||
int err;
|
GtkWidget *button;
|
||||||
|
gboolean filtered;
|
||||||
|
|
||||||
cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
|
cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
|
||||||
gtk_widget_hide(GTK_WIDGET (fs));
|
gtk_widget_hide(GTK_WIDGET (fs));
|
||||||
gtk_widget_destroy(GTK_WIDGET (fs));
|
gtk_widget_destroy(GTK_WIDGET (fs));
|
||||||
if (!file_cp(cf.filename, cf_name))
|
|
||||||
return;
|
button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(w),
|
||||||
g_free(cf.filename);
|
FILTER_CB_KEY);
|
||||||
cf.filename = g_strdup(cf_name);
|
filtered = GTK_TOGGLE_BUTTON (button)->active;
|
||||||
cf.user_saved = 1;
|
|
||||||
if ((err = open_cap_file(cf.filename, &cf)) == 0) {
|
/* Write out the packets (all, or only the ones that are currently
|
||||||
err = read_cap_file(&cf);
|
displayed) to the file with the specified name. */
|
||||||
set_menu_sensitivity("/File/Save", FALSE);
|
save_cap_file(cf_name, &cf, filtered, WTAP_FILE_PCAP);
|
||||||
set_menu_sensitivity("/File/Save As...", TRUE);
|
|
||||||
}
|
/* If "save_cap_file()" saved the file name we handed it, it saved
|
||||||
|
a copy, so we should free up our copy. */
|
||||||
|
g_free(cf_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reload a file using the current read and display filters */
|
/* Reload a file using the current read and display filters */
|
||||||
|
@ -261,13 +245,40 @@ void
|
||||||
file_reload_cmd_cb(GtkWidget *w, gpointer data) {
|
file_reload_cmd_cb(GtkWidget *w, gpointer data) {
|
||||||
/*GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);*/
|
/*GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);*/
|
||||||
GtkWidget *filter_te;
|
GtkWidget *filter_te;
|
||||||
|
gchar *filename;
|
||||||
|
gboolean is_tempfile;
|
||||||
|
|
||||||
filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
|
filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
|
||||||
|
|
||||||
if (cf.dfilter) g_free(cf.dfilter);
|
if (cf.dfilter)
|
||||||
|
g_free(cf.dfilter);
|
||||||
cf.dfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
|
cf.dfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
|
||||||
if (open_cap_file(cf.filename, &cf) == 0)
|
|
||||||
read_cap_file(&cf);
|
|
||||||
/* XXX - change the menu if the open fails? */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* If the file could be opened, "open_cap_file()" calls "close_cap_file()"
|
||||||
|
to get rid of state for the old capture file before filling in state
|
||||||
|
for the new capture file. "close_cap_file()" 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, "close_cap_file()" will free "cf.filename", so we must make
|
||||||
|
a copy of it first. */
|
||||||
|
filename = strdup(cf.filename);
|
||||||
|
is_tempfile = cf.is_tempfile;
|
||||||
|
cf.is_tempfile = FALSE;
|
||||||
|
if (open_cap_file(filename, is_tempfile, &cf) == 0)
|
||||||
|
read_cap_file(&cf);
|
||||||
|
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 "open_cap_file()" will do that;
|
||||||
|
make sure it does! */
|
||||||
|
cf.is_tempfile = is_tempfile;
|
||||||
|
}
|
||||||
|
/* "open_cap_file()" made a copy of the file name we handed it, so
|
||||||
|
we should free up our copy. */
|
||||||
|
g_free(filename);
|
||||||
|
}
|
||||||
|
|
20
gtk/main.c
20
gtk/main.c
|
@ -1,6 +1,6 @@
|
||||||
/* main.c
|
/* main.c
|
||||||
*
|
*
|
||||||
* $Id: main.c,v 1.56 1999/11/30 05:33:05 guy Exp $
|
* $Id: main.c,v 1.57 1999/11/30 20:50:15 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@zing.org>
|
* By Gerald Combs <gerald@zing.org>
|
||||||
|
@ -796,11 +796,10 @@ void expand_all_cb(GtkWidget *widget, gpointer data) {
|
||||||
|
|
||||||
void
|
void
|
||||||
file_quit_cmd_cb (GtkWidget *widget, gpointer data) {
|
file_quit_cmd_cb (GtkWidget *widget, gpointer data) {
|
||||||
/* If we have a save file, and it's a temporary file (i.e., the user
|
/* If we have a capture file open, and it's a temporary file,
|
||||||
hasn't explicitly saved it), delete it. */
|
unlink it. */
|
||||||
if (cf.save_file && !cf.user_saved) {
|
if (cf.filename != NULL && cf.is_tempfile)
|
||||||
unlink(cf.save_file);
|
unlink(cf.filename);
|
||||||
}
|
|
||||||
gtk_exit(0);
|
gtk_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -922,6 +921,9 @@ main(int argc, char *argv[])
|
||||||
cf.plist_end = NULL;
|
cf.plist_end = NULL;
|
||||||
cf.wth = NULL;
|
cf.wth = NULL;
|
||||||
cf.fh = NULL;
|
cf.fh = NULL;
|
||||||
|
cf.filename = NULL;
|
||||||
|
cf.user_saved = FALSE;
|
||||||
|
cf.is_tempfile = FALSE;
|
||||||
cf.rfcode = NULL;
|
cf.rfcode = NULL;
|
||||||
cf.dfilter = NULL;
|
cf.dfilter = NULL;
|
||||||
cf.dfcode = NULL;
|
cf.dfcode = NULL;
|
||||||
|
@ -931,7 +933,6 @@ main(int argc, char *argv[])
|
||||||
cf.iface = NULL;
|
cf.iface = NULL;
|
||||||
cf.save_file = NULL;
|
cf.save_file = NULL;
|
||||||
cf.save_file_fd = -1;
|
cf.save_file_fd = -1;
|
||||||
cf.user_saved = 0;
|
|
||||||
cf.snap = WTAP_MAX_PACKET_SIZE;
|
cf.snap = WTAP_MAX_PACKET_SIZE;
|
||||||
cf.count = 0;
|
cf.count = 0;
|
||||||
cf.cinfo.num_cols = prefs->num_cols;
|
cf.cinfo.num_cols = prefs->num_cols;
|
||||||
|
@ -1029,7 +1030,7 @@ main(int argc, char *argv[])
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 'r': /* Read capture file xxx */
|
case 'r': /* Read capture file xxx */
|
||||||
cf_name = g_strdup(optarg);
|
cf_name = optarg;
|
||||||
break;
|
break;
|
||||||
case 'R': /* Read file filter */
|
case 'R': /* Read file filter */
|
||||||
rfilter = optarg;
|
rfilter = optarg;
|
||||||
|
@ -1326,7 +1327,7 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!rfilter_parse_failed) {
|
if (!rfilter_parse_failed) {
|
||||||
if ((err = open_cap_file(cf_name, &cf)) == 0) {
|
if ((err = open_cap_file(cf_name, FALSE, &cf)) == 0) {
|
||||||
/* "open_cap_file()" succeeded, so it closed the previous
|
/* "open_cap_file()" succeeded, so it closed the previous
|
||||||
capture file, and thus destroyed any previous read filter
|
capture file, and thus destroyed any previous read filter
|
||||||
attached to "cf". */
|
attached to "cf". */
|
||||||
|
@ -1337,7 +1338,6 @@ main(int argc, char *argv[])
|
||||||
last_open_dir = cf_name;
|
last_open_dir = cf_name;
|
||||||
*s = '\0';
|
*s = '\0';
|
||||||
}
|
}
|
||||||
set_menu_sensitivity("/File/Save As...", TRUE);
|
|
||||||
} else {
|
} else {
|
||||||
dfilter_destroy(rfcode);
|
dfilter_destroy(rfcode);
|
||||||
cf.rfcode = NULL;
|
cf.rfcode = NULL;
|
||||||
|
|
Loading…
Reference in New Issue