4 * $Id: file.c,v 1.158 2000/01/25 01:05:06 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.
51 #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>
79 #include "simple_dialog.h"
81 #include "gtk/proto_draw.h"
83 #include "conversation.h"
88 extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view;
89 extern guint file_ctx;
91 gboolean auto_scroll_live = FALSE;
93 static guint32 firstsec, firstusec;
94 static guint32 prevsec, prevusec;
96 static void wtap_dispatch_cb(u_char *, const struct wtap_pkthdr *, int,
99 static void freeze_clist(capture_file *cf);
100 static void thaw_clist(capture_file *cf);
102 static char *file_rename_error_message(int err);
103 static char *file_close_error_message(int err);
105 /* Update the progress bar this many times when reading a file. */
106 #define N_PROGBAR_UPDATES 100
109 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
117 wth = wtap_open_offline(fname, &err);
121 /* Find the size of the file. */
124 if (fstat(fd, &cf_stat) < 0) {
130 /* The open succeeded. Close whatever capture file we had open,
131 and fill in the information for this file. */
132 close_cap_file(cf, info_bar);
134 /* Initialize the table of conversations. */
137 /* Initialize protocol-specific variables */
138 init_all_protocols();
143 cf->f_len = cf_stat.st_size;
145 /* Set the file name because we need it to set the follow stream filter.
146 XXX - is that still true? We need it for other reasons, though,
148 cf->filename = g_strdup(fname);
150 /* Indicate whether it's a permanent or temporary file. */
151 cf->is_tempfile = is_tempfile;
153 /* If it's a temporary capture buffer file, mark it as not saved. */
154 cf->user_saved = !is_tempfile;
156 cf->cd_t = wtap_file_type(cf->wth);
161 cf->snap = wtap_snapshot_length(cf->wth);
162 cf->update_progbar = FALSE;
163 cf->progbar_quantum = 0;
164 cf->progbar_nextstep = 0;
165 firstsec = 0, firstusec = 0;
166 prevsec = 0, prevusec = 0;
171 simple_dialog(ESD_TYPE_WARN, NULL,
172 file_open_error_message(err, FALSE), fname);
176 /* Reset everything to a pristine state */
178 close_cap_file(capture_file *cf, void *w)
180 frame_data *fd, *fd_next;
190 /* We have no file open... */
191 if (cf->filename != NULL) {
192 /* If it's a temporary file, remove it. */
194 unlink(cf->filename);
195 g_free(cf->filename);
198 /* ...which means we have nothing to save. */
199 cf->user_saved = FALSE;
201 for (fd = cf->plist; fd != NULL; fd = fd_next) {
205 if (cf->rfcode != NULL) {
206 dfilter_destroy(cf->rfcode);
210 cf->plist_end = NULL;
211 unselect_packet(cf); /* nothing to select */
212 cf->first_displayed = NULL;
213 cf->last_displayed = NULL;
215 /* Clear the packet list. */
216 gtk_clist_freeze(GTK_CLIST(packet_list));
217 gtk_clist_clear(GTK_CLIST(packet_list));
218 gtk_clist_thaw(GTK_CLIST(packet_list));
220 /* Clear any file-related status bar messages.
221 XXX - should be "clear *ALL* file-related status bar messages;
222 will there ever be more than one on the stack? */
223 gtk_statusbar_pop(GTK_STATUSBAR(w), file_ctx);
225 /* Restore the standard title bar message. */
226 set_main_window_name("The Ethereal Network Analyzer");
228 /* Disable all menu items that make sense only if you have a capture. */
229 set_menus_for_capture_file(FALSE);
230 set_menus_for_unsaved_capture_file(FALSE);
231 set_menus_for_captured_packets(FALSE);
232 set_menus_for_selected_packet(FALSE);
235 /* Set the file name in the status line, in the name for the main window,
236 and in the name for the main window's icon. */
238 set_display_filename(capture_file *cf)
242 gchar *done_fmt = " File: %s Drops: %u";
244 gchar *win_name_fmt = "%s - Ethereal";
247 if (!cf->is_tempfile) {
248 /* Get the last component of the file name, and put that in the
250 if ((name_ptr = (gchar *) strrchr(cf->filename, PATH_SEPARATOR)) == NULL)
251 name_ptr = cf->filename;
255 /* The file we read is a temporary file from a live capture;
256 we don't mention its name in the status bar. */
257 name_ptr = "<capture>";
260 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
261 done_msg = g_malloc(msg_len);
262 snprintf(done_msg, msg_len, done_fmt, name_ptr, cf->drops);
263 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
266 msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
267 win_name = g_malloc(msg_len);
268 snprintf(win_name, msg_len, win_name_fmt, name_ptr);
269 set_main_window_name(win_name);
274 read_cap_file(capture_file *cf)
276 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
281 char errmsg_errno[1024+1];
282 gchar err_str[2048+1];
284 if ((name_ptr = (gchar *) strrchr(cf->filename, PATH_SEPARATOR)) == NULL)
285 name_ptr = cf->filename;
289 msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
290 load_msg = g_malloc(msg_len);
291 snprintf(load_msg, msg_len, load_fmt, name_ptr);
292 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
295 cf->update_progbar = TRUE;
296 /* Update the progress bar when it gets to this value. */
297 cf->progbar_nextstep = 0;
298 /* When we reach the value that triggers a progress bar update,
299 bump that value by this amount. */
300 cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
303 proto_tree_is_visible = FALSE;
304 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
305 /* Set the file encapsulation type now; we don't know what it is until
306 we've looked at all the packets, as we don't know until then whether
307 there's more than one type (and thus whether it's
308 WTAP_ENCAP_PER_PACKET). */
309 cf->lnk_t = wtap_file_encap(cf->wth);
312 cf->filed = open(cf->filename, O_RDONLY);
313 cf->fh = filed_open(cf->filed, "rb");
314 cf->current_frame = cf->first_displayed;
317 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
318 gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
320 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
321 set_display_filename(cf);
323 /* Enable menu items that make sense if you have a capture file you've
325 set_menus_for_capture_file(TRUE);
326 set_menus_for_unsaved_capture_file(!cf->user_saved);
328 /* Enable menu items that make sense if you have some captured packets. */
329 set_menus_for_captured_packets(TRUE);
331 /* If we have any displayed packets to select, select the first of those
332 packets by making the first row the selected row. */
333 if (cf->first_displayed != NULL)
334 gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
337 /* Put up a message box noting that the read failed somewhere along
338 the line. Don't throw out the stuff we managed to read, though,
342 case WTAP_ERR_CANT_READ:
343 errmsg = "An attempt to read from the file failed for"
344 " some unknown reason.";
347 case WTAP_ERR_SHORT_READ:
348 errmsg = "The capture file appears to have been cut short"
349 " in the middle of a packet.";
352 case WTAP_ERR_BAD_RECORD:
353 errmsg = "The capture file appears to be damaged or corrupt.";
357 sprintf(errmsg_errno, "An error occurred while reading the"
358 " capture file: %s.", wtap_strerror(err));
359 errmsg = errmsg_errno;
362 snprintf(err_str, sizeof err_str, errmsg);
363 simple_dialog(ESD_TYPE_WARN, NULL, err_str);
371 start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
376 err = open_cap_file(fname, is_tempfile, cf);
378 /* Disable menu items that make no sense if you're currently running
380 set_menus_for_capture_in_progress(TRUE);
382 /* Enable menu items that make sense if you have some captured
383 packets (yes, I know, we don't have any *yet*). */
384 set_menus_for_captured_packets(TRUE);
386 for (i = 0; i < cf->cinfo.num_cols; i++) {
387 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
388 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
390 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
391 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
392 cf->cinfo.col_width[i]);
393 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
397 /* Yes, "open_cap_file()" set this - but it set it to a file handle
398 from Wiretap, which will be closed when we close the file; we
399 want it to remain open even after that, so that we can read
400 packet data from it. */
401 cf->fh = file_open(fname, "rb");
403 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
404 " <live capture in progress>");
410 continue_tail_cap_file(capture_file *cf, int to_read)
414 gtk_clist_freeze(GTK_CLIST(packet_list));
416 wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf, &err);
418 gtk_clist_thaw(GTK_CLIST(packet_list));
419 if (auto_scroll_live && cf->plist_end != NULL)
420 gtk_clist_moveto(GTK_CLIST(packet_list),
421 cf->plist_end->row, -1, 1.0, 1.0);
426 finish_tail_cap_file(capture_file *cf)
430 gtk_clist_freeze(GTK_CLIST(packet_list));
432 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
435 if (auto_scroll_live && cf->plist_end != NULL)
436 gtk_clist_moveto(GTK_CLIST(packet_list),
437 cf->plist_end->row, -1, 1.0, 1.0);
439 /* Set the file encapsulation type now; we don't know what it is until
440 we've looked at all the packets, as we don't know until then whether
441 there's more than one type (and thus whether it's
442 WTAP_ENCAP_PER_PACKET). */
443 cf->lnk_t = wtap_file_encap(cf->wth);
445 /* There's nothing more to read from the capture file - close it. */
449 /* Pop the "<live capture in progress>" message off the status bar. */
450 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
452 set_display_filename(cf);
454 /* Enable menu items that make sense if you're not currently running
456 set_menus_for_capture_in_progress(FALSE);
458 /* Enable menu items that make sense if you have a capture file
459 you've finished reading. */
460 set_menus_for_capture_file(TRUE);
461 set_menus_for_unsaved_capture_file(!cf->user_saved);
465 #endif /* HAVE_LIBPCAP */
468 color_filter_t *colorf;
469 proto_tree *protocol_tree;
471 } apply_color_filter_args;
474 * If no color filter has been applied, apply this one.
475 * (The "if no color filter has been applied" is to handle the case where
476 * more than one color filter matches the packet.)
479 apply_color_filter(gpointer filter_arg, gpointer argp)
481 color_filter_t *colorf = filter_arg;
482 apply_color_filter_args *args = argp;
484 if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
485 if (dfilter_apply(colorf->c_colorfilter, args->protocol_tree, args->pd))
486 args->colorf = colorf;
491 add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf)
493 apply_color_filter_args args;
495 proto_tree *protocol_tree = NULL;
497 /* We don't yet have a color filter to apply. */
500 /* If we don't have the time stamp of the first packet in the
501 capture, it's because this is the first packet. Save the time
502 stamp of this packet as the time stamp of the first packet. */
503 if (!firstsec && !firstusec) {
504 firstsec = fdata->abs_secs;
505 firstusec = fdata->abs_usecs;
508 /* Get the time elapsed between the first packet and this packet. */
509 cf->esec = fdata->abs_secs - firstsec;
510 if (firstusec <= fdata->abs_usecs) {
511 cf->eusec = fdata->abs_usecs - firstusec;
513 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
517 fdata->cinfo = &cf->cinfo;
518 for (i = 0; i < fdata->cinfo->num_cols; i++) {
519 fdata->cinfo->col_data[i][0] = '\0';
522 /* Apply the filters */
523 if (cf->dfcode != NULL || filter_list != NULL) {
524 protocol_tree = proto_tree_create_root();
525 dissect_packet(buf, fdata, protocol_tree);
526 if (cf->dfcode != NULL)
527 fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
529 fdata->passed_dfilter = TRUE;
531 /* Apply color filters, if we have any. */
532 if (filter_list != NULL) {
533 args.protocol_tree = protocol_tree;
535 g_slist_foreach(filter_list, apply_color_filter, &args);
537 proto_tree_free(protocol_tree);
542 protocol_tree = proto_tree_create_root();
544 dissect_packet(buf, fdata, protocol_tree);
545 fdata->passed_dfilter = TRUE;
548 proto_tree_free(protocol_tree);
552 if (fdata->passed_dfilter) {
553 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
554 the first entry is added to it by "real_insert_row()", that row
555 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
556 our version and the vanilla GTK+ version).
558 This means that a "select-row" signal is emitted; this causes
559 "packet_list_select_cb()" to be called, which causes "select_packet()"
562 "select_packet()" searches the list of frames for a frame with the
563 row number passed into it; however, as "gtk_clist_append()", which
564 called "real_insert_row()", hasn't yet returned, we don't know what
565 the row number is, so we can't correctly set "fd->row" for that frame
568 This means that we won't find the frame for that row.
570 We can't assume that there's only one frame in the frame list,
571 either, as we may be filtering the display.
573 Therefore, we set "fdata->row" to 0, under the assumption that
574 the row number passed to "select_packet()" will be 0 (as we're
575 adding the first row to the list; it gets set to the proper
579 /* If we don't have the time stamp of the previous displayed packet,
580 it's because this is the first displayed packet. Save the time
581 stamp of this packet as the time stamp of the previous displayed
583 if (!prevsec && !prevusec) {
584 prevsec = fdata->abs_secs;
585 prevusec = fdata->abs_usecs;
588 /* Get the time elapsed between the first packet and this packet. */
589 fdata->rel_secs = cf->esec;
590 fdata->rel_usecs = cf->eusec;
592 /* Get the time elapsed between the previous displayed packet and
594 fdata->del_secs = fdata->abs_secs - prevsec;
595 if (prevusec <= fdata->abs_usecs) {
596 fdata->del_usecs = fdata->abs_usecs - prevusec;
598 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
601 prevsec = fdata->abs_secs;
602 prevusec = fdata->abs_usecs;
604 fill_in_columns(fdata);
606 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
609 if (filter_list != NULL && (args.colorf != NULL)) {
610 gtk_clist_set_background(GTK_CLIST(packet_list), row,
611 &args.colorf->bg_color);
612 gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
613 &args.colorf->fg_color);
615 gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
616 gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
619 /* If we haven't yet seen the first frame, this is it. */
620 if (cf->first_displayed == NULL)
621 cf->first_displayed = fdata;
623 /* This is the last frame we've seen so far. */
624 cf->last_displayed = fdata;
626 /* If this was the current frame, remember the row it's in, so
627 we can arrange that it's on the screen when we're done. */
628 if (cf->current_frame == fdata)
629 cf->current_row = row;
631 fdata->row = -1; /* not in the display */
636 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
639 capture_file *cf = (capture_file *) user;
641 proto_tree *protocol_tree;
642 frame_data *plist_end;
646 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
647 when we update it, we have to run the GTK+ main loop to get it
648 to repaint what's pending, and doing so may involve an "ioctl()"
649 to see if there's any pending input from an X server, and doing
650 that for every packet can be costly, especially on a big file.
652 Do so only if we were told to do so; when reading a capture file
653 being updated by a live capture, we don't do so (as we're not
654 "done" until the capture stops, so we don't know how close to
657 if (cf->update_progbar && offset >= cf->progbar_nextstep) {
658 file_pos = lseek(cf->filed, 0, SEEK_CUR);
659 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
660 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), prog_val);
661 cf->progbar_nextstep += cf->progbar_quantum;
662 while (gtk_events_pending())
663 gtk_main_iteration();
666 /* Allocate the next list entry, and add it to the list. */
667 fdata = (frame_data *) g_malloc(sizeof(frame_data));
671 fdata->pkt_len = phdr->len;
672 fdata->cap_len = phdr->caplen;
673 fdata->file_off = offset;
674 fdata->lnk_t = phdr->pkt_encap;
675 fdata->abs_secs = phdr->ts.tv_sec;
676 fdata->abs_usecs = phdr->ts.tv_usec;
677 fdata->encoding = CHAR_ASCII;
678 fdata->pseudo_header = phdr->pseudo_header;
683 protocol_tree = proto_tree_create_root();
684 dissect_packet(buf, fdata, protocol_tree);
685 passed = dfilter_apply(cf->rfcode, protocol_tree, cf->pd);
686 proto_tree_free(protocol_tree);
689 plist_end = cf->plist_end;
690 fdata->prev = plist_end;
691 if (plist_end != NULL)
692 plist_end->next = fdata;
695 cf->plist_end = fdata;
698 fdata->num = cf->count;
699 add_packet_to_packet_list(fdata, cf, buf);
705 filter_packets(capture_file *cf, gchar *dftext)
709 if (dftext == NULL) {
710 /* The new filter is an empty filter (i.e., display all packets). */
714 * We have a filter; try to compile it.
716 if (dfilter_compile(dftext, &dfcode) != 0) {
717 /* The attempt failed; report an error. */
718 simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
723 if (dfcode == NULL) {
724 /* Yes - free the filter text, and set it to null. */
730 /* We have a valid filter. Replace the current filter. */
731 if (cf->dfilter != NULL)
733 cf->dfilter = dftext;
734 if (cf->dfcode != NULL)
735 dfilter_destroy(cf->dfcode);
738 /* Now go through the list of packets we've read from the capture file,
739 applying the current display filter, and, if the packet passes the
740 display filter, add it to the summary display, appropriately
741 colored. (That's how we colorize the display - it's like filtering
742 the display, only we don't install a new filter.) */
743 colorize_packets(cf);
748 colorize_packets(capture_file *cf)
751 guint32 progbar_quantum;
752 guint32 progbar_nextstep;
755 /* We need to re-initialize all the state information that protocols
756 keep, because we're making a fresh pass through all the packets. */
758 /* Initialize the table of conversations. */
761 /* Initialize protocol-specific variables */
762 init_all_protocols();
764 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
766 /* Freeze the packet list while we redo it, so we don't get any
767 screen updates while it happens. */
768 gtk_clist_freeze(GTK_CLIST(packet_list));
771 gtk_clist_clear(GTK_CLIST(packet_list));
773 /* We don't yet know which will be the first and last frames displayed. */
774 cf->first_displayed = NULL;
775 cf->last_displayed = NULL;
777 /* If a packet was selected, we don't know yet what row, if any, it'll
779 cf->current_row = -1;
781 /* Iterate through the list of packets, calling a routine
782 to run the filter on the packet, see if it matches, and
783 put it in the display list if so. */
789 proto_tree_is_visible = FALSE;
791 /* Update the progress bar when it gets to this value. */
792 progbar_nextstep = 0;
793 /* When we reach the value that triggers a progress bar update,
794 bump that value by this amount. */
795 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
796 /* Count of packets at which we've looked. */
799 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
801 for (fd = cf->plist; fd != NULL; fd = fd->next) {
802 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
803 when we update it, we have to run the GTK+ main loop to get it
804 to repaint what's pending, and doing so may involve an "ioctl()"
805 to see if there's any pending input from an X server, and doing
806 that for every packet can be costly, especially on a big file. */
807 if (count >= progbar_nextstep) {
808 /* let's not divide by zero. I should never be started
809 * with count == 0, so let's assert that
811 g_assert(cf->count > 0);
813 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
814 (gfloat) count / cf->count);
816 progbar_nextstep += progbar_quantum;
817 while (gtk_events_pending())
818 gtk_main_iteration();
823 wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
825 add_packet_to_packet_list(fd, cf, cf->pd);
828 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
830 if (cf->current_row != -1) {
831 /* The current frame passed the filter; make sure it's visible. */
832 if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), cf->current_row))
833 gtk_clist_moveto(GTK_CLIST(packet_list), cf->current_row, -1, 0.0, 0.0);
834 if (cf->current_frame_is_selected) {
835 /* It was selected, so re-select it. */
836 gtk_clist_select_row(GTK_CLIST(packet_list), cf->current_row, -1);
838 finfo_selected = NULL;
840 /* The current frame didn't pass the filter; make the first frame
841 the current frame, and leave it unselected. */
843 cf->current_frame = cf->first_displayed;
846 /* Unfreeze the packet list. */
847 gtk_clist_thaw(GTK_CLIST(packet_list));
850 #define MAX_LINE_LENGTH 256
853 print_packets(capture_file *cf, print_args_t *print_args)
857 guint32 progbar_quantum;
858 guint32 progbar_nextstep;
860 proto_tree *protocol_tree;
861 gint *col_widths = NULL;
863 gboolean print_separator;
864 char line_buf[MAX_LINE_LENGTH+1]; /* static-sized buffer! */
868 cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
869 if (cf->print_fh == NULL)
870 return FALSE; /* attempt to open destination failed */
872 print_preamble(cf->print_fh, print_args->format);
874 if (print_args->print_summary) {
875 /* We're printing packet summaries.
877 Find the widths for each of the columns - maximum of the
878 width of the title and the width of the data - and print
879 the column titles. */
880 col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
882 for (i = 0; i < cf->cinfo.num_cols; i++) {
883 /* Don't pad the last column. */
884 if (i == cf->cinfo.num_cols - 1)
887 col_widths[i] = strlen(cf->cinfo.col_title[i]);
888 data_width = get_column_char_width(get_column_format(i));
889 if (data_width > col_widths[i])
890 col_widths[i] = data_width;
893 /* Right-justify the packet number column. */
894 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
895 sprintf_len = sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_title[i]);
897 sprintf_len = sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
899 if (i == cf->cinfo.num_cols - 1)
905 print_line(cf->print_fh, print_args->format, line_buf);
908 print_separator = FALSE;
909 proto_tree_is_visible = TRUE;
911 /* Update the progress bar when it gets to this value. */
912 progbar_nextstep = 0;
913 /* When we reach the value that triggers a progress bar update,
914 bump that value by this amount. */
915 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
916 /* Count of packets at which we've looked. */
919 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
921 /* Iterate through the list of packets, printing the packets that
922 were selected by the current display filter. */
923 for (fd = cf->plist; fd != NULL; fd = fd->next) {
924 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
925 when we update it, we have to run the GTK+ main loop to get it
926 to repaint what's pending, and doing so may involve an "ioctl()"
927 to see if there's any pending input from an X server, and doing
928 that for every packet can be costly, especially on a big file. */
929 if (count >= progbar_nextstep) {
930 /* let's not divide by zero. I should never be started
931 * with count == 0, so let's assert that
933 g_assert(cf->count > 0);
935 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
936 (gfloat) count / cf->count);
937 progbar_nextstep += progbar_quantum;
938 while (gtk_events_pending())
939 gtk_main_iteration();
943 if (fd->passed_dfilter) {
944 wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
945 if (print_args->print_summary) {
946 /* Fill in the column information, but don't bother creating
947 the logical protocol tree. */
948 fd->cinfo = &cf->cinfo;
949 for (i = 0; i < fd->cinfo->num_cols; i++) {
950 fd->cinfo->col_data[i][0] = '\0';
952 dissect_packet(cf->pd, fd, NULL);
955 for (i = 0; i < cf->cinfo.num_cols; i++) {
956 /* Right-justify the packet number column. */
957 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
958 sprintf_len = sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_data[i]);
960 sprintf_len = sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
962 if (i == cf->cinfo.num_cols - 1)
968 print_line(cf->print_fh, print_args->format, line_buf);
971 print_line(cf->print_fh, print_args->format, "\n");
973 /* Create the logical protocol tree. */
974 protocol_tree = proto_tree_create_root();
975 dissect_packet(cf->pd, fd, protocol_tree);
977 /* Print the information in that tree. */
978 proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
979 cf->pd, fd, cf->print_fh);
981 proto_tree_free(protocol_tree);
983 if (print_args->print_hex) {
984 /* Print the full packet data as hex. */
985 print_hex_data(cf->print_fh, print_args->format, cf->pd,
986 fd->cap_len, fd->encoding);
989 /* Print a blank line if we print anything after this. */
990 print_separator = TRUE;
995 if (col_widths != NULL)
998 print_finale(cf->print_fh, print_args->format);
1000 close_print_dest(print_args->to_file, cf->print_fh);
1002 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1004 cf->print_fh = NULL;
1008 /* Scan through the packet list and change all columns that use the
1009 "command-line-specified" time stamp format to use the current
1010 value of that format. */
1012 change_time_formats(capture_file *cf)
1018 /* Freeze the packet list while we redo it, so we don't get any
1019 screen updates while it happens. */
1022 /* Iterate through the list of packets, checking whether the packet
1023 is in a row of the summary list and, if so, whether there are
1024 any columns that show the time in the "command-line-specified"
1025 format and, if so, update that row. */
1026 for (fd = cf->plist; fd != NULL; fd = fd->next) {
1027 if (fd->row != -1) {
1028 /* This packet is in the summary list, on row "fd->row". */
1030 /* XXX - there really should be a way of checking "cf->cinfo" for this;
1031 the answer isn't going to change from packet to packet, so we should
1032 simply skip all the "change_time_formats()" work if we're not
1033 changing anything. */
1034 fd->cinfo = &cf->cinfo;
1035 if (check_col(fd, COL_CLS_TIME)) {
1036 /* There are columns that show the time in the "command-line-specified"
1037 format; update them. */
1038 for (i = 0; i < cf->cinfo.num_cols; i++) {
1039 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1040 /* This is one of the columns that shows the time in
1041 "command-line-specified" format; update it. */
1042 cf->cinfo.col_data[i][0] = '\0';
1043 col_set_cls_time(fd, i);
1044 gtk_clist_set_text(GTK_CLIST(packet_list), fd->row, i,
1045 cf->cinfo.col_data[i]);
1052 /* Set the column widths of those columns that show the time in
1053 "command-line-specified" format. */
1054 pl_style = gtk_widget_get_style(packet_list);
1055 for (i = 0; i < cf->cinfo.num_cols; i++) {
1056 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1057 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1058 gdk_string_width(pl_style->font, get_column_longest_string(COL_CLS_TIME)));
1062 /* Unfreeze the packet list. */
1067 clear_tree_and_hex_views(void)
1069 /* Clear the hex dump. */
1070 gtk_text_freeze(GTK_TEXT(byte_view));
1071 gtk_text_set_point(GTK_TEXT(byte_view), 0);
1072 gtk_text_forward_delete(GTK_TEXT(byte_view),
1073 gtk_text_get_length(GTK_TEXT(byte_view)));
1074 gtk_text_thaw(GTK_TEXT(byte_view));
1076 /* Remove all nodes in ctree. This is how it's done in testgtk.c in GTK+ */
1077 gtk_clist_clear ( GTK_CLIST(tree_view) );
1082 find_packet(capture_file *cf, dfilter *sfcode)
1084 frame_data *start_fd;
1086 frame_data *new_fd = NULL;
1087 guint32 progbar_quantum;
1088 guint32 progbar_nextstep;
1090 proto_tree *protocol_tree;
1092 start_fd = cf->current_frame;
1093 if (start_fd != NULL) {
1094 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
1096 /* Iterate through the list of packets, starting at the packet we've
1097 picked, calling a routine to run the filter on the packet, see if
1098 it matches, and stop if so. */
1102 proto_tree_is_visible = FALSE;
1104 /* Update the progress bar when it gets to this value. */
1105 progbar_nextstep = 0;
1106 /* When we reach the value that triggers a progress bar update,
1107 bump that value by this amount. */
1108 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1109 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
1113 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1114 when we update it, we have to run the GTK+ main loop to get it
1115 to repaint what's pending, and doing so may involve an "ioctl()"
1116 to see if there's any pending input from an X server, and doing
1117 that for every packet can be costly, especially on a big file. */
1118 if (count >= progbar_nextstep) {
1119 /* let's not divide by zero. I should never be started
1120 * with count == 0, so let's assert that
1122 g_assert(cf->count > 0);
1124 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1125 (gfloat) count / cf->count);
1127 progbar_nextstep += progbar_quantum;
1128 while (gtk_events_pending())
1129 gtk_main_iteration();
1132 /* Go past the current frame. */
1133 if (cf->sbackward) {
1134 /* Go on to the previous frame. */
1137 fd = cf->plist_end; /* wrap around */
1139 /* Go on to the next frame. */
1142 fd = cf->plist; /* wrap around */
1145 if (fd == start_fd) {
1146 /* We're back to the frame we were on originally. The search
1153 /* Is this packet in the display? */
1154 if (fd->passed_dfilter) {
1155 /* Yes. Does it match the search filter? */
1156 protocol_tree = proto_tree_create_root();
1157 wtap_seek_read(cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1158 dissect_packet(cf->pd, fd, protocol_tree);
1159 if (dfilter_apply(sfcode, protocol_tree, cf->pd)) {
1161 break; /* found it! */
1166 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1169 if (new_fd != NULL) {
1170 /* We found a frame. Make it visible, and select it. */
1171 if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), new_fd->row))
1172 gtk_clist_moveto(GTK_CLIST(packet_list), new_fd->row, -1, 0.0, 0.0);
1174 /* XXX - why is there no "gtk_clist_set_focus_row()", so that we
1175 can make the row for the frame we found the focus row?
1179 http://www.gnome.org/mailing-lists/archives/gtk-list/2000-January/0038.shtml
1182 GTK_CLIST(packet_list)->focus_row = new_fd->row;
1183 gtk_clist_select_row(GTK_CLIST(packet_list), new_fd->row, -1);
1184 return TRUE; /* success */
1186 return FALSE; /* failure */
1190 goto_frame(capture_file *cf, guint fnumber)
1194 for (fd = cf->plist; fd != NULL && fd->num < fnumber; fd = fd->next)
1198 return NO_SUCH_FRAME; /* we didn't find that frame */
1199 if (!fd->passed_dfilter)
1200 return FRAME_NOT_DISPLAYED; /* the frame with that number isn't displayed */
1202 /* We found that frame, and it's currently being displayed.
1203 Make it visible, and select it. */
1204 if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), fd->row))
1205 gtk_clist_moveto(GTK_CLIST(packet_list), fd->row, -1, 0.0, 0.0);
1207 /* See above complaint about the lack of "gtk_clist_set_focus_row()". */
1208 GTK_CLIST(packet_list)->focus_row = fd->row;
1209 gtk_clist_select_row(GTK_CLIST(packet_list), fd->row, -1);
1213 /* Select the packet on a given row. */
1215 select_packet(capture_file *cf, int row)
1220 /* Search through the list of frames to see which one is in
1222 for (fd = cf->plist, i = 0; fd != NULL; fd = fd->next, i++) {
1227 g_assert(fd != NULL);
1229 /* Record that this frame is the current frame, and that it's selected. */
1230 cf->current_frame = fd;
1231 cf->current_frame_is_selected = TRUE;
1233 /* Get the data in that frame. */
1234 wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1236 /* Create the logical protocol tree. */
1237 if (cf->protocol_tree)
1238 proto_tree_free(cf->protocol_tree);
1239 cf->protocol_tree = proto_tree_create_root();
1240 proto_tree_is_visible = TRUE;
1241 dissect_packet(cf->pd, cf->current_frame, cf->protocol_tree);
1243 /* Display the GUI protocol tree and hex dump. */
1244 clear_tree_and_hex_views();
1245 proto_tree_draw(cf->protocol_tree, tree_view);
1246 packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->current_frame->cap_len,
1247 -1, -1, cf->current_frame->encoding);
1249 /* A packet is selected. */
1250 set_menus_for_selected_packet(TRUE);
1253 /* Unselect the selected packet, if any. */
1255 unselect_packet(capture_file *cf)
1257 cf->current_frame_is_selected = FALSE;
1259 /* Destroy the protocol tree for that packet. */
1260 if (cf->protocol_tree != NULL) {
1261 proto_tree_free(cf->protocol_tree);
1262 cf->protocol_tree = NULL;
1265 finfo_selected = NULL;
1267 /* Clear out the display of that packet. */
1268 clear_tree_and_hex_views();
1270 /* No packet is selected. */
1271 set_menus_for_selected_packet(FALSE);
1275 freeze_clist(capture_file *cf)
1279 /* Make the column sizes static, so they don't adjust while
1280 we're reading the capture file (freezing the clist doesn't
1281 seem to suffice). */
1282 for (i = 0; i < cf->cinfo.num_cols; i++)
1283 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1284 gtk_clist_freeze(GTK_CLIST(packet_list));
1288 thaw_clist(capture_file *cf)
1292 for (i = 0; i < cf->cinfo.num_cols; i++) {
1293 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1294 /* Set this column's width to the appropriate value. */
1295 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1296 cf->cinfo.col_width[i]);
1298 /* Make this column's size dynamic, so that it adjusts to the
1299 appropriate size. */
1300 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1303 gtk_clist_thaw(GTK_CLIST(packet_list));
1305 /* Hopefully, the columns have now gotten their appropriate sizes;
1306 make them resizeable - a column that auto-resizes cannot be
1307 resized by the user, and *vice versa*. */
1308 for (i = 0; i < cf->cinfo.num_cols; i++)
1309 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1313 save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
1316 gchar *from_filename;
1317 gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
1321 int from_fd, to_fd, nread, nwritten;
1324 struct wtap_pkthdr hdr;
1327 if ((name_ptr = (gchar *) strrchr(fname, PATH_SEPARATOR)) == NULL)
1331 msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
1332 save_msg = g_malloc(msg_len);
1333 snprintf(save_msg, msg_len, save_fmt, name_ptr);
1334 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
1337 if (!save_filtered && save_format == cf->cd_t) {
1338 /* We're not filtering packets, and we're saving it in the format
1339 it's already in, so we can just move or copy the raw data. */
1341 /* In this branch, we set "err" only if we get an error, so we
1342 must first clear it. */
1344 if (cf->is_tempfile) {
1345 /* The file being saved is a temporary file from a live
1346 capture, so it doesn't need to stay around under that name;
1347 first, try renaming the capture buffer file to the new name. */
1348 if (rename(cf->filename, fname) == 0) {
1349 /* That succeeded - there's no need to copy the source file. */
1350 from_filename = NULL;
1353 if (errno == EXDEV) {
1354 /* They're on different file systems, so we have to copy the
1357 from_filename = cf->filename;
1359 /* The rename failed, but not because they're on different
1360 file systems - put up an error message. (Or should we
1361 just punt and try to copy? The only reason why I'd
1362 expect the rename to fail and the copy to succeed would
1363 be if we didn't have permission to remove the file from
1364 the temporary directory, and that might be fixable - but
1365 is it worth requiring the user to go off and fix it?) */
1367 simple_dialog(ESD_TYPE_WARN, NULL,
1368 file_rename_error_message(err), fname);
1373 /* It's a permanent file, so we should copy it, and not remove the
1376 from_filename = cf->filename;
1379 /* Copy the file, if we haven't moved it. */
1381 /* Copy the raw bytes of the file. */
1382 from_fd = open(from_filename, O_RDONLY);
1385 simple_dialog(ESD_TYPE_WARN, NULL,
1386 file_open_error_message(err, TRUE), from_filename);
1390 to_fd = creat(fname, 0644);
1393 simple_dialog(ESD_TYPE_WARN, NULL,
1394 file_open_error_message(err, TRUE), fname);
1399 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
1400 nwritten = write(to_fd, pd, nread);
1401 if (nwritten < nread) {
1405 err = WTAP_ERR_SHORT_WRITE;
1406 simple_dialog(ESD_TYPE_WARN, NULL,
1407 file_write_error_message(err), fname);
1415 simple_dialog(ESD_TYPE_WARN, NULL,
1416 file_read_error_message(err), from_filename);
1422 if (close(to_fd) < 0) {
1424 simple_dialog(ESD_TYPE_WARN, NULL,
1425 file_close_error_message(err), fname);
1430 /* Either we're filtering packets, or we're saving in a different
1431 format; we can't do that by copying or moving the capture file,
1432 we have to do it by writing the packets out in Wiretap. */
1433 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
1435 simple_dialog(ESD_TYPE_WARN, NULL,
1436 file_open_error_message(err, TRUE), fname);
1440 /* XXX - have a way to save only the packets currently selected by
1443 If we do that, should we make that file the current file? If so,
1444 it means we can no longer get at the other packets. What does
1446 for (fd = cf->plist; fd != NULL; fd = fd->next) {
1447 /* XXX - do a progress bar */
1448 if (!save_filtered || fd->passed_dfilter) {
1449 /* Either we're saving all frames, or we're saving filtered frames
1450 and this one passed the display filter - save it. */
1451 hdr.ts.tv_sec = fd->abs_secs;
1452 hdr.ts.tv_usec = fd->abs_usecs;
1453 hdr.caplen = fd->cap_len;
1454 hdr.len = fd->pkt_len;
1455 hdr.pkt_encap = fd->lnk_t;
1456 hdr.pseudo_header = fd->pseudo_header;
1457 wtap_seek_read(cf->cd_t, cf->fh, fd->file_off, pd, fd->cap_len);
1459 if (!wtap_dump(pdh, &hdr, pd, &err)) {
1460 simple_dialog(ESD_TYPE_WARN, NULL,
1461 file_write_error_message(err), fname);
1462 wtap_dump_close(pdh, &err);
1468 if (!wtap_dump_close(pdh, &err)) {
1469 simple_dialog(ESD_TYPE_WARN, NULL,
1470 file_close_error_message(err), fname);
1477 /* Pop the "Saving:" message off the status bar. */
1478 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
1480 if (!save_filtered) {
1481 /* We saved the entire capture, not just some packets from it.
1482 Open and read the file we saved it to.
1484 XXX - this is somewhat of a waste; we already have the
1485 packets, all this gets us is updated file type information
1486 (which we could just stuff into "cf"), and having the new
1487 file be the one we have opened and from which we're reading
1488 the data, and it means we have to spend time opening and
1489 reading the file, which could be a significant amount of
1490 time if the file is large. */
1491 cf->user_saved = TRUE;
1493 if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
1494 /* XXX - report errors if this fails? */
1495 err = read_cap_file(cf);
1496 set_menus_for_unsaved_capture_file(FALSE);
1504 file_open_error_message(int err, int for_writing)
1507 static char errmsg_errno[1024+1];
1511 case WTAP_ERR_NOT_REGULAR_FILE:
1512 errmsg = "The file \"%s\" is invalid.";
1515 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1516 case WTAP_ERR_UNSUPPORTED:
1517 /* Seen only when opening a capture file for reading. */
1518 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1521 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1522 /* Seen only when opening a capture file for writing. */
1523 errmsg = "Ethereal does not support writing capture files in that format.";
1526 case WTAP_ERR_UNSUPPORTED_ENCAP:
1527 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1528 /* Seen only when opening a capture file for writing. */
1529 errmsg = "Ethereal cannot save this capture in that format.";
1532 case WTAP_ERR_BAD_RECORD:
1533 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1536 case WTAP_ERR_CANT_OPEN:
1538 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1540 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1543 case WTAP_ERR_SHORT_READ:
1544 errmsg = "The file \"%s\" appears to have been cut short"
1545 " in the middle of a packet.";
1548 case WTAP_ERR_SHORT_WRITE:
1549 errmsg = "A full header couldn't be written to the file \"%s\".";
1554 errmsg = "The path to the file \"%s\" does not exist.";
1556 errmsg = "The file \"%s\" does not exist.";
1561 errmsg = "You do not have permission to create or write to the file \"%s\".";
1563 errmsg = "You do not have permission to read the file \"%s\".";
1567 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
1568 wtap_strerror(err));
1569 errmsg = errmsg_errno;
1576 file_rename_error_message(int err)
1579 static char errmsg_errno[1024+1];
1584 errmsg = "The path to the file \"%s\" does not exist.";
1588 errmsg = "You do not have permission to move the capture file to \"%s\".";
1592 sprintf(errmsg_errno, "The file \"%%s\" could not be moved: %s.",
1593 wtap_strerror(err));
1594 errmsg = errmsg_errno;
1601 file_read_error_message(int err)
1603 static char errmsg_errno[1024+1];
1605 sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.",
1606 wtap_strerror(err));
1607 return errmsg_errno;
1611 file_write_error_message(int err)
1614 static char errmsg_errno[1024+1];
1619 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1624 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1629 sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.",
1630 wtap_strerror(err));
1631 errmsg = errmsg_errno;
1637 /* Check for write errors - if the file is being written to an NFS server,
1638 a write error may not show up until the file is closed, as NFS clients
1639 might not send writes to the server until the "write()" call finishes,
1640 so that the write may fail on the server but the "write()" may succeed. */
1642 file_close_error_message(int err)
1645 static char errmsg_errno[1024+1];
1649 case WTAP_ERR_CANT_CLOSE:
1650 errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
1653 case WTAP_ERR_SHORT_WRITE:
1654 errmsg = "Not all the data could be written to the file \"%s\".";
1658 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1663 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1668 sprintf(errmsg_errno, "An error occurred while closing the file \"%%s\": %s.",
1669 wtap_strerror(err));
1670 errmsg = errmsg_errno;