4 * $Id: file.c,v 1.244 2001/08/21 06:39:14 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
47 #ifdef HAVE_SYS_STAT_H
55 #ifdef NEED_SNPRINTF_H
56 # include "snprintf.h"
59 #ifdef NEED_STRERROR_H
63 #ifdef HAVE_SYS_TYPES_H
64 # include <sys/types.h>
67 #ifdef HAVE_NETINET_IN_H
68 # include <netinet/in.h>
72 #include <filesystem.h>
76 #include "gtk/color_utils.h"
83 #include "simple_dialog.h"
84 #include "progress_dlg.h"
86 #include "statusbar.h"
88 #include "gtk/proto_draw.h"
89 #include "gtk/packet_win.h"
90 #include "dfilter/dfilter.h"
91 #include "conversation.h"
92 #include "reassemble.h"
94 #include "gtk/colors.h"
96 extern GtkWidget *packet_list, *byte_nb_ptr, *tree_view;
98 static guint32 firstsec, firstusec;
99 static guint32 prevsec, prevusec;
101 static void read_packet(capture_file *cf, int offset);
103 static void rescan_packets(capture_file *cf, const char *action,
104 gboolean refilter, gboolean redissect);
106 static void set_selected_row(int row);
108 static void freeze_clist(capture_file *cf);
109 static void thaw_clist(capture_file *cf);
111 static char *file_rename_error_message(int err);
112 static char *file_close_error_message(int err);
113 static gboolean copy_binary_file(char *from_filename, char *to_filename);
115 /* Update the progress bar this many times when reading a file. */
116 #define N_PROGBAR_UPDATES 100
118 /* Number of "frame_data" structures per memory chunk.
119 XXX - is this the right number? */
120 #define FRAME_DATA_CHUNK_SIZE 1024
123 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
130 wth = wtap_open_offline(fname, &err, TRUE);
134 /* Find the size of the file. */
136 if (fstat(fd, &cf_stat) < 0) {
142 /* The open succeeded. Close whatever capture file we had open,
143 and fill in the information for this file. */
146 /* Initialize the table of conversations. */
147 epan_conversation_init();
149 /* Initialize protocol-specific variables */
150 init_all_protocols();
152 /* Initialize the common data structures for fragment reassembly.
153 Must be done *after* "init_all_protocols()", as "init_all_protocols()"
154 may free up space for fragments, which it finds by using the
155 data structures that "reassemble_init()" frees. */
158 /* We're about to start reading the file. */
159 cf->state = FILE_READ_IN_PROGRESS;
163 cf->f_len = cf_stat.st_size;
165 /* Set the file name because we need it to set the follow stream filter.
166 XXX - is that still true? We need it for other reasons, though,
168 cf->filename = g_strdup(fname);
170 /* Indicate whether it's a permanent or temporary file. */
171 cf->is_tempfile = is_tempfile;
173 /* If it's a temporary capture buffer file, mark it as not saved. */
174 cf->user_saved = !is_tempfile;
176 cf->cd_t = wtap_file_type(cf->wth);
178 cf->drops_known = FALSE;
182 cf->snap = wtap_snapshot_length(cf->wth);
183 cf->progbar_quantum = 0;
184 cf->progbar_nextstep = 0;
185 firstsec = 0, firstusec = 0;
186 prevsec = 0, prevusec = 0;
188 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
190 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
192 g_assert(cf->plist_chunk);
197 simple_dialog(ESD_TYPE_CRIT, NULL,
198 file_open_error_message(err, FALSE), fname);
202 /* Reset everything to a pristine state */
204 close_cap_file(capture_file *cf)
206 /* Die if we're in the middle of reading a file. */
207 g_assert(cf->state != FILE_READ_IN_PROGRESS);
209 /* Destroy all popup packet windows, as they refer to packets in the
210 capture file we're closing. */
211 destroy_packet_wins();
217 /* We have no file open... */
218 if (cf->filename != NULL) {
219 /* If it's a temporary file, remove it. */
221 unlink(cf->filename);
222 g_free(cf->filename);
225 /* ...which means we have nothing to save. */
226 cf->user_saved = FALSE;
228 if (cf->plist_chunk != NULL) {
229 g_mem_chunk_destroy(cf->plist_chunk);
230 cf->plist_chunk = NULL;
232 if (cf->rfcode != NULL) {
233 dfilter_free(cf->rfcode);
237 cf->plist_end = NULL;
238 unselect_packet(cf); /* nothing to select */
239 cf->first_displayed = NULL;
240 cf->last_displayed = NULL;
242 /* Clear the packet list. */
243 gtk_clist_freeze(GTK_CLIST(packet_list));
244 gtk_clist_clear(GTK_CLIST(packet_list));
245 gtk_clist_thaw(GTK_CLIST(packet_list));
247 /* Clear any file-related status bar messages.
248 XXX - should be "clear *ALL* file-related status bar messages;
249 will there ever be more than one on the stack? */
250 statusbar_pop_file_msg();
252 /* Restore the standard title bar message. */
253 set_main_window_name("The Ethereal Network Analyzer");
255 /* Disable all menu items that make sense only if you have a capture. */
256 set_menus_for_capture_file(FALSE);
257 set_menus_for_unsaved_capture_file(FALSE);
258 set_menus_for_captured_packets(FALSE);
259 set_menus_for_selected_packet(FALSE);
260 set_menus_for_capture_in_progress(FALSE);
261 set_menus_for_selected_tree_row(FALSE);
263 /* We have no file open. */
264 cf->state = FILE_CLOSED;
267 /* Set the file name in the status line, in the name for the main window,
268 and in the name for the main window's icon. */
270 set_display_filename(capture_file *cf)
274 static const gchar done_fmt_nodrops[] = " File: %s";
275 static const gchar done_fmt_drops[] = " File: %s Drops: %u";
277 gchar *win_name_fmt = "%s - Ethereal";
280 if (!cf->is_tempfile) {
281 /* Get the last component of the file name, and put that in the
283 name_ptr = get_basename(cf->filename);
285 /* The file we read is a temporary file from a live capture;
286 we don't mention its name in the status bar. */
287 name_ptr = "<capture>";
290 if (cf->drops_known) {
291 msg_len = strlen(name_ptr) + strlen(done_fmt_drops) + 64;
292 done_msg = g_malloc(msg_len);
293 snprintf(done_msg, msg_len, done_fmt_drops, name_ptr, cf->drops);
295 msg_len = strlen(name_ptr) + strlen(done_fmt_nodrops);
296 done_msg = g_malloc(msg_len);
297 snprintf(done_msg, msg_len, done_fmt_nodrops, name_ptr);
299 statusbar_push_file_msg(done_msg);
302 msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
303 win_name = g_malloc(msg_len);
304 snprintf(win_name, msg_len, win_name_fmt, name_ptr);
305 set_main_window_name(win_name);
310 read_cap_file(capture_file *cf, int *err)
312 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
315 char errmsg_errno[1024+1];
316 gchar err_str[2048+1];
323 name_ptr = get_basename(cf->filename);
325 msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
326 load_msg = g_malloc(msg_len);
327 snprintf(load_msg, msg_len, load_fmt, name_ptr);
328 statusbar_push_file_msg(load_msg);
330 /* Update the progress bar when it gets to this value. */
331 cf->progbar_nextstep = 0;
332 /* When we reach the value that triggers a progress bar update,
333 bump that value by this amount. */
334 cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
343 progbar = create_progress_dlg(load_msg, "Stop", &stop_flag);
346 while ((wtap_read(cf->wth, err, &data_offset))) {
347 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
348 when we update it, we have to run the GTK+ main loop to get it
349 to repaint what's pending, and doing so may involve an "ioctl()"
350 to see if there's any pending input from an X server, and doing
351 that for every packet can be costly, especially on a big file. */
352 if (data_offset >= cf->progbar_nextstep) {
353 file_pos = lseek(cf->filed, 0, SEEK_CUR);
354 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
355 update_progress_dlg(progbar, prog_val);
356 cf->progbar_nextstep += cf->progbar_quantum;
360 /* Well, the user decided to abort the read. Destroy the progress
361 bar, close the capture file, and return READ_ABORTED so our caller
362 can do whatever is appropriate when that happens. */
363 destroy_progress_dlg(progbar);
364 cf->state = FILE_READ_ABORTED; /* so that we're allowed to close it */
365 gtk_clist_thaw(GTK_CLIST(packet_list)); /* undo our freeze */
367 return (READ_ABORTED);
369 read_packet(cf, data_offset);
372 /* We're done reading the file; destroy the progress bar. */
373 destroy_progress_dlg(progbar);
375 /* We're done reading sequentially through the file. */
376 cf->state = FILE_READ_DONE;
378 /* Close the sequential I/O side, to free up memory it requires. */
379 wtap_sequential_close(cf->wth);
381 /* Set the file encapsulation type now; we don't know what it is until
382 we've looked at all the packets, as we don't know until then whether
383 there's more than one type (and thus whether it's
384 WTAP_ENCAP_PER_PACKET). */
385 cf->lnk_t = wtap_file_encap(cf->wth);
387 cf->current_frame = cf->first_displayed;
390 statusbar_pop_file_msg();
391 set_display_filename(cf);
393 /* Enable menu items that make sense if you have a capture file you've
395 set_menus_for_capture_file(TRUE);
396 set_menus_for_unsaved_capture_file(!cf->user_saved);
398 /* Enable menu items that make sense if you have some captured packets. */
399 set_menus_for_captured_packets(TRUE);
401 /* If we have any displayed packets to select, select the first of those
402 packets by making the first row the selected row. */
403 if (cf->first_displayed != NULL)
404 gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
407 /* Put up a message box noting that the read failed somewhere along
408 the line. Don't throw out the stuff we managed to read, though,
412 case WTAP_ERR_UNSUPPORTED_ENCAP:
413 errmsg = "The capture file is for a network type that Ethereal doesn't support.";
416 case WTAP_ERR_CANT_READ:
417 errmsg = "An attempt to read from the file failed for"
418 " some unknown reason.";
421 case WTAP_ERR_SHORT_READ:
422 errmsg = "The capture file appears to have been cut short"
423 " in the middle of a packet.";
426 case WTAP_ERR_BAD_RECORD:
427 errmsg = "The capture file appears to be damaged or corrupt.";
431 snprintf(errmsg_errno, sizeof(errmsg_errno),
432 "An error occurred while reading the"
433 " capture file: %s.", wtap_strerror(*err));
434 errmsg = errmsg_errno;
437 snprintf(err_str, sizeof err_str, errmsg);
438 simple_dialog(ESD_TYPE_CRIT, NULL, err_str);
441 return (READ_SUCCESS);
446 start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
451 err = open_cap_file(fname, is_tempfile, cf);
453 /* Disable menu items that make no sense if you're currently running
455 set_menus_for_capture_in_progress(TRUE);
457 /* Enable menu items that make sense if you have some captured
458 packets (yes, I know, we don't have any *yet*). */
459 set_menus_for_captured_packets(TRUE);
461 for (i = 0; i < cf->cinfo.num_cols; i++) {
462 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
463 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
465 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
466 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
467 cf->cinfo.col_width[i]);
468 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
472 statusbar_push_file_msg(" <live capture in progress>");
478 continue_tail_cap_file(capture_file *cf, int to_read, int *err)
482 gtk_clist_freeze(GTK_CLIST(packet_list));
484 while (to_read != 0 && (wtap_read(cf->wth, err, &data_offset))) {
485 if (cf->state == FILE_READ_ABORTED) {
486 /* Well, the user decided to exit Ethereal. Break out of the
487 loop, and let the code below (which is called even if there
488 aren't any packets left to read) exit. */
491 read_packet(cf, data_offset);
495 gtk_clist_thaw(GTK_CLIST(packet_list));
497 /* XXX - this cheats and looks inside the packet list to find the final
499 if (prefs.capture_auto_scroll && cf->plist_end != NULL)
500 gtk_clist_moveto(GTK_CLIST(packet_list),
501 GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
503 if (cf->state == FILE_READ_ABORTED) {
504 /* Well, the user decided to exit Ethereal. Return READ_ABORTED
505 so that our caller can kill off the capture child process;
506 this will cause an EOF on the pipe from the child, so
507 "finish_tail_cap_file()" will be called, and it will clean up
510 } else if (*err != 0) {
511 /* We got an error reading the capture file.
512 XXX - pop up a dialog box? */
515 return (READ_SUCCESS);
519 finish_tail_cap_file(capture_file *cf, int *err)
523 gtk_clist_freeze(GTK_CLIST(packet_list));
525 while ((wtap_read(cf->wth, err, &data_offset))) {
526 if (cf->state == FILE_READ_ABORTED) {
527 /* Well, the user decided to abort the read. Break out of the
528 loop, and let the code below (which is called even if there
529 aren't any packets left to read) exit. */
532 read_packet(cf, data_offset);
535 if (cf->state == FILE_READ_ABORTED) {
536 /* Well, the user decided to abort the read. We're only called
537 when the child capture process closes the pipe to us (meaning
538 it's probably exited), so we can just close the capture
539 file; we return READ_ABORTED so our caller can do whatever
540 is appropriate when that happens. */
546 if (prefs.capture_auto_scroll && cf->plist_end != NULL)
547 /* XXX - this cheats and looks inside the packet list to find the final
549 gtk_clist_moveto(GTK_CLIST(packet_list),
550 GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
552 /* We're done reading sequentially through the file. */
553 cf->state = FILE_READ_DONE;
555 /* We're done reading sequentially through the file; close the
556 sequential I/O side, to free up memory it requires. */
557 wtap_sequential_close(cf->wth);
559 /* Set the file encapsulation type now; we don't know what it is until
560 we've looked at all the packets, as we don't know until then whether
561 there's more than one type (and thus whether it's
562 WTAP_ENCAP_PER_PACKET). */
563 cf->lnk_t = wtap_file_encap(cf->wth);
565 /* Pop the "<live capture in progress>" message off the status bar. */
566 statusbar_pop_file_msg();
568 set_display_filename(cf);
570 /* Enable menu items that make sense if you're not currently running
572 set_menus_for_capture_in_progress(FALSE);
574 /* Enable menu items that make sense if you have a capture file
575 you've finished reading. */
576 set_menus_for_capture_file(TRUE);
577 set_menus_for_unsaved_capture_file(!cf->user_saved);
580 /* We got an error reading the capture file.
581 XXX - pop up a dialog box? */
584 return (READ_SUCCESS);
586 #endif /* HAVE_LIBPCAP */
589 color_filter_t *colorf;
591 } apply_color_filter_args;
594 * If no color filter has been applied, apply this one.
595 * (The "if no color filter has been applied" is to handle the case where
596 * more than one color filter matches the packet.)
599 apply_color_filter(gpointer filter_arg, gpointer argp)
601 color_filter_t *colorf = filter_arg;
602 apply_color_filter_args *args = argp;
604 if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
605 if (dfilter_apply_edt(colorf->c_colorfilter, args->edt))
606 args->colorf = colorf;
611 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
612 union wtap_pseudo_header *pseudo_header, const u_char *buf,
615 apply_color_filter_args args;
617 proto_tree *protocol_tree = NULL;
621 /* We don't yet have a color filter to apply. */
624 /* If we don't have the time stamp of the first packet in the
625 capture, it's because this is the first packet. Save the time
626 stamp of this packet as the time stamp of the first packet. */
627 if (!firstsec && !firstusec) {
628 firstsec = fdata->abs_secs;
629 firstusec = fdata->abs_usecs;
632 fdata->cinfo = &cf->cinfo;
633 for (i = 0; i < fdata->cinfo->num_cols; i++) {
634 fdata->cinfo->col_buf[i][0] = '\0';
635 fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
640 we have a display filter and are re-applying it;
642 we have a list of color filters;
644 allocate a protocol tree root node, so that we'll construct
645 a protocol tree against which a filter expression can be
647 if ((cf->dfcode != NULL && refilter) || filter_list != NULL)
648 protocol_tree = proto_tree_create_root();
650 /* Dissect the frame. */
651 edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree);
653 /* If we have a display filter, apply it if we're refiltering, otherwise
654 leave the "passed_dfilter" flag alone.
656 If we don't have a display filter, set "passed_dfilter" to 1. */
657 if (cf->dfcode != NULL) {
659 if (cf->dfcode != NULL)
660 fdata->flags.passed_dfilter = dfilter_apply_edt(cf->dfcode, edt) ? 1 : 0;
662 fdata->flags.passed_dfilter = 1;
665 fdata->flags.passed_dfilter = 1;
667 /* If we have color filters, and the frame is to be displayed, apply
668 the color filters. */
669 if (fdata->flags.passed_dfilter) {
670 if (filter_list != NULL) {
672 g_slist_foreach(filter_list, apply_color_filter, &args);
676 /* There are no more filters to apply, so we don't need any protocol
677 tree; free it if we created it. */
678 if (protocol_tree != NULL)
679 proto_tree_free(protocol_tree);
681 epan_dissect_free(edt);
683 if (fdata->flags.passed_dfilter) {
684 /* This frame passed the display filter, so add it to the clist. */
686 /* If we don't have the time stamp of the previous displayed packet,
687 it's because this is the first displayed packet. Save the time
688 stamp of this packet as the time stamp of the previous displayed
690 if (!prevsec && !prevusec) {
691 prevsec = fdata->abs_secs;
692 prevusec = fdata->abs_usecs;
695 /* Get the time elapsed between the first packet and this packet. */
696 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
697 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
699 /* If it's greater than the current elapsed time, set the elapsed time
700 to it (we check for "greater than" so as not to be confused by
701 time moving backwards). */
702 if (cf->esec < fdata->rel_secs
703 || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
704 cf->esec = fdata->rel_secs;
705 cf->eusec = fdata->rel_usecs;
708 /* Get the time elapsed between the previous displayed packet and
710 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
711 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
712 prevsec = fdata->abs_secs;
713 prevusec = fdata->abs_usecs;
715 fill_in_columns(fdata);
717 /* If we haven't yet seen the first frame, this is it.
719 XXX - we must do this before we add the row to the display,
720 as, if the display's GtkCList's selection mode is
721 GTK_SELECTION_BROWSE, when the first entry is added to it,
722 "select_packet()" will be called, and it will fetch the row
723 data for the 0th row, and will get a null pointer rather than
724 "fdata", as "gtk_clist_append()" won't yet have returned and
725 thus "gtk_clist_set_row_data()" won't yet have been called.
727 We thus need to leave behind bread crumbs so that
728 "select_packet()" can find this frame. See the comment
729 in "select_packet()". */
730 if (cf->first_displayed == NULL)
731 cf->first_displayed = fdata;
733 /* This is the last frame we've seen so far. */
734 cf->last_displayed = fdata;
736 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
737 gtk_clist_set_row_data(GTK_CLIST(packet_list), row, fdata);
739 if (fdata->flags.marked) {
740 color_t_to_gdkcolor(&bg, &prefs.gui_marked_bg);
741 color_t_to_gdkcolor(&fg, &prefs.gui_marked_fg);
742 } else if (filter_list != NULL && (args.colorf != NULL)) {
743 bg = args.colorf->bg_color;
744 fg = args.colorf->fg_color;
749 gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
750 gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
752 /* This frame didn't pass the display filter, so it's not being added
753 to the clist, and thus has no row. */
761 read_packet(capture_file *cf, int offset)
763 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
764 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
765 const u_char *buf = wtap_buf_ptr(cf->wth);
768 proto_tree *protocol_tree;
769 frame_data *plist_end;
772 /* Allocate the next list entry, and add it to the list. */
773 fdata = g_mem_chunk_alloc(cf->plist_chunk);
778 fdata->data_src = NULL;
779 fdata->pkt_len = phdr->len;
780 fdata->cap_len = phdr->caplen;
781 fdata->file_off = offset;
782 fdata->lnk_t = phdr->pkt_encap;
783 fdata->abs_secs = phdr->ts.tv_sec;
784 fdata->abs_usecs = phdr->ts.tv_usec;
785 fdata->flags.encoding = CHAR_ASCII;
786 fdata->flags.visited = 0;
787 fdata->flags.marked = 0;
792 protocol_tree = proto_tree_create_root();
793 edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree);
794 passed = dfilter_apply_edt(cf->rfcode, edt);
795 proto_tree_free(protocol_tree);
796 epan_dissect_free(edt);
799 plist_end = cf->plist_end;
800 fdata->prev = plist_end;
801 if (plist_end != NULL)
802 plist_end->next = fdata;
805 cf->plist_end = fdata;
808 fdata->num = cf->count;
809 add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE);
811 /* XXX - if we didn't have read filters, or if we could avoid
812 allocating the "frame_data" structure until we knew whether
813 the frame passed the read filter, we could use a G_ALLOC_ONLY
816 ...but, at least in one test I did, where I just made the chunk
817 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
818 seem to save a noticeable amount of time or space. */
819 g_mem_chunk_free(cf->plist_chunk, fdata);
824 filter_packets(capture_file *cf, gchar *dftext)
828 if (dftext == NULL) {
829 /* The new filter is an empty filter (i.e., display all packets). */
833 * We have a filter; try to compile it.
835 if (!dfilter_compile(dftext, &dfcode)) {
836 /* The attempt failed; report an error. */
837 simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
842 if (dfcode == NULL) {
843 /* Yes - free the filter text, and set it to null. */
849 /* We have a valid filter. Replace the current filter. */
850 if (cf->dfilter != NULL)
852 cf->dfilter = dftext;
853 if (cf->dfcode != NULL)
854 dfilter_free(cf->dfcode);
857 /* Now rescan the packet list, applying the new filter, but not
858 throwing away information constructed on a previous pass. */
859 rescan_packets(cf, "Filtering", TRUE, FALSE);
864 colorize_packets(capture_file *cf)
866 rescan_packets(cf, "Colorizing", FALSE, FALSE);
870 redissect_packets(capture_file *cf)
872 rescan_packets(cf, "Reprocessing", TRUE, TRUE);
875 /* Rescan the list of packets, reconstructing the CList.
877 "action" describes why we're doing this; it's used in the progress
880 "refilter" is TRUE if we need to re-evaluate the filter expression.
882 "redissect" is TRUE if we need to make the dissectors reconstruct
883 any state information they have (because a preference that affects
884 some dissector has changed, meaning some dissector might construct
885 its state differently from the way it was constructed the last time). */
887 rescan_packets(capture_file *cf, const char *action, gboolean refilter,
893 guint32 progbar_quantum;
894 guint32 progbar_nextstep;
896 frame_data *selected_frame;
900 /* Which frame, if any, is the currently selected frame?
901 XXX - should the selected frame or the focus frame be the "current"
902 frame, that frame being the one from which "Find Frame" searches
904 selected_frame = cf->current_frame;
906 /* We don't yet know what row that frame will be on, if any, after we
907 rebuild the clist, however. */
911 /* We need to re-initialize all the state information that protocols
912 keep, because some preference that controls a dissector has changed,
913 which might cause the state information to be constructed differently
914 by that dissector. */
916 /* Initialize the table of conversations. */
917 epan_conversation_init();
919 /* Initialize protocol-specific variables */
920 init_all_protocols();
922 /* Initialize the common data structures for fragment reassembly.
923 Must be done *after* "init_all_protocols()", as "init_all_protocols()"
924 may free up space for fragments, which it finds by using the
925 data structures that "reassemble_init()" frees. */
929 /* Freeze the packet list while we redo it, so we don't get any
930 screen updates while it happens. */
931 gtk_clist_freeze(GTK_CLIST(packet_list));
934 gtk_clist_clear(GTK_CLIST(packet_list));
936 /* We don't yet know which will be the first and last frames displayed. */
937 cf->first_displayed = NULL;
938 cf->last_displayed = NULL;
940 /* Iterate through the list of frames. Call a routine for each frame
941 to check whether it should be displayed and, if so, add it to
948 /* Update the progress bar when it gets to this value. */
949 progbar_nextstep = 0;
950 /* When we reach the value that triggers a progress bar update,
951 bump that value by this amount. */
952 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
953 /* Count of packets at which we've looked. */
957 progbar = create_progress_dlg(action, "Stop", &stop_flag);
959 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
960 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
961 when we update it, we have to run the GTK+ main loop to get it
962 to repaint what's pending, and doing so may involve an "ioctl()"
963 to see if there's any pending input from an X server, and doing
964 that for every packet can be costly, especially on a big file. */
965 if (count >= progbar_nextstep) {
966 /* let's not divide by zero. I should never be started
967 * with count == 0, so let's assert that
969 g_assert(cf->count > 0);
971 update_progress_dlg(progbar, (gfloat) count / cf->count);
973 progbar_nextstep += progbar_quantum;
977 /* Well, the user decided to abort the filtering. Just stop.
979 XXX - go back to the previous filter? Users probably just
980 want not to wait for a filtering operation to finish;
981 unless we cancel by having no filter, reverting to the
982 previous filter will probably be even more expensive than
983 continuing the filtering, as it involves going back to the
984 beginning and filtering, and even with no filter we currently
985 have to re-generate the entire clist, which is also expensive.
987 I'm not sure what Network Monitor does, but it doesn't appear
988 to give you an unfiltered display if you cancel. */
995 /* Since all state for the frame was destroyed, mark the frame
996 * as not visited, free the GSList referring to the state
997 * data (the per-frame data itself was freed by
998 * "init_all_protocols()"), and null out the GSList pointer. */
999 fdata->flags.visited = 0;
1001 g_slist_free(fdata->pfd);
1004 if (fdata->data_src) { /* release data source list */
1005 g_slist_free(fdata->data_src);
1007 fdata->data_src = NULL;
1010 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1011 cf->pd, fdata->cap_len);
1013 row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
1015 if (fdata == selected_frame)
1020 /* Clear out what remains of the visited flags and per-frame data
1023 XXX - that may cause various forms of bogosity when dissecting
1024 these frames, as they won't have been seen by this sequential
1025 pass, but the only alternative I see is to keep scanning them
1026 even though the user requested that the scan stop, and that
1027 would leave the user stuck with an Ethereal grinding on
1028 until it finishes. Should we just stick them with that? */
1029 for (; fdata != NULL; fdata = fdata->next) {
1030 fdata->flags.visited = 0;
1032 g_slist_free(fdata->pfd);
1035 if (fdata->data_src) {
1036 g_slist_free(fdata->data_src);
1038 fdata->data_src = NULL;
1042 /* We're done filtering the packets; destroy the progress bar. */
1043 destroy_progress_dlg(progbar);
1045 /* Unfreeze the packet list. */
1046 gtk_clist_thaw(GTK_CLIST(packet_list));
1048 if (selected_row != -1) {
1049 /* The frame that was selected passed the filter; select it, make it
1050 the focus row, and make it visible. */
1051 set_selected_row(selected_row);
1052 finfo_selected = NULL;
1054 /* The selected frame didn't pass the filter; make the first frame
1055 the current frame, and leave it unselected. */
1056 unselect_packet(cf);
1057 cf->current_frame = cf->first_displayed;
1062 print_packets(capture_file *cf, print_args_t *print_args)
1068 guint32 progbar_quantum;
1069 guint32 progbar_nextstep;
1071 proto_tree *protocol_tree;
1072 gint *col_widths = NULL;
1074 gboolean print_separator;
1075 char *line_buf = NULL;
1076 int line_buf_len = 256;
1080 epan_dissect_t *edt = NULL;
1082 cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
1083 if (cf->print_fh == NULL)
1084 return FALSE; /* attempt to open destination failed */
1086 print_preamble(cf->print_fh, print_args->format);
1088 if (print_args->print_summary) {
1089 /* We're printing packet summaries. Allocate the line buffer at
1090 its initial length. */
1091 line_buf = g_malloc(line_buf_len + 1);
1093 /* Find the widths for each of the columns - maximum of the
1094 width of the title and the width of the data - and print
1095 the column titles. */
1096 col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1099 for (i = 0; i < cf->cinfo.num_cols; i++) {
1100 /* Don't pad the last column. */
1101 if (i == cf->cinfo.num_cols - 1)
1104 col_widths[i] = strlen(cf->cinfo.col_title[i]);
1105 data_width = get_column_char_width(get_column_format(i));
1106 if (data_width > col_widths[i])
1107 col_widths[i] = data_width;
1110 /* Find the length of the string for this column. */
1111 column_len = strlen(cf->cinfo.col_title[i]);
1112 if (col_widths[i] > column_len)
1113 column_len = col_widths[i];
1115 /* Make sure there's room in the line buffer for the column; if not,
1116 double its length. */
1117 line_len += column_len + 1; /* "+1" for space or \n */
1118 if (line_len > line_buf_len) {
1120 line_buf = g_realloc(line_buf, line_buf_len + 1);
1123 /* Right-justify the packet number column. */
1124 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1125 sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_title[i]);
1127 sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
1129 if (i == cf->cinfo.num_cols - 1)
1135 print_line(cf->print_fh, print_args->format, line_buf);
1138 print_separator = FALSE;
1140 /* The protocol tree will be "visible", i.e., printed, only if we're
1141 not printing a summary. */
1142 proto_tree_is_visible = !print_args->print_summary;
1144 /* Update the progress bar when it gets to this value. */
1145 progbar_nextstep = 0;
1146 /* When we reach the value that triggers a progress bar update,
1147 bump that value by this amount. */
1148 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1149 /* Count of packets at which we've looked. */
1153 progbar = create_progress_dlg("Printing", "Stop", &stop_flag);
1155 /* Iterate through the list of packets, printing the packets that
1156 were selected by the current display filter. */
1157 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1158 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1159 when we update it, we have to run the GTK+ main loop to get it
1160 to repaint what's pending, and doing so may involve an "ioctl()"
1161 to see if there's any pending input from an X server, and doing
1162 that for every packet can be costly, especially on a big file. */
1163 if (count >= progbar_nextstep) {
1164 /* let's not divide by zero. I should never be started
1165 * with count == 0, so let's assert that
1167 g_assert(cf->count > 0);
1169 update_progress_dlg(progbar, (gfloat) count / cf->count);
1171 progbar_nextstep += progbar_quantum;
1175 /* Well, the user decided to abort the printing. Just stop.
1177 XXX - note that what got generated before they did that
1178 will get printed, as we're piping to a print program; we'd
1179 have to write to a file and then hand that to the print
1180 program to make it actually not print anything. */
1185 /* Check to see if we are suppressing unmarked packets, if so,
1186 * suppress them and then proceed to check for visibility.
1188 if (((print_args->suppress_unmarked && fdata->flags.marked ) || !(print_args->suppress_unmarked)) && fdata->flags.passed_dfilter) {
1189 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1190 cf->pd, fdata->cap_len);
1191 if (print_args->print_summary) {
1192 /* Fill in the column information, but don't bother creating
1193 the logical protocol tree. */
1194 fdata->cinfo = &cf->cinfo;
1195 for (i = 0; i < fdata->cinfo->num_cols; i++) {
1196 fdata->cinfo->col_buf[i][0] = '\0';
1197 fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
1199 edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, NULL);
1200 fill_in_columns(fdata);
1203 for (i = 0; i < cf->cinfo.num_cols; i++) {
1204 /* Find the length of the string for this column. */
1205 column_len = strlen(cf->cinfo.col_data[i]);
1206 if (col_widths[i] > column_len)
1207 column_len = col_widths[i];
1209 /* Make sure there's room in the line buffer for the column; if not,
1210 double its length. */
1211 line_len += column_len + 1; /* "+1" for space or \n */
1212 if (line_len > line_buf_len) {
1214 line_buf = g_realloc(line_buf, line_buf_len + 1);
1217 /* Right-justify the packet number column. */
1218 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1219 sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_data[i]);
1221 sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
1223 if (i == cf->cinfo.num_cols - 1)
1229 print_line(cf->print_fh, print_args->format, line_buf);
1231 if (print_separator)
1232 print_line(cf->print_fh, print_args->format, "\n");
1234 /* Create the logical protocol tree. */
1235 protocol_tree = proto_tree_create_root();
1236 edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
1238 /* Print the information in that tree. */
1239 proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
1240 fdata, cf->print_fh);
1242 proto_tree_free(protocol_tree);
1244 if (print_args->print_hex) {
1245 /* Print the full packet data as hex. */
1246 print_hex_data(cf->print_fh, print_args->format, fdata);
1249 /* Print a blank line if we print anything after this. */
1250 print_separator = TRUE;
1252 epan_dissect_free(edt);
1256 /* We're done printing the packets; destroy the progress bar. */
1257 destroy_progress_dlg(progbar);
1259 if (col_widths != NULL)
1261 if (line_buf != NULL)
1264 print_finale(cf->print_fh, print_args->format);
1266 close_print_dest(print_args->to_file, cf->print_fh);
1268 cf->print_fh = NULL;
1270 proto_tree_is_visible = FALSE;
1275 /* Scan through the packet list and change all columns that use the
1276 "command-line-specified" time stamp format to use the current
1277 value of that format. */
1279 change_time_formats(capture_file *cf)
1284 guint32 progbar_quantum;
1285 guint32 progbar_nextstep;
1291 /* Freeze the packet list while we redo it, so we don't get any
1292 screen updates while it happens. */
1295 /* Update the progress bar when it gets to this value. */
1296 progbar_nextstep = 0;
1297 /* When we reach the value that triggers a progress bar update,
1298 bump that value by this amount. */
1299 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1300 /* Count of packets at which we've looked. */
1304 progbar = create_progress_dlg("Changing time display", "Stop", &stop_flag);
1306 /* Iterate through the list of packets, checking whether the packet
1307 is in a row of the summary list and, if so, whether there are
1308 any columns that show the time in the "command-line-specified"
1309 format and, if so, update that row. */
1310 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1311 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1312 when we update it, we have to run the GTK+ main loop to get it
1313 to repaint what's pending, and doing so may involve an "ioctl()"
1314 to see if there's any pending input from an X server, and doing
1315 that for every packet can be costly, especially on a big file. */
1316 if (count >= progbar_nextstep) {
1317 /* let's not divide by zero. I should never be started
1318 * with count == 0, so let's assert that
1320 g_assert(cf->count > 0);
1322 update_progress_dlg(progbar, (gfloat) count / cf->count);
1324 progbar_nextstep += progbar_quantum;
1328 /* Well, the user decided to abort the redisplay. Just stop.
1330 XXX - this leaves the time field in the old format in
1331 frames we haven't yet processed. So it goes; should we
1332 simply not offer them the option of stopping? */
1338 /* Find what row this packet is in. */
1339 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1342 /* This packet is in the summary list, on row "row". */
1344 /* XXX - there really should be a way of checking "cf->cinfo" for this;
1345 the answer isn't going to change from packet to packet, so we should
1346 simply skip all the "change_time_formats()" work if we're not
1347 changing anything. */
1348 fdata->cinfo = &cf->cinfo;
1349 if (check_col(fdata, COL_CLS_TIME)) {
1350 /* There are columns that show the time in the "command-line-specified"
1351 format; update them. */
1352 for (i = 0; i < cf->cinfo.num_cols; i++) {
1353 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1354 /* This is one of the columns that shows the time in
1355 "command-line-specified" format; update it. */
1356 cf->cinfo.col_buf[i][0] = '\0';
1357 col_set_cls_time(fdata, i);
1358 gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
1359 cf->cinfo.col_data[i]);
1366 /* We're done redisplaying the packets; destroy the progress bar. */
1367 destroy_progress_dlg(progbar);
1369 /* Set the column widths of those columns that show the time in
1370 "command-line-specified" format. */
1371 pl_style = gtk_widget_get_style(packet_list);
1372 for (i = 0; i < cf->cinfo.num_cols; i++) {
1373 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1374 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1375 gdk_string_width(pl_style->font, get_column_longest_string(COL_CLS_TIME)));
1379 /* Unfreeze the packet list. */
1384 find_packet(capture_file *cf, dfilter_t *sfcode)
1386 frame_data *start_fd;
1388 frame_data *new_fd = NULL;
1391 guint32 progbar_quantum;
1392 guint32 progbar_nextstep;
1394 proto_tree *protocol_tree;
1395 gboolean frame_matched;
1397 epan_dissect_t *edt;
1399 start_fd = cf->current_frame;
1400 if (start_fd != NULL) {
1401 /* Iterate through the list of packets, starting at the packet we've
1402 picked, calling a routine to run the filter on the packet, see if
1403 it matches, and stop if so. */
1407 /* Update the progress bar when it gets to this value. */
1408 progbar_nextstep = 0;
1409 /* When we reach the value that triggers a progress bar update,
1410 bump that value by this amount. */
1411 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1414 progbar = create_progress_dlg("Searching", "Cancel", &stop_flag);
1418 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1419 when we update it, we have to run the GTK+ main loop to get it
1420 to repaint what's pending, and doing so may involve an "ioctl()"
1421 to see if there's any pending input from an X server, and doing
1422 that for every packet can be costly, especially on a big file. */
1423 if (count >= progbar_nextstep) {
1424 /* let's not divide by zero. I should never be started
1425 * with count == 0, so let's assert that
1427 g_assert(cf->count > 0);
1429 update_progress_dlg(progbar, (gfloat) count / cf->count);
1431 progbar_nextstep += progbar_quantum;
1435 /* Well, the user decided to abort the search. Go back to the
1436 frame where we started. */
1441 /* Go past the current frame. */
1442 if (cf->sbackward) {
1443 /* Go on to the previous frame. */
1444 fdata = fdata->prev;
1446 fdata = cf->plist_end; /* wrap around */
1448 /* Go on to the next frame. */
1449 fdata = fdata->next;
1451 fdata = cf->plist; /* wrap around */
1456 /* Is this packet in the display? */
1457 if (fdata->flags.passed_dfilter) {
1458 /* Yes. Does it match the search filter? */
1459 protocol_tree = proto_tree_create_root();
1460 wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
1461 cf->pd, fdata->cap_len);
1462 edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
1463 frame_matched = dfilter_apply_edt(sfcode, edt);
1464 proto_tree_free(protocol_tree);
1465 epan_dissect_free(edt);
1466 if (frame_matched) {
1468 break; /* found it! */
1472 if (fdata == start_fd) {
1473 /* We're back to the frame we were on originally, and that frame
1474 doesn't match the search filter. The search failed. */
1479 /* We're done scanning the packets; destroy the progress bar. */
1480 destroy_progress_dlg(progbar);
1483 if (new_fd != NULL) {
1484 /* We found a frame. Find what row it's in. */
1485 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), new_fd);
1486 g_assert(row != -1);
1488 /* Select that row, make it the focus row, and make it visible. */
1489 set_selected_row(row);
1490 return TRUE; /* success */
1492 return FALSE; /* failure */
1496 goto_frame(capture_file *cf, guint fnumber)
1501 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
1505 return NO_SUCH_FRAME; /* we didn't find that frame */
1506 if (!fdata->flags.passed_dfilter)
1507 return FRAME_NOT_DISPLAYED; /* the frame with that number isn't displayed */
1509 /* We found that frame, and it's currently being displayed.
1510 Find what row it's in. */
1511 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1512 g_assert(row != -1);
1514 /* Select that row, make it the focus row, and make it visible. */
1515 set_selected_row(row);
1519 /* Select the packet on a given row. */
1521 select_packet(capture_file *cf, int row)
1527 /* Get the frame data struct pointer for this frame */
1528 fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
1530 if (fdata == NULL) {
1531 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
1532 the first entry is added to it by "real_insert_row()", that row
1533 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
1534 our version and the vanilla GTK+ version).
1536 This means that a "select-row" signal is emitted; this causes
1537 "packet_list_select_cb()" to be called, which causes "select_packet()"
1540 "select_packet()" fetches, above, the data associated with the
1541 row that was selected; however, as "gtk_clist_append()", which
1542 called "real_insert_row()", hasn't yet returned, we haven't yet
1543 associated any data with that row, so we get back a null pointer.
1545 We can't assume that there's only one frame in the frame list,
1546 either, as we may be filtering the display.
1548 We therefore assume that, if "row" is 0, i.e. the first row
1549 is being selected, and "cf->first_displayed" equals
1550 "cf->last_displayed", i.e. there's only one frame being
1551 displayed, that frame is the frame we want.
1553 This means we have to set "cf->first_displayed" and
1554 "cf->last_displayed" before adding the row to the
1555 GtkCList; see the comment in "add_packet_to_packet_list()". */
1557 if (row == 0 && cf->first_displayed == cf->last_displayed)
1558 fdata = cf->first_displayed;
1561 /* Record that this frame is the current frame. */
1562 cf->current_frame = fdata;
1564 /* Get the data in that frame. */
1565 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1566 cf->pd, fdata->cap_len);
1568 /* Create the logical protocol tree. */
1569 if (cf->protocol_tree)
1570 proto_tree_free(cf->protocol_tree);
1571 cf->protocol_tree = proto_tree_create_root();
1572 proto_tree_is_visible = TRUE;
1573 if (cf->edt != NULL) {
1574 epan_dissect_free(cf->edt);
1577 cf->edt = epan_dissect_new(&cf->pseudo_header, cf->pd, cf->current_frame,
1579 proto_tree_is_visible = FALSE;
1581 /* Display the GUI protocol tree and hex dump. */
1582 clear_tree_and_hex_views();
1585 while((bv_tvb = g_slist_nth_data ( cf->current_frame->data_src, i++))){
1586 add_byte_view( tvb_get_name( bv_tvb), tvb_get_ptr(bv_tvb, 0, -1), tvb_length(bv_tvb));
1589 proto_tree_draw(cf->protocol_tree, tree_view);
1591 set_notebook_page( byte_nb_ptr, 0);
1593 /* A packet is selected. */
1594 set_menus_for_selected_packet(TRUE);
1597 /* Unselect the selected packet, if any. */
1599 unselect_packet(capture_file *cf)
1601 /* Destroy the protocol tree and epan_dissect_t for that packet. */
1602 if (cf->protocol_tree != NULL) {
1603 proto_tree_free(cf->protocol_tree);
1604 cf->protocol_tree = NULL;
1606 if (cf->edt != NULL) {
1607 epan_dissect_free(cf->edt);
1611 /* Clear out the display of that packet. */
1612 clear_tree_and_hex_views();
1614 /* No packet is selected. */
1615 set_menus_for_selected_packet(FALSE);
1617 /* No protocol tree means no selected field. */
1621 /* Set the selected row and the focus row of the packet list to the specified
1622 row, and make it visible if it's not currently visible. */
1624 set_selected_row(int row)
1626 if (gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) != GTK_VISIBILITY_FULL)
1627 gtk_clist_moveto(GTK_CLIST(packet_list), row, -1, 0.0, 0.0);
1629 /* XXX - why is there no "gtk_clist_set_focus_row()", so that we
1630 can make the row for the frame we found the focus row?
1634 http://www.gnome.org/mailing-lists/archives/gtk-list/2000-January/0038.shtml
1637 GTK_CLIST(packet_list)->focus_row = row;
1639 gtk_clist_select_row(GTK_CLIST(packet_list), row, -1);
1642 /* Unset the selected protocol tree field, if any. */
1644 unselect_field(void)
1646 statusbar_pop_field_msg();
1647 finfo_selected = NULL;
1648 set_menus_for_selected_tree_row(FALSE);
1652 freeze_clist(capture_file *cf)
1656 /* Make the column sizes static, so they don't adjust while
1657 we're reading the capture file (freezing the clist doesn't
1658 seem to suffice). */
1659 for (i = 0; i < cf->cinfo.num_cols; i++)
1660 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1661 gtk_clist_freeze(GTK_CLIST(packet_list));
1665 thaw_clist(capture_file *cf)
1669 for (i = 0; i < cf->cinfo.num_cols; i++) {
1670 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1671 /* Set this column's width to the appropriate value. */
1672 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1673 cf->cinfo.col_width[i]);
1675 /* Make this column's size dynamic, so that it adjusts to the
1676 appropriate size. */
1677 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1680 gtk_clist_thaw(GTK_CLIST(packet_list));
1682 /* Hopefully, the columns have now gotten their appropriate sizes;
1683 make them resizeable - a column that auto-resizes cannot be
1684 resized by the user, and *vice versa*. */
1685 for (i = 0; i < cf->cinfo.num_cols; i++)
1686 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1690 save_cap_file(char *fname, capture_file *cf, gboolean save_filtered, gboolean save_marked,
1693 gchar *from_filename;
1694 gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
1700 struct wtap_pkthdr hdr;
1701 union wtap_pseudo_header pseudo_header;
1704 name_ptr = get_basename(fname);
1705 msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
1706 save_msg = g_malloc(msg_len);
1707 snprintf(save_msg, msg_len, save_fmt, name_ptr);
1708 statusbar_push_file_msg(save_msg);
1711 if (!save_filtered && !save_marked && save_format == cf->cd_t) {
1712 /* We're not filtering packets, and we're saving it in the format
1713 it's already in, so we can just move or copy the raw data. */
1715 /* In this branch, we set "err" only if we get an error, so we
1716 must first clear it. */
1718 if (cf->is_tempfile) {
1719 /* The file being saved is a temporary file from a live
1720 capture, so it doesn't need to stay around under that name;
1721 first, try renaming the capture buffer file to the new name. */
1723 if (rename(cf->filename, fname) == 0) {
1724 /* That succeeded - there's no need to copy the source file. */
1725 from_filename = NULL;
1728 if (errno == EXDEV) {
1729 /* They're on different file systems, so we have to copy the
1732 from_filename = cf->filename;
1734 /* The rename failed, but not because they're on different
1735 file systems - put up an error message. (Or should we
1736 just punt and try to copy? The only reason why I'd
1737 expect the rename to fail and the copy to succeed would
1738 be if we didn't have permission to remove the file from
1739 the temporary directory, and that might be fixable - but
1740 is it worth requiring the user to go off and fix it?) */
1742 simple_dialog(ESD_TYPE_CRIT, NULL,
1743 file_rename_error_message(err), fname);
1749 from_filename = cf->filename;
1752 /* It's a permanent file, so we should copy it, and not remove the
1755 from_filename = cf->filename;
1757 /* Copy the file, if we haven't moved it. */
1759 if (!copy_binary_file(from_filename, fname)) {
1764 /* Either we're filtering packets, or we're saving in a different
1765 format; we can't do that by copying or moving the capture file,
1766 we have to do it by writing the packets out in Wiretap. */
1767 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
1769 simple_dialog(ESD_TYPE_CRIT, NULL,
1770 file_open_error_message(err, TRUE), fname);
1774 /* XXX - have a way to save only the packets currently selected by
1775 the display filter or the marked ones.
1777 If we do that, should we make that file the current file? If so,
1778 it means we can no longer get at the other packets. What does
1780 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1781 /* XXX - do a progress bar */
1782 if ((!save_filtered && !save_marked) ||
1783 (save_filtered && fdata->flags.passed_dfilter && !save_marked) ||
1784 (save_marked && fdata->flags.marked && !save_filtered) ||
1785 (save_filtered && save_marked && fdata->flags.passed_dfilter &&
1786 fdata->flags.marked)) {
1788 - we're saving all frames, or
1789 - we're saving filtered frames and this one passed the display filter or
1790 - we're saving marked frames (and it has been marked) or
1791 - we're saving filtered _and_ marked frames,
1793 hdr.ts.tv_sec = fdata->abs_secs;
1794 hdr.ts.tv_usec = fdata->abs_usecs;
1795 hdr.caplen = fdata->cap_len;
1796 hdr.len = fdata->pkt_len;
1797 hdr.pkt_encap = fdata->lnk_t;
1798 wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1799 pd, fdata->cap_len);
1801 if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
1802 simple_dialog(ESD_TYPE_CRIT, NULL,
1803 file_write_error_message(err), fname);
1804 wtap_dump_close(pdh, &err);
1810 if (!wtap_dump_close(pdh, &err)) {
1811 simple_dialog(ESD_TYPE_WARN, NULL,
1812 file_close_error_message(err), fname);
1819 /* Pop the "Saving:" message off the status bar. */
1820 statusbar_pop_file_msg();
1822 if (!save_filtered && !save_marked) {
1823 /* We saved the entire capture, not just some packets from it.
1824 Open and read the file we saved it to.
1826 XXX - this is somewhat of a waste; we already have the
1827 packets, all this gets us is updated file type information
1828 (which we could just stuff into "cf"), and having the new
1829 file be the one we have opened and from which we're reading
1830 the data, and it means we have to spend time opening and
1831 reading the file, which could be a significant amount of
1832 time if the file is large. */
1833 cf->user_saved = TRUE;
1835 if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
1836 /* XXX - report errors if this fails? */
1837 switch (read_cap_file(cf, &err)) {
1841 /* Just because we got an error, that doesn't mean we were unable
1842 to read any of the file; we handle what we could get from the
1847 /* The user bailed out of re-reading the capture file; the
1848 capture file has been closed - just return (without
1849 changing any menu settings; "close_cap_file()" set them
1850 correctly for the "no capture file open" state). */
1853 set_menus_for_unsaved_capture_file(FALSE);
1861 file_open_error_message(int err, gboolean for_writing)
1864 static char errmsg_errno[1024+1];
1868 case WTAP_ERR_NOT_REGULAR_FILE:
1869 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1872 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1873 case WTAP_ERR_UNSUPPORTED:
1874 /* Seen only when opening a capture file for reading. */
1875 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1878 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1879 /* Seen only when opening a capture file for writing. */
1880 errmsg = "Ethereal does not support writing capture files in that format.";
1883 case WTAP_ERR_UNSUPPORTED_ENCAP:
1884 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1886 errmsg = "Ethereal cannot save this capture in that format.";
1888 errmsg = "The file \"%s\" is a capture for a network type that Ethereal doesn't support.";
1891 case WTAP_ERR_BAD_RECORD:
1892 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1895 case WTAP_ERR_CANT_OPEN:
1897 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1899 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1902 case WTAP_ERR_SHORT_READ:
1903 errmsg = "The file \"%s\" appears to have been cut short"
1904 " in the middle of a packet.";
1907 case WTAP_ERR_SHORT_WRITE:
1908 errmsg = "A full header couldn't be written to the file \"%s\".";
1913 errmsg = "The path to the file \"%s\" does not exist.";
1915 errmsg = "The file \"%s\" does not exist.";
1920 errmsg = "You do not have permission to create or write to the file \"%s\".";
1922 errmsg = "You do not have permission to read the file \"%s\".";
1926 errmsg = "\"%s\" is a directory (folder), not a file.";
1930 snprintf(errmsg_errno, sizeof(errmsg_errno),
1931 "The file \"%%s\" could not be opened: %s.",
1932 wtap_strerror(err));
1933 errmsg = errmsg_errno;
1940 file_rename_error_message(int err)
1943 static char errmsg_errno[1024+1];
1948 errmsg = "The path to the file \"%s\" does not exist.";
1952 errmsg = "You do not have permission to move the capture file to \"%s\".";
1956 snprintf(errmsg_errno, sizeof(errmsg_errno),
1957 "The file \"%%s\" could not be moved: %s.",
1958 wtap_strerror(err));
1959 errmsg = errmsg_errno;
1966 file_read_error_message(int err)
1968 static char errmsg_errno[1024+1];
1970 snprintf(errmsg_errno, sizeof(errmsg_errno),
1971 "An error occurred while reading from the file \"%%s\": %s.",
1972 wtap_strerror(err));
1973 return errmsg_errno;
1977 file_write_error_message(int err)
1980 static char errmsg_errno[1024+1];
1985 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1990 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1995 snprintf(errmsg_errno, sizeof(errmsg_errno),
1996 "An error occurred while writing to the file \"%%s\": %s.",
1997 wtap_strerror(err));
1998 errmsg = errmsg_errno;
2004 /* Check for write errors - if the file is being written to an NFS server,
2005 a write error may not show up until the file is closed, as NFS clients
2006 might not send writes to the server until the "write()" call finishes,
2007 so that the write may fail on the server but the "write()" may succeed. */
2009 file_close_error_message(int err)
2012 static char errmsg_errno[1024+1];
2016 case WTAP_ERR_CANT_CLOSE:
2017 errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
2020 case WTAP_ERR_SHORT_WRITE:
2021 errmsg = "Not all the packets could be written to the file \"%s\".";
2025 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
2030 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
2035 snprintf(errmsg_errno, sizeof(errmsg_errno),
2036 "An error occurred while closing the file \"%%s\": %s.",
2037 wtap_strerror(err));
2038 errmsg = errmsg_errno;
2045 /* Copies a file in binary mode, for those operating systems that care about
2047 * Returns TRUE on success, FALSE on failure. If a failure, it also
2048 * displays a simple dialog window with the error message.
2051 copy_binary_file(char *from_filename, char *to_filename)
2053 int from_fd, to_fd, nread, nwritten, err;
2054 guint8 pd[65536]; /* XXX - Hmm, 64K here, 64K in save_cap_file(),
2055 perhaps we should make just one 64K buffer. */
2057 /* Copy the raw bytes of the file. */
2058 from_fd = open(from_filename, O_RDONLY | O_BINARY);
2061 simple_dialog(ESD_TYPE_CRIT, NULL,
2062 file_open_error_message(err, TRUE), from_filename);
2066 /* Use open() instead of creat() so that we can pass the O_BINARY
2067 flag, which is relevant on Win32; it appears that "creat()"
2068 may open the file in text mode, not binary mode, but we want
2069 to copy the raw bytes of the file, so we need the output file
2070 to be open in binary mode. */
2071 to_fd = open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
2074 simple_dialog(ESD_TYPE_CRIT, NULL,
2075 file_open_error_message(err, TRUE), to_filename);
2080 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
2081 nwritten = write(to_fd, pd, nread);
2082 if (nwritten < nread) {
2086 err = WTAP_ERR_SHORT_WRITE;
2087 simple_dialog(ESD_TYPE_CRIT, NULL,
2088 file_write_error_message(err), to_filename);
2096 simple_dialog(ESD_TYPE_CRIT, NULL,
2097 file_read_error_message(err), from_filename);
2103 if (close(to_fd) < 0) {
2105 simple_dialog(ESD_TYPE_CRIT, NULL,
2106 file_close_error_message(err), to_filename);