4 * $Id: file.c,v 1.227 2000/11/21 23:54:08 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
48 #ifdef HAVE_SYS_STAT_H
56 #ifdef NEED_SNPRINTF_H
57 # include "snprintf.h"
60 #ifdef NEED_STRERROR_H
64 #ifdef HAVE_SYS_TYPES_H
65 # include <sys/types.h>
68 #ifdef HAVE_NETINET_IN_H
69 # include <netinet/in.h>
76 #include "gtk/color_utils.h"
83 #include "simple_dialog.h"
86 #include "gtk/proto_draw.h"
88 #include "conversation.h"
90 #include "gtk/colors.h"
94 extern GtkWidget *packet_list, *info_bar, *byte_view, *tree_view;
95 extern guint file_ctx;
97 gboolean auto_scroll_live = FALSE;
99 static guint32 firstsec, firstusec;
100 static guint32 prevsec, prevusec;
102 static void read_packet(capture_file *cf, int offset);
104 static void rescan_packets(capture_file *cf, const char *action,
105 gboolean refilter, gboolean redissect);
107 static void set_selected_row(int row);
109 static void freeze_clist(capture_file *cf);
110 static void thaw_clist(capture_file *cf);
112 static char *file_rename_error_message(int err);
113 static char *file_close_error_message(int err);
114 static gboolean copy_binary_file(char *from_filename, char *to_filename);
116 /* Update the progress bar this many times when reading a file. */
117 #define N_PROGBAR_UPDATES 100
119 /* Number of "frame_data" structures per memory chunk.
120 XXX - is this the right number? */
121 #define FRAME_DATA_CHUNK_SIZE 1024
124 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
132 wth = wtap_open_offline(fname, &err, TRUE);
136 /* Find the size of the file. */
139 if (fstat(fd, &cf_stat) < 0) {
145 /* The open succeeded. Close whatever capture file we had open,
146 and fill in the information for this file. */
147 close_cap_file(cf, info_bar);
149 /* Initialize the table of conversations. */
150 epan_conversation_init();
152 /* Initialize protocol-specific variables */
153 init_all_protocols();
155 /* We're about to start reading the file. */
156 cf->state = FILE_READ_IN_PROGRESS;
160 cf->f_len = cf_stat.st_size;
162 /* Set the file name because we need it to set the follow stream filter.
163 XXX - is that still true? We need it for other reasons, though,
165 cf->filename = g_strdup(fname);
167 /* Indicate whether it's a permanent or temporary file. */
168 cf->is_tempfile = is_tempfile;
170 /* If it's a temporary capture buffer file, mark it as not saved. */
171 cf->user_saved = !is_tempfile;
173 cf->cd_t = wtap_file_type(cf->wth);
178 cf->snap = wtap_snapshot_length(cf->wth);
179 cf->progbar_quantum = 0;
180 cf->progbar_nextstep = 0;
181 firstsec = 0, firstusec = 0;
182 prevsec = 0, prevusec = 0;
184 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
186 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
188 g_assert(cf->plist_chunk);
193 simple_dialog(ESD_TYPE_CRIT, NULL,
194 file_open_error_message(err, FALSE), fname);
198 /* Reset everything to a pristine state */
200 close_cap_file(capture_file *cf, void *w)
202 /* Die if we're in the middle of reading a file. */
203 g_assert(cf->state != FILE_READ_IN_PROGRESS);
205 /* Destroy all popup packet windows, as they refer to packets in the
206 capture file we're closing. */
207 destroy_packet_wins();
213 /* We have no file open... */
214 if (cf->filename != NULL) {
215 /* If it's a temporary file, remove it. */
217 unlink(cf->filename);
218 g_free(cf->filename);
221 /* ...which means we have nothing to save. */
222 cf->user_saved = FALSE;
224 if (cf->plist_chunk != NULL) {
225 g_mem_chunk_destroy(cf->plist_chunk);
226 cf->plist_chunk = NULL;
228 if (cf->rfcode != NULL) {
229 dfilter_destroy(cf->rfcode);
233 cf->plist_end = NULL;
234 unselect_packet(cf); /* nothing to select */
235 cf->first_displayed = NULL;
236 cf->last_displayed = NULL;
238 /* Clear the packet list. */
239 gtk_clist_freeze(GTK_CLIST(packet_list));
240 gtk_clist_clear(GTK_CLIST(packet_list));
241 gtk_clist_thaw(GTK_CLIST(packet_list));
243 /* Clear any file-related status bar messages.
244 XXX - should be "clear *ALL* file-related status bar messages;
245 will there ever be more than one on the stack? */
246 gtk_statusbar_pop(GTK_STATUSBAR(w), file_ctx);
248 /* Restore the standard title bar message. */
249 set_main_window_name("The Ethereal Network Analyzer");
251 /* Disable all menu items that make sense only if you have a capture. */
252 set_menus_for_capture_file(FALSE);
253 set_menus_for_unsaved_capture_file(FALSE);
254 set_menus_for_captured_packets(FALSE);
255 set_menus_for_selected_packet(FALSE);
256 set_menus_for_capture_in_progress(FALSE);
257 set_menus_for_selected_tree_row(FALSE);
259 /* We have no file open. */
260 cf->state = FILE_CLOSED;
263 /* Set the file name in the status line, in the name for the main window,
264 and in the name for the main window's icon. */
266 set_display_filename(capture_file *cf)
270 gchar *done_fmt = " File: %s Drops: %u";
272 gchar *win_name_fmt = "%s - Ethereal";
275 if (!cf->is_tempfile) {
276 /* Get the last component of the file name, and put that in the
278 name_ptr = get_basename(cf->filename);
280 /* The file we read is a temporary file from a live capture;
281 we don't mention its name in the status bar. */
282 name_ptr = "<capture>";
285 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
286 done_msg = g_malloc(msg_len);
287 snprintf(done_msg, msg_len, done_fmt, name_ptr, cf->drops);
288 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
291 msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
292 win_name = g_malloc(msg_len);
293 snprintf(win_name, msg_len, win_name_fmt, name_ptr);
294 set_main_window_name(win_name);
299 read_cap_file(capture_file *cf, int *err)
301 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
304 char errmsg_errno[1024+1];
305 gchar err_str[2048+1];
312 name_ptr = get_basename(cf->filename);
314 msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
315 load_msg = g_malloc(msg_len);
316 snprintf(load_msg, msg_len, load_fmt, name_ptr);
317 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
319 /* Update the progress bar when it gets to this value. */
320 cf->progbar_nextstep = 0;
321 /* When we reach the value that triggers a progress bar update,
322 bump that value by this amount. */
323 cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
332 progbar = create_progress_dlg(load_msg, "Stop", &stop_flag);
335 while ((wtap_read(cf->wth, err, &data_offset))) {
336 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
337 when we update it, we have to run the GTK+ main loop to get it
338 to repaint what's pending, and doing so may involve an "ioctl()"
339 to see if there's any pending input from an X server, and doing
340 that for every packet can be costly, especially on a big file. */
341 if (data_offset >= cf->progbar_nextstep) {
342 file_pos = lseek(cf->filed, 0, SEEK_CUR);
343 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
344 update_progress_dlg(progbar, prog_val);
345 cf->progbar_nextstep += cf->progbar_quantum;
349 /* Well, the user decided to abort the read. Destroy the progress
350 bar, close the capture file, and return READ_ABORTED so our caller
351 can do whatever is appropriate when that happens. */
352 destroy_progress_dlg(progbar);
353 cf->state = FILE_READ_ABORTED; /* so that we're allowed to close it */
354 gtk_clist_thaw(GTK_CLIST(packet_list)); /* undo our freeze */
355 close_cap_file(cf, info_bar);
356 return (READ_ABORTED);
358 read_packet(cf, data_offset);
361 /* We're done reading the file; destroy the progress bar. */
362 destroy_progress_dlg(progbar);
364 /* We're done reading sequentially through the file. */
365 cf->state = FILE_READ_DONE;
367 /* Close the sequential I/O side, to free up memory it requires. */
368 wtap_sequential_close(cf->wth);
370 /* Set the file encapsulation type now; we don't know what it is until
371 we've looked at all the packets, as we don't know until then whether
372 there's more than one type (and thus whether it's
373 WTAP_ENCAP_PER_PACKET). */
374 cf->lnk_t = wtap_file_encap(cf->wth);
376 cf->current_frame = cf->first_displayed;
379 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
380 set_display_filename(cf);
382 /* Enable menu items that make sense if you have a capture file you've
384 set_menus_for_capture_file(TRUE);
385 set_menus_for_unsaved_capture_file(!cf->user_saved);
387 /* Enable menu items that make sense if you have some captured packets. */
388 set_menus_for_captured_packets(TRUE);
390 /* If we have any displayed packets to select, select the first of those
391 packets by making the first row the selected row. */
392 if (cf->first_displayed != NULL)
393 gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
396 /* Put up a message box noting that the read failed somewhere along
397 the line. Don't throw out the stuff we managed to read, though,
401 case WTAP_ERR_UNSUPPORTED_ENCAP:
402 errmsg = "The capture file is for a network type that Ethereal doesn't support.";
405 case WTAP_ERR_CANT_READ:
406 errmsg = "An attempt to read from the file failed for"
407 " some unknown reason.";
410 case WTAP_ERR_SHORT_READ:
411 errmsg = "The capture file appears to have been cut short"
412 " in the middle of a packet.";
415 case WTAP_ERR_BAD_RECORD:
416 errmsg = "The capture file appears to be damaged or corrupt.";
420 snprintf(errmsg_errno, sizeof(errmsg_errno),
421 "An error occurred while reading the"
422 " capture file: %s.", wtap_strerror(*err));
423 errmsg = errmsg_errno;
426 snprintf(err_str, sizeof err_str, errmsg);
427 simple_dialog(ESD_TYPE_CRIT, NULL, err_str);
430 return (READ_SUCCESS);
435 start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
440 err = open_cap_file(fname, is_tempfile, cf);
442 /* Disable menu items that make no sense if you're currently running
444 set_menus_for_capture_in_progress(TRUE);
446 /* Enable menu items that make sense if you have some captured
447 packets (yes, I know, we don't have any *yet*). */
448 set_menus_for_captured_packets(TRUE);
450 for (i = 0; i < cf->cinfo.num_cols; i++) {
451 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
452 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
454 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
455 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
456 cf->cinfo.col_width[i]);
457 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
461 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
462 " <live capture in progress>");
468 continue_tail_cap_file(capture_file *cf, int to_read, int *err)
472 gtk_clist_freeze(GTK_CLIST(packet_list));
474 while (to_read != 0 && (wtap_read(cf->wth, err, &data_offset))) {
475 if (cf->state == FILE_READ_ABORTED) {
476 /* Well, the user decided to exit Ethereal. Break out of the
477 loop, and let the code below (which is called even if there
478 aren't any packets left to read) exit. */
481 read_packet(cf, data_offset);
485 gtk_clist_thaw(GTK_CLIST(packet_list));
487 /* XXX - this cheats and looks inside the packet list to find the final
489 if (auto_scroll_live && cf->plist_end != NULL)
490 gtk_clist_moveto(GTK_CLIST(packet_list),
491 GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
493 if (cf->state == FILE_READ_ABORTED) {
494 /* Well, the user decided to exit Ethereal. Return READ_ABORTED
495 so that our caller can kill off the capture child process;
496 this will cause an EOF on the pipe from the child, so
497 "finish_tail_cap_file()" will be called, and it will clean up
500 } else if (*err != 0) {
501 /* We got an error reading the capture file.
502 XXX - pop up a dialog box? */
505 return (READ_SUCCESS);
509 finish_tail_cap_file(capture_file *cf, int *err)
513 gtk_clist_freeze(GTK_CLIST(packet_list));
515 while ((wtap_read(cf->wth, err, &data_offset))) {
516 if (cf->state == FILE_READ_ABORTED) {
517 /* Well, the user decided to abort the read. Break out of the
518 loop, and let the code below (which is called even if there
519 aren't any packets left to read) exit. */
522 read_packet(cf, data_offset);
525 if (cf->state == FILE_READ_ABORTED) {
526 /* Well, the user decided to abort the read. We're only called
527 when the child capture process closes the pipe to us (meaning
528 it's probably exited), so we can just close the capture
529 file; we return READ_ABORTED so our caller can do whatever
530 is appropriate when that happens. */
531 close_cap_file(cf, info_bar);
536 if (auto_scroll_live && cf->plist_end != NULL)
537 /* XXX - this cheats and looks inside the packet list to find the final
539 gtk_clist_moveto(GTK_CLIST(packet_list),
540 GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
542 /* We're done reading sequentially through the file. */
543 cf->state = FILE_READ_DONE;
545 /* We're done reading sequentially through the file; close the
546 sequential I/O side, to free up memory it requires. */
547 wtap_sequential_close(cf->wth);
549 /* Set the file encapsulation type now; we don't know what it is until
550 we've looked at all the packets, as we don't know until then whether
551 there's more than one type (and thus whether it's
552 WTAP_ENCAP_PER_PACKET). */
553 cf->lnk_t = wtap_file_encap(cf->wth);
555 /* Pop the "<live capture in progress>" message off the status bar. */
556 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
558 set_display_filename(cf);
560 /* Enable menu items that make sense if you're not currently running
562 set_menus_for_capture_in_progress(FALSE);
564 /* Enable menu items that make sense if you have a capture file
565 you've finished reading. */
566 set_menus_for_capture_file(TRUE);
567 set_menus_for_unsaved_capture_file(!cf->user_saved);
570 /* We got an error reading the capture file.
571 XXX - pop up a dialog box? */
574 return (READ_SUCCESS);
576 #endif /* HAVE_LIBPCAP */
579 color_filter_t *colorf;
580 proto_tree *protocol_tree;
583 } apply_color_filter_args;
586 * If no color filter has been applied, apply this one.
587 * (The "if no color filter has been applied" is to handle the case where
588 * more than one color filter matches the packet.)
591 apply_color_filter(gpointer filter_arg, gpointer argp)
593 color_filter_t *colorf = filter_arg;
594 apply_color_filter_args *args = argp;
596 if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
597 if (dfilter_apply(colorf->c_colorfilter, args->protocol_tree, args->pd, args->fdata->cap_len))
598 args->colorf = colorf;
603 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
604 union wtap_pseudo_header *pseudo_header, const u_char *buf,
607 apply_color_filter_args args;
609 proto_tree *protocol_tree = NULL;
613 /* We don't yet have a color filter to apply. */
616 /* If we don't have the time stamp of the first packet in the
617 capture, it's because this is the first packet. Save the time
618 stamp of this packet as the time stamp of the first packet. */
619 if (!firstsec && !firstusec) {
620 firstsec = fdata->abs_secs;
621 firstusec = fdata->abs_usecs;
624 fdata->cinfo = &cf->cinfo;
625 for (i = 0; i < fdata->cinfo->num_cols; i++) {
626 fdata->cinfo->col_buf[i][0] = '\0';
627 fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
632 we have a display filter and are re-applying it;
634 we have a list of color filters;
636 we have plugins to apply;
638 allocate a protocol tree root node, so that we'll construct
639 a protocol tree against which a filter expression can be
641 if ((cf->dfcode != NULL && refilter) || filter_list != NULL
643 || enabled_plugins_number > 0
646 protocol_tree = proto_tree_create_root();
648 /* Dissect the frame. */
649 edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree);
651 /* If we have a display filter, apply it if we're refiltering, otherwise
652 leave the "passed_dfilter" flag alone.
654 If we don't have a display filter, set "passed_dfilter" to 1. */
655 if (cf->dfcode != NULL) {
657 if (cf->dfcode != NULL)
658 fdata->flags.passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, buf, fdata->cap_len) ? 1 : 0;
660 fdata->flags.passed_dfilter = 1;
663 fdata->flags.passed_dfilter = 1;
665 /* If we have color filters, and the frame is to be displayed, apply
666 the color filters. */
667 if (fdata->flags.passed_dfilter) {
668 if (filter_list != NULL) {
669 args.protocol_tree = protocol_tree;
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->pkt_len = phdr->len;
779 fdata->cap_len = phdr->caplen;
780 fdata->file_off = offset;
781 fdata->lnk_t = phdr->pkt_encap;
782 fdata->abs_secs = phdr->ts.tv_sec;
783 fdata->abs_usecs = phdr->ts.tv_usec;
784 fdata->flags.encoding = CHAR_ASCII;
785 fdata->flags.visited = 0;
786 fdata->flags.marked = 0;
791 protocol_tree = proto_tree_create_root();
792 edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree);
793 passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata->cap_len);
794 proto_tree_free(protocol_tree);
795 epan_dissect_free(edt);
798 plist_end = cf->plist_end;
799 fdata->prev = plist_end;
800 if (plist_end != NULL)
801 plist_end->next = fdata;
804 cf->plist_end = fdata;
807 fdata->num = cf->count;
808 add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE);
810 /* XXX - if we didn't have read filters, or if we could avoid
811 allocating the "frame_data" structure until we knew whether
812 the frame passed the read filter, we could use a G_ALLOC_ONLY
815 ...but, at least in one test I did, where I just made the chunk
816 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
817 seem to save a noticeable amount of time or space. */
818 g_mem_chunk_free(cf->plist_chunk, fdata);
823 filter_packets(capture_file *cf, gchar *dftext)
827 if (dftext == NULL) {
828 /* The new filter is an empty filter (i.e., display all packets). */
832 * We have a filter; try to compile it.
834 if (dfilter_compile(dftext, &dfcode) != 0) {
835 /* The attempt failed; report an error. */
836 simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
841 if (dfcode == NULL) {
842 /* Yes - free the filter text, and set it to null. */
848 /* We have a valid filter. Replace the current filter. */
849 if (cf->dfilter != NULL)
851 cf->dfilter = dftext;
852 if (cf->dfcode != NULL)
853 dfilter_destroy(cf->dfcode);
856 /* Now rescan the packet list, applying the new filter, but not
857 throwing away information constructed on a previous pass. */
858 rescan_packets(cf, "Filtering", TRUE, FALSE);
863 colorize_packets(capture_file *cf)
865 rescan_packets(cf, "Colorizing", FALSE, FALSE);
869 redissect_packets(capture_file *cf)
871 rescan_packets(cf, "Reprocessing", TRUE, TRUE);
874 /* Rescan the list of packets, reconstructing the CList.
876 "action" describes why we're doing this; it's used in the progress
879 "refilter" is TRUE if we need to re-evaluate the filter expression.
881 "redissect" is TRUE if we need to make the dissectors reconstruct
882 any state information they have (because a preference that affects
883 some dissector has changed, meaning some dissector might construct
884 its state differently from the way it was constructed the last time). */
886 rescan_packets(capture_file *cf, const char *action, gboolean refilter,
892 guint32 progbar_quantum;
893 guint32 progbar_nextstep;
895 frame_data *selected_frame;
899 /* Which frame, if any, is the currently selected frame?
900 XXX - should the selected frame or the focus frame be the "current"
901 frame, that frame being the one from which "Find Frame" searches
903 selected_frame = cf->current_frame;
905 /* We don't yet know what row that frame will be on, if any, after we
906 rebuild the clist, however. */
910 /* We need to re-initialize all the state information that protocols
911 keep, because some preference that controls a dissector has changed,
912 which might cause the state information to be constructed differently
913 by that dissector. */
915 /* Initialize the table of conversations. */
916 epan_conversation_init();
918 /* Initialize protocol-specific variables */
919 init_all_protocols();
922 /* Freeze the packet list while we redo it, so we don't get any
923 screen updates while it happens. */
924 gtk_clist_freeze(GTK_CLIST(packet_list));
927 gtk_clist_clear(GTK_CLIST(packet_list));
929 /* We don't yet know which will be the first and last frames displayed. */
930 cf->first_displayed = NULL;
931 cf->last_displayed = NULL;
933 /* Iterate through the list of frames. Call a routine for each frame
934 to check whether it should be displayed and, if so, add it to
941 /* Update the progress bar when it gets to this value. */
942 progbar_nextstep = 0;
943 /* When we reach the value that triggers a progress bar update,
944 bump that value by this amount. */
945 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
946 /* Count of packets at which we've looked. */
950 progbar = create_progress_dlg(action, "Stop", &stop_flag);
952 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
953 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
954 when we update it, we have to run the GTK+ main loop to get it
955 to repaint what's pending, and doing so may involve an "ioctl()"
956 to see if there's any pending input from an X server, and doing
957 that for every packet can be costly, especially on a big file. */
958 if (count >= progbar_nextstep) {
959 /* let's not divide by zero. I should never be started
960 * with count == 0, so let's assert that
962 g_assert(cf->count > 0);
964 update_progress_dlg(progbar, (gfloat) count / cf->count);
966 progbar_nextstep += progbar_quantum;
970 /* Well, the user decided to abort the filtering. Just stop.
972 XXX - go back to the previous filter? Users probably just
973 want not to wait for a filtering operation to finish;
974 unless we cancel by having no filter, reverting to the
975 previous filter will probably be even more expensive than
976 continuing the filtering, as it involves going back to the
977 beginning and filtering, and even with no filter we currently
978 have to re-generate the entire clist, which is also expensive.
980 I'm not sure what Network Monitor does, but it doesn't appear
981 to give you an unfiltered display if you cancel. */
988 /* Since all state for the frame was destroyed, mark the frame
989 * as not visited, free the GSList referring to the state
990 * data (the per-frame data itself was freed by
991 * "init_all_protocols()"), and null out the GSList pointer. */
992 fdata->flags.visited = 0;
994 g_slist_free(fdata->pfd);
999 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1000 cf->pd, fdata->cap_len);
1002 row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
1004 if (fdata == selected_frame)
1009 /* Clear out what remains of the visited flags and per-frame data
1012 XXX - that may cause various forms of bogosity when dissecting
1013 these frames, as they won't have been seen by this sequential
1014 pass, but the only alternative I see is to keep scanning them
1015 even though the user requested that the scan stop, and that
1016 would leave the user stuck with an Ethereal grinding on
1017 until it finishes. Should we just stick them with that? */
1018 for (; fdata != NULL; fdata = fdata->next) {
1019 fdata->flags.visited = 0;
1021 g_slist_free(fdata->pfd);
1027 /* We're done filtering the packets; destroy the progress bar. */
1028 destroy_progress_dlg(progbar);
1030 /* Unfreeze the packet list. */
1031 gtk_clist_thaw(GTK_CLIST(packet_list));
1033 if (selected_row != -1) {
1034 /* The frame that was selected passed the filter; select it, make it
1035 the focus row, and make it visible. */
1036 set_selected_row(selected_row);
1037 finfo_selected = NULL;
1039 /* The selected frame didn't pass the filter; make the first frame
1040 the current frame, and leave it unselected. */
1041 unselect_packet(cf);
1042 cf->current_frame = cf->first_displayed;
1047 print_packets(capture_file *cf, print_args_t *print_args)
1053 guint32 progbar_quantum;
1054 guint32 progbar_nextstep;
1056 proto_tree *protocol_tree;
1057 gint *col_widths = NULL;
1059 gboolean print_separator;
1060 char *line_buf = NULL;
1061 int line_buf_len = 256;
1065 epan_dissect_t *edt = NULL;
1067 cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
1068 if (cf->print_fh == NULL)
1069 return FALSE; /* attempt to open destination failed */
1071 print_preamble(cf->print_fh, print_args->format);
1073 if (print_args->print_summary) {
1074 /* We're printing packet summaries. Allocate the line buffer at
1075 its initial length. */
1076 line_buf = g_malloc(line_buf_len + 1);
1078 /* Find the widths for each of the columns - maximum of the
1079 width of the title and the width of the data - and print
1080 the column titles. */
1081 col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1084 for (i = 0; i < cf->cinfo.num_cols; i++) {
1085 /* Don't pad the last column. */
1086 if (i == cf->cinfo.num_cols - 1)
1089 col_widths[i] = strlen(cf->cinfo.col_title[i]);
1090 data_width = get_column_char_width(get_column_format(i));
1091 if (data_width > col_widths[i])
1092 col_widths[i] = data_width;
1095 /* Find the length of the string for this column. */
1096 column_len = strlen(cf->cinfo.col_title[i]);
1097 if (col_widths[i] > column_len)
1098 column_len = col_widths[i];
1100 /* Make sure there's room in the line buffer for the column; if not,
1101 double its length. */
1102 line_len += column_len + 1; /* "+1" for space or \n */
1103 if (line_len > line_buf_len) {
1105 line_buf = g_realloc(line_buf, line_buf_len + 1);
1108 /* Right-justify the packet number column. */
1109 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1110 sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_title[i]);
1112 sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
1114 if (i == cf->cinfo.num_cols - 1)
1120 print_line(cf->print_fh, print_args->format, line_buf);
1123 print_separator = FALSE;
1125 /* The protocol tree will be "visible", i.e., printed, only if we're
1126 not printing a summary. */
1127 proto_tree_is_visible = !print_args->print_summary;
1129 /* Update the progress bar when it gets to this value. */
1130 progbar_nextstep = 0;
1131 /* When we reach the value that triggers a progress bar update,
1132 bump that value by this amount. */
1133 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1134 /* Count of packets at which we've looked. */
1138 progbar = create_progress_dlg("Printing", "Stop", &stop_flag);
1140 /* Iterate through the list of packets, printing the packets that
1141 were selected by the current display filter. */
1142 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1143 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1144 when we update it, we have to run the GTK+ main loop to get it
1145 to repaint what's pending, and doing so may involve an "ioctl()"
1146 to see if there's any pending input from an X server, and doing
1147 that for every packet can be costly, especially on a big file. */
1148 if (count >= progbar_nextstep) {
1149 /* let's not divide by zero. I should never be started
1150 * with count == 0, so let's assert that
1152 g_assert(cf->count > 0);
1154 update_progress_dlg(progbar, (gfloat) count / cf->count);
1156 progbar_nextstep += progbar_quantum;
1160 /* Well, the user decided to abort the printing. Just stop.
1162 XXX - note that what got generated before they did that
1163 will get printed, as we're piping to a print program; we'd
1164 have to write to a file and then hand that to the print
1165 program to make it actually not print anything. */
1171 if (fdata->flags.passed_dfilter) {
1172 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1173 cf->pd, fdata->cap_len);
1174 if (print_args->print_summary) {
1175 /* Fill in the column information, but don't bother creating
1176 the logical protocol tree. */
1177 fdata->cinfo = &cf->cinfo;
1178 for (i = 0; i < fdata->cinfo->num_cols; i++) {
1179 fdata->cinfo->col_buf[i][0] = '\0';
1180 fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
1182 edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, NULL);
1183 fill_in_columns(fdata);
1186 for (i = 0; i < cf->cinfo.num_cols; i++) {
1187 /* Find the length of the string for this column. */
1188 column_len = strlen(cf->cinfo.col_data[i]);
1189 if (col_widths[i] > column_len)
1190 column_len = col_widths[i];
1192 /* Make sure there's room in the line buffer for the column; if not,
1193 double its length. */
1194 line_len += column_len + 1; /* "+1" for space or \n */
1195 if (line_len > line_buf_len) {
1197 line_buf = g_realloc(line_buf, line_buf_len + 1);
1200 /* Right-justify the packet number column. */
1201 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1202 sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_data[i]);
1204 sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
1206 if (i == cf->cinfo.num_cols - 1)
1212 print_line(cf->print_fh, print_args->format, line_buf);
1214 if (print_separator)
1215 print_line(cf->print_fh, print_args->format, "\n");
1217 /* Create the logical protocol tree. */
1218 protocol_tree = proto_tree_create_root();
1219 edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
1221 /* Print the information in that tree. */
1222 proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
1223 cf->pd, fdata, cf->print_fh);
1225 proto_tree_free(protocol_tree);
1227 if (print_args->print_hex) {
1228 /* Print the full packet data as hex. */
1229 print_hex_data(cf->print_fh, print_args->format, cf->pd,
1230 fdata->cap_len, fdata->flags.encoding);
1233 /* Print a blank line if we print anything after this. */
1234 print_separator = TRUE;
1236 epan_dissect_free(edt);
1240 /* We're done printing the packets; destroy the progress bar. */
1241 destroy_progress_dlg(progbar);
1243 if (col_widths != NULL)
1245 if (line_buf != NULL)
1248 print_finale(cf->print_fh, print_args->format);
1250 close_print_dest(print_args->to_file, cf->print_fh);
1252 cf->print_fh = NULL;
1254 proto_tree_is_visible = FALSE;
1259 /* Scan through the packet list and change all columns that use the
1260 "command-line-specified" time stamp format to use the current
1261 value of that format. */
1263 change_time_formats(capture_file *cf)
1268 guint32 progbar_quantum;
1269 guint32 progbar_nextstep;
1275 /* Freeze the packet list while we redo it, so we don't get any
1276 screen updates while it happens. */
1279 /* Update the progress bar when it gets to this value. */
1280 progbar_nextstep = 0;
1281 /* When we reach the value that triggers a progress bar update,
1282 bump that value by this amount. */
1283 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1284 /* Count of packets at which we've looked. */
1288 progbar = create_progress_dlg("Changing time display", "Stop", &stop_flag);
1290 /* Iterate through the list of packets, checking whether the packet
1291 is in a row of the summary list and, if so, whether there are
1292 any columns that show the time in the "command-line-specified"
1293 format and, if so, update that row. */
1294 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1295 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1296 when we update it, we have to run the GTK+ main loop to get it
1297 to repaint what's pending, and doing so may involve an "ioctl()"
1298 to see if there's any pending input from an X server, and doing
1299 that for every packet can be costly, especially on a big file. */
1300 if (count >= progbar_nextstep) {
1301 /* let's not divide by zero. I should never be started
1302 * with count == 0, so let's assert that
1304 g_assert(cf->count > 0);
1306 update_progress_dlg(progbar, (gfloat) count / cf->count);
1308 progbar_nextstep += progbar_quantum;
1312 /* Well, the user decided to abort the redisplay. Just stop.
1314 XXX - this leaves the time field in the old format in
1315 frames we haven't yet processed. So it goes; should we
1316 simply not offer them the option of stopping? */
1322 /* Find what row this packet is in. */
1323 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1326 /* This packet is in the summary list, on row "row". */
1328 /* XXX - there really should be a way of checking "cf->cinfo" for this;
1329 the answer isn't going to change from packet to packet, so we should
1330 simply skip all the "change_time_formats()" work if we're not
1331 changing anything. */
1332 fdata->cinfo = &cf->cinfo;
1333 if (check_col(fdata, COL_CLS_TIME)) {
1334 /* There are columns that show the time in the "command-line-specified"
1335 format; update them. */
1336 for (i = 0; i < cf->cinfo.num_cols; i++) {
1337 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1338 /* This is one of the columns that shows the time in
1339 "command-line-specified" format; update it. */
1340 cf->cinfo.col_buf[i][0] = '\0';
1341 col_set_cls_time(fdata, i);
1342 gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
1343 cf->cinfo.col_data[i]);
1350 /* We're done redisplaying the packets; destroy the progress bar. */
1351 destroy_progress_dlg(progbar);
1353 /* Set the column widths of those columns that show the time in
1354 "command-line-specified" format. */
1355 pl_style = gtk_widget_get_style(packet_list);
1356 for (i = 0; i < cf->cinfo.num_cols; i++) {
1357 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1358 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1359 gdk_string_width(pl_style->font, get_column_longest_string(COL_CLS_TIME)));
1363 /* Unfreeze the packet list. */
1368 clear_tree_and_hex_views(void)
1370 /* Clear the hex dump. */
1371 gtk_text_freeze(GTK_TEXT(byte_view));
1372 gtk_text_set_point(GTK_TEXT(byte_view), 0);
1373 gtk_text_forward_delete(GTK_TEXT(byte_view),
1374 gtk_text_get_length(GTK_TEXT(byte_view)));
1375 gtk_text_thaw(GTK_TEXT(byte_view));
1377 /* Remove all nodes in ctree. This is how it's done in testgtk.c in GTK+ */
1378 gtk_clist_clear ( GTK_CLIST(tree_view) );
1383 find_packet(capture_file *cf, dfilter *sfcode)
1385 frame_data *start_fd;
1387 frame_data *new_fd = NULL;
1390 guint32 progbar_quantum;
1391 guint32 progbar_nextstep;
1393 proto_tree *protocol_tree;
1394 gboolean frame_matched;
1396 epan_dissect_t *edt;
1398 start_fd = cf->current_frame;
1399 if (start_fd != NULL) {
1400 /* Iterate through the list of packets, starting at the packet we've
1401 picked, calling a routine to run the filter on the packet, see if
1402 it matches, and stop if so. */
1406 /* Update the progress bar when it gets to this value. */
1407 progbar_nextstep = 0;
1408 /* When we reach the value that triggers a progress bar update,
1409 bump that value by this amount. */
1410 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1413 progbar = create_progress_dlg("Searching", "Cancel", &stop_flag);
1417 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1418 when we update it, we have to run the GTK+ main loop to get it
1419 to repaint what's pending, and doing so may involve an "ioctl()"
1420 to see if there's any pending input from an X server, and doing
1421 that for every packet can be costly, especially on a big file. */
1422 if (count >= progbar_nextstep) {
1423 /* let's not divide by zero. I should never be started
1424 * with count == 0, so let's assert that
1426 g_assert(cf->count > 0);
1428 update_progress_dlg(progbar, (gfloat) count / cf->count);
1430 progbar_nextstep += progbar_quantum;
1434 /* Well, the user decided to abort the search. Go back to the
1435 frame where we started. */
1440 /* Go past the current frame. */
1441 if (cf->sbackward) {
1442 /* Go on to the previous frame. */
1443 fdata = fdata->prev;
1445 fdata = cf->plist_end; /* wrap around */
1447 /* Go on to the next frame. */
1448 fdata = fdata->next;
1450 fdata = cf->plist; /* wrap around */
1455 /* Is this packet in the display? */
1456 if (fdata->flags.passed_dfilter) {
1457 /* Yes. Does it match the search filter? */
1458 protocol_tree = proto_tree_create_root();
1459 wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
1460 cf->pd, fdata->cap_len);
1461 edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
1462 frame_matched = dfilter_apply(sfcode, protocol_tree, cf->pd, fdata->cap_len);
1463 proto_tree_free(protocol_tree);
1464 epan_dissect_free(edt);
1465 if (frame_matched) {
1467 break; /* found it! */
1471 if (fdata == start_fd) {
1472 /* We're back to the frame we were on originally, and that frame
1473 doesn't match the search filter. The search failed. */
1478 /* We're done scanning the packets; destroy the progress bar. */
1479 destroy_progress_dlg(progbar);
1482 if (new_fd != NULL) {
1483 /* We found a frame. Find what row it's in. */
1484 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), new_fd);
1485 g_assert(row != -1);
1487 /* Select that row, make it the focus row, and make it visible. */
1488 set_selected_row(row);
1489 return TRUE; /* success */
1491 return FALSE; /* failure */
1495 goto_frame(capture_file *cf, guint fnumber)
1500 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
1504 return NO_SUCH_FRAME; /* we didn't find that frame */
1505 if (!fdata->flags.passed_dfilter)
1506 return FRAME_NOT_DISPLAYED; /* the frame with that number isn't displayed */
1508 /* We found that frame, and it's currently being displayed.
1509 Find what row it's in. */
1510 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1511 g_assert(row != -1);
1513 /* Select that row, make it the focus row, and make it visible. */
1514 set_selected_row(row);
1518 /* Select the packet on a given row. */
1520 select_packet(capture_file *cf, int row)
1524 /* Get the frame data struct pointer for this frame */
1525 fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
1527 if (fdata == NULL) {
1528 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
1529 the first entry is added to it by "real_insert_row()", that row
1530 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
1531 our version and the vanilla GTK+ version).
1533 This means that a "select-row" signal is emitted; this causes
1534 "packet_list_select_cb()" to be called, which causes "select_packet()"
1537 "select_packet()" fetches, above, the data associated with the
1538 row that was selected; however, as "gtk_clist_append()", which
1539 called "real_insert_row()", hasn't yet returned, we haven't yet
1540 associated any data with that row, so we get back a null pointer.
1542 We can't assume that there's only one frame in the frame list,
1543 either, as we may be filtering the display.
1545 We therefore assume that, if "row" is 0, i.e. the first row
1546 is being selected, and "cf->first_displayed" equals
1547 "cf->last_displayed", i.e. there's only one frame being
1548 displayed, that frame is the frame we want.
1550 This means we have to set "cf->first_displayed" and
1551 "cf->last_displayed" before adding the row to the
1552 GtkCList; see the comment in "add_packet_to_packet_list()". */
1554 if (row == 0 && cf->first_displayed == cf->last_displayed)
1555 fdata = cf->first_displayed;
1558 /* Record that this frame is the current frame. */
1559 cf->current_frame = fdata;
1561 /* Get the data in that frame. */
1562 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1563 cf->pd, fdata->cap_len);
1565 /* Create the logical protocol tree. */
1566 if (cf->protocol_tree)
1567 proto_tree_free(cf->protocol_tree);
1568 cf->protocol_tree = proto_tree_create_root();
1569 proto_tree_is_visible = TRUE;
1570 cf->edt = epan_dissect_new(&cf->pseudo_header, cf->pd, cf->current_frame,
1572 proto_tree_is_visible = FALSE;
1574 /* Display the GUI protocol tree and hex dump. */
1575 clear_tree_and_hex_views();
1576 proto_tree_draw(cf->protocol_tree, tree_view);
1577 packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->current_frame, NULL);
1579 /* A packet is selected. */
1580 set_menus_for_selected_packet(TRUE);
1583 /* Unselect the selected packet, if any. */
1585 unselect_packet(capture_file *cf)
1587 /* Destroy the protocol tree for that packet. */
1588 if (cf->protocol_tree != NULL) {
1589 proto_tree_free(cf->protocol_tree);
1590 cf->protocol_tree = NULL;
1591 epan_dissect_free(cf->edt);
1594 finfo_selected = NULL;
1596 /* Clear out the display of that packet. */
1597 clear_tree_and_hex_views();
1599 /* No packet is selected. */
1600 set_menus_for_selected_packet(FALSE);
1603 /* Set the selected row and the focus row of the packet list to the specified
1604 row, and make it visible if it's not currently visible. */
1606 set_selected_row(int row)
1608 if (gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) != GTK_VISIBILITY_FULL)
1609 gtk_clist_moveto(GTK_CLIST(packet_list), row, -1, 0.0, 0.0);
1611 /* XXX - why is there no "gtk_clist_set_focus_row()", so that we
1612 can make the row for the frame we found the focus row?
1616 http://www.gnome.org/mailing-lists/archives/gtk-list/2000-January/0038.shtml
1619 GTK_CLIST(packet_list)->focus_row = row;
1621 gtk_clist_select_row(GTK_CLIST(packet_list), row, -1);
1625 freeze_clist(capture_file *cf)
1629 /* Make the column sizes static, so they don't adjust while
1630 we're reading the capture file (freezing the clist doesn't
1631 seem to suffice). */
1632 for (i = 0; i < cf->cinfo.num_cols; i++)
1633 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1634 gtk_clist_freeze(GTK_CLIST(packet_list));
1638 thaw_clist(capture_file *cf)
1642 for (i = 0; i < cf->cinfo.num_cols; i++) {
1643 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1644 /* Set this column's width to the appropriate value. */
1645 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1646 cf->cinfo.col_width[i]);
1648 /* Make this column's size dynamic, so that it adjusts to the
1649 appropriate size. */
1650 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1653 gtk_clist_thaw(GTK_CLIST(packet_list));
1655 /* Hopefully, the columns have now gotten their appropriate sizes;
1656 make them resizeable - a column that auto-resizes cannot be
1657 resized by the user, and *vice versa*. */
1658 for (i = 0; i < cf->cinfo.num_cols; i++)
1659 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1663 save_cap_file(char *fname, capture_file *cf, gboolean save_filtered, gboolean save_marked,
1666 gchar *from_filename;
1667 gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
1673 struct wtap_pkthdr hdr;
1674 union wtap_pseudo_header pseudo_header;
1677 name_ptr = get_basename(fname);
1678 msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
1679 save_msg = g_malloc(msg_len);
1680 snprintf(save_msg, msg_len, save_fmt, name_ptr);
1681 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
1684 if (!save_filtered && !save_marked && save_format == cf->cd_t) {
1685 /* We're not filtering packets, and we're saving it in the format
1686 it's already in, so we can just move or copy the raw data. */
1688 /* In this branch, we set "err" only if we get an error, so we
1689 must first clear it. */
1691 if (cf->is_tempfile) {
1692 /* The file being saved is a temporary file from a live
1693 capture, so it doesn't need to stay around under that name;
1694 first, try renaming the capture buffer file to the new name. */
1696 if (rename(cf->filename, fname) == 0) {
1697 /* That succeeded - there's no need to copy the source file. */
1698 from_filename = NULL;
1701 if (errno == EXDEV) {
1702 /* They're on different file systems, so we have to copy the
1705 from_filename = cf->filename;
1707 /* The rename failed, but not because they're on different
1708 file systems - put up an error message. (Or should we
1709 just punt and try to copy? The only reason why I'd
1710 expect the rename to fail and the copy to succeed would
1711 be if we didn't have permission to remove the file from
1712 the temporary directory, and that might be fixable - but
1713 is it worth requiring the user to go off and fix it?) */
1715 simple_dialog(ESD_TYPE_CRIT, NULL,
1716 file_rename_error_message(err), fname);
1722 from_filename = cf->filename;
1725 /* It's a permanent file, so we should copy it, and not remove the
1728 from_filename = cf->filename;
1730 /* Copy the file, if we haven't moved it. */
1732 if (!copy_binary_file(from_filename, fname)) {
1737 /* Either we're filtering packets, or we're saving in a different
1738 format; we can't do that by copying or moving the capture file,
1739 we have to do it by writing the packets out in Wiretap. */
1740 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
1742 simple_dialog(ESD_TYPE_CRIT, NULL,
1743 file_open_error_message(err, TRUE), fname);
1747 /* XXX - have a way to save only the packets currently selected by
1748 the display filter or the marked ones.
1750 If we do that, should we make that file the current file? If so,
1751 it means we can no longer get at the other packets. What does
1753 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1754 /* XXX - do a progress bar */
1755 if ((!save_filtered && !save_marked) ||
1756 (save_filtered && fdata->flags.passed_dfilter && !save_marked) ||
1757 (save_marked && fdata->flags.marked && !save_filtered) ||
1758 (save_filtered && save_marked && fdata->flags.passed_dfilter &&
1759 fdata->flags.marked)) {
1761 - we're saving all frames, or
1762 - we're saving filtered frames and this one passed the display filter or
1763 - we're saving marked frames (and it has been marked) or
1764 - we're saving filtered _and_ marked frames,
1766 hdr.ts.tv_sec = fdata->abs_secs;
1767 hdr.ts.tv_usec = fdata->abs_usecs;
1768 hdr.caplen = fdata->cap_len;
1769 hdr.len = fdata->pkt_len;
1770 hdr.pkt_encap = fdata->lnk_t;
1771 wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1772 pd, fdata->cap_len);
1774 if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
1775 simple_dialog(ESD_TYPE_CRIT, NULL,
1776 file_write_error_message(err), fname);
1777 wtap_dump_close(pdh, &err);
1783 if (!wtap_dump_close(pdh, &err)) {
1784 simple_dialog(ESD_TYPE_WARN, NULL,
1785 file_close_error_message(err), fname);
1792 /* Pop the "Saving:" message off the status bar. */
1793 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
1795 if (!save_filtered && !save_marked) {
1796 /* We saved the entire capture, not just some packets from it.
1797 Open and read the file we saved it to.
1799 XXX - this is somewhat of a waste; we already have the
1800 packets, all this gets us is updated file type information
1801 (which we could just stuff into "cf"), and having the new
1802 file be the one we have opened and from which we're reading
1803 the data, and it means we have to spend time opening and
1804 reading the file, which could be a significant amount of
1805 time if the file is large. */
1806 cf->user_saved = TRUE;
1808 if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
1809 /* XXX - report errors if this fails? */
1810 switch (read_cap_file(cf, &err)) {
1814 /* Just because we got an error, that doesn't mean we were unable
1815 to read any of the file; we handle what we could get from the
1820 /* The user bailed out of re-reading the capture file; the
1821 capture file has been closed - just return (without
1822 changing any menu settings; "close_cap_file()" set them
1823 correctly for the "no capture file open" state). */
1826 set_menus_for_unsaved_capture_file(FALSE);
1834 file_open_error_message(int err, gboolean for_writing)
1837 static char errmsg_errno[1024+1];
1841 case WTAP_ERR_NOT_REGULAR_FILE:
1842 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1845 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1846 case WTAP_ERR_UNSUPPORTED:
1847 /* Seen only when opening a capture file for reading. */
1848 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1851 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1852 /* Seen only when opening a capture file for writing. */
1853 errmsg = "Ethereal does not support writing capture files in that format.";
1856 case WTAP_ERR_UNSUPPORTED_ENCAP:
1857 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1859 errmsg = "Ethereal cannot save this capture in that format.";
1861 errmsg = "The file \"%s\" is a capture for a network type that Ethereal doesn't support.";
1864 case WTAP_ERR_BAD_RECORD:
1865 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1868 case WTAP_ERR_CANT_OPEN:
1870 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1872 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1875 case WTAP_ERR_SHORT_READ:
1876 errmsg = "The file \"%s\" appears to have been cut short"
1877 " in the middle of a packet.";
1880 case WTAP_ERR_SHORT_WRITE:
1881 errmsg = "A full header couldn't be written to the file \"%s\".";
1886 errmsg = "The path to the file \"%s\" does not exist.";
1888 errmsg = "The file \"%s\" does not exist.";
1893 errmsg = "You do not have permission to create or write to the file \"%s\".";
1895 errmsg = "You do not have permission to read the file \"%s\".";
1899 errmsg = "\"%s\" is a directory (folder), not a file.";
1903 snprintf(errmsg_errno, sizeof(errmsg_errno),
1904 "The file \"%%s\" could not be opened: %s.",
1905 wtap_strerror(err));
1906 errmsg = errmsg_errno;
1913 file_rename_error_message(int err)
1916 static char errmsg_errno[1024+1];
1921 errmsg = "The path to the file \"%s\" does not exist.";
1925 errmsg = "You do not have permission to move the capture file to \"%s\".";
1929 snprintf(errmsg_errno, sizeof(errmsg_errno),
1930 "The file \"%%s\" could not be moved: %s.",
1931 wtap_strerror(err));
1932 errmsg = errmsg_errno;
1939 file_read_error_message(int err)
1941 static char errmsg_errno[1024+1];
1943 snprintf(errmsg_errno, sizeof(errmsg_errno),
1944 "An error occurred while reading from the file \"%%s\": %s.",
1945 wtap_strerror(err));
1946 return errmsg_errno;
1950 file_write_error_message(int err)
1953 static char errmsg_errno[1024+1];
1958 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1963 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1968 snprintf(errmsg_errno, sizeof(errmsg_errno),
1969 "An error occurred while writing to the file \"%%s\": %s.",
1970 wtap_strerror(err));
1971 errmsg = errmsg_errno;
1977 /* Check for write errors - if the file is being written to an NFS server,
1978 a write error may not show up until the file is closed, as NFS clients
1979 might not send writes to the server until the "write()" call finishes,
1980 so that the write may fail on the server but the "write()" may succeed. */
1982 file_close_error_message(int err)
1985 static char errmsg_errno[1024+1];
1989 case WTAP_ERR_CANT_CLOSE:
1990 errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
1993 case WTAP_ERR_SHORT_WRITE:
1994 errmsg = "Not all the data could be written to the file \"%s\".";
1998 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
2003 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
2008 snprintf(errmsg_errno, sizeof(errmsg_errno),
2009 "An error occurred while closing the file \"%%s\": %s.",
2010 wtap_strerror(err));
2011 errmsg = errmsg_errno;
2018 /* Copies a file in binary mode, for those operating systems that care about
2020 * Returns TRUE on success, FALSE on failure. If a failure, it also
2021 * displays a simple dialog window with the error message.
2024 copy_binary_file(char *from_filename, char *to_filename)
2026 int from_fd, to_fd, nread, nwritten, err;
2027 guint8 pd[65536]; /* XXX - Hmm, 64K here, 64K in save_cap_file(),
2028 perhaps we should make just one 64K buffer. */
2030 /* Copy the raw bytes of the file. */
2031 from_fd = open(from_filename, O_RDONLY | O_BINARY);
2034 simple_dialog(ESD_TYPE_CRIT, NULL,
2035 file_open_error_message(err, TRUE), from_filename);
2039 /* Use open() instead of creat() so that we can pass the O_BINARY
2040 flag, which is relevant on Win32; it appears that "creat()"
2041 may open the file in text mode, not binary mode, but we want
2042 to copy the raw bytes of the file, so we need the output file
2043 to be open in binary mode. */
2044 to_fd = open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
2047 simple_dialog(ESD_TYPE_CRIT, NULL,
2048 file_open_error_message(err, TRUE), to_filename);
2053 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
2054 nwritten = write(to_fd, pd, nread);
2055 if (nwritten < nread) {
2059 err = WTAP_ERR_SHORT_WRITE;
2060 simple_dialog(ESD_TYPE_CRIT, NULL,
2061 file_write_error_message(err), to_filename);
2069 simple_dialog(ESD_TYPE_CRIT, NULL,
2070 file_read_error_message(err), from_filename);
2076 if (close(to_fd) < 0) {
2078 simple_dialog(ESD_TYPE_CRIT, NULL,
2079 file_close_error_message(err), to_filename);