4 * $Id: file.c,v 1.157 2000/01/25 00:36:35 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 */
213 /* Clear the packet list. */
214 gtk_clist_freeze(GTK_CLIST(packet_list));
215 gtk_clist_clear(GTK_CLIST(packet_list));
216 gtk_clist_thaw(GTK_CLIST(packet_list));
218 /* Clear any file-related status bar messages.
219 XXX - should be "clear *ALL* file-related status bar messages;
220 will there ever be more than one on the stack? */
221 gtk_statusbar_pop(GTK_STATUSBAR(w), file_ctx);
223 /* Restore the standard title bar message. */
224 set_main_window_name("The Ethereal Network Analyzer");
226 /* Disable all menu items that make sense only if you have a capture. */
227 set_menus_for_capture_file(FALSE);
228 set_menus_for_unsaved_capture_file(FALSE);
229 set_menus_for_captured_packets(FALSE);
230 set_menus_for_selected_packet(FALSE);
233 /* Set the file name in the status line, in the name for the main window,
234 and in the name for the main window's icon. */
236 set_display_filename(capture_file *cf)
240 gchar *done_fmt = " File: %s Drops: %u";
242 gchar *win_name_fmt = "%s - Ethereal";
245 if (!cf->is_tempfile) {
246 /* Get the last component of the file name, and put that in the
248 if ((name_ptr = (gchar *) strrchr(cf->filename, PATH_SEPARATOR)) == NULL)
249 name_ptr = cf->filename;
253 /* The file we read is a temporary file from a live capture;
254 we don't mention its name in the status bar. */
255 name_ptr = "<capture>";
258 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
259 done_msg = g_malloc(msg_len);
260 snprintf(done_msg, msg_len, done_fmt, name_ptr, cf->drops);
261 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
264 msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
265 win_name = g_malloc(msg_len);
266 snprintf(win_name, msg_len, win_name_fmt, name_ptr);
267 set_main_window_name(win_name);
272 read_cap_file(capture_file *cf)
274 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
279 char errmsg_errno[1024+1];
280 gchar err_str[2048+1];
282 if ((name_ptr = (gchar *) strrchr(cf->filename, PATH_SEPARATOR)) == NULL)
283 name_ptr = cf->filename;
287 msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
288 load_msg = g_malloc(msg_len);
289 snprintf(load_msg, msg_len, load_fmt, name_ptr);
290 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
293 cf->update_progbar = TRUE;
294 /* Update the progress bar when it gets to this value. */
295 cf->progbar_nextstep = 0;
296 /* When we reach the value that triggers a progress bar update,
297 bump that value by this amount. */
298 cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
301 proto_tree_is_visible = FALSE;
302 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
303 /* Set the file encapsulation type now; we don't know what it is until
304 we've looked at all the packets, as we don't know until then whether
305 there's more than one type (and thus whether it's
306 WTAP_ENCAP_PER_PACKET). */
307 cf->lnk_t = wtap_file_encap(cf->wth);
310 cf->filed = open(cf->filename, O_RDONLY);
311 cf->fh = filed_open(cf->filed, "rb");
312 cf->current_frame = cf->first_displayed;
315 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
316 gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
318 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
319 set_display_filename(cf);
321 /* Enable menu items that make sense if you have a capture file you've
323 set_menus_for_capture_file(TRUE);
324 set_menus_for_unsaved_capture_file(!cf->user_saved);
326 /* Enable menu items that make sense if you have some captured packets. */
327 set_menus_for_captured_packets(TRUE);
329 /* If we have any packets to select, select the first packet by making
330 the first row the selected row. */
331 if (cf->plist != NULL)
332 gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
335 /* Put up a message box noting that the read failed somewhere along
336 the line. Don't throw out the stuff we managed to read, though,
340 case WTAP_ERR_CANT_READ:
341 errmsg = "An attempt to read from the file failed for"
342 " some unknown reason.";
345 case WTAP_ERR_SHORT_READ:
346 errmsg = "The capture file appears to have been cut short"
347 " in the middle of a packet.";
350 case WTAP_ERR_BAD_RECORD:
351 errmsg = "The capture file appears to be damaged or corrupt.";
355 sprintf(errmsg_errno, "An error occurred while reading the"
356 " capture file: %s.", wtap_strerror(err));
357 errmsg = errmsg_errno;
360 snprintf(err_str, sizeof err_str, errmsg);
361 simple_dialog(ESD_TYPE_WARN, NULL, err_str);
369 start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
374 err = open_cap_file(fname, is_tempfile, cf);
376 /* Disable menu items that make no sense if you're currently running
378 set_menus_for_capture_in_progress(TRUE);
380 /* Enable menu items that make sense if you have some captured
381 packets (yes, I know, we don't have any *yet*). */
382 set_menus_for_captured_packets(TRUE);
384 for (i = 0; i < cf->cinfo.num_cols; i++) {
385 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
386 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
388 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
389 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
390 cf->cinfo.col_width[i]);
391 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
395 /* Yes, "open_cap_file()" set this - but it set it to a file handle
396 from Wiretap, which will be closed when we close the file; we
397 want it to remain open even after that, so that we can read
398 packet data from it. */
399 cf->fh = file_open(fname, "rb");
401 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
402 " <live capture in progress>");
408 continue_tail_cap_file(capture_file *cf, int to_read)
412 gtk_clist_freeze(GTK_CLIST(packet_list));
414 wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf, &err);
416 gtk_clist_thaw(GTK_CLIST(packet_list));
417 if (auto_scroll_live && cf->plist_end != NULL)
418 gtk_clist_moveto(GTK_CLIST(packet_list),
419 cf->plist_end->row, -1, 1.0, 1.0);
424 finish_tail_cap_file(capture_file *cf)
428 gtk_clist_freeze(GTK_CLIST(packet_list));
430 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
433 if (auto_scroll_live && cf->plist_end != NULL)
434 gtk_clist_moveto(GTK_CLIST(packet_list),
435 cf->plist_end->row, -1, 1.0, 1.0);
437 /* Set the file encapsulation type now; we don't know what it is until
438 we've looked at all the packets, as we don't know until then whether
439 there's more than one type (and thus whether it's
440 WTAP_ENCAP_PER_PACKET). */
441 cf->lnk_t = wtap_file_encap(cf->wth);
443 /* There's nothing more to read from the capture file - close it. */
447 /* Pop the "<live capture in progress>" message off the status bar. */
448 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
450 set_display_filename(cf);
452 /* Enable menu items that make sense if you're not currently running
454 set_menus_for_capture_in_progress(FALSE);
456 /* Enable menu items that make sense if you have a capture file
457 you've finished reading. */
458 set_menus_for_capture_file(TRUE);
459 set_menus_for_unsaved_capture_file(!cf->user_saved);
463 #endif /* HAVE_LIBPCAP */
466 color_filter_t *colorf;
467 proto_tree *protocol_tree;
469 } apply_color_filter_args;
472 * If no color filter has been applied, apply this one.
473 * (The "if no color filter has been applied" is to handle the case where
474 * more than one color filter matches the packet.)
477 apply_color_filter(gpointer filter_arg, gpointer argp)
479 color_filter_t *colorf = filter_arg;
480 apply_color_filter_args *args = argp;
482 if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
483 if (dfilter_apply(colorf->c_colorfilter, args->protocol_tree, args->pd))
484 args->colorf = colorf;
489 add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf)
491 apply_color_filter_args args;
493 proto_tree *protocol_tree = NULL;
495 /* We don't yet have a color filter to apply. */
498 /* If we don't have the time stamp of the first packet in the
499 capture, it's because this is the first packet. Save the time
500 stamp of this packet as the time stamp of the first packet. */
501 if (!firstsec && !firstusec) {
502 firstsec = fdata->abs_secs;
503 firstusec = fdata->abs_usecs;
506 /* Get the time elapsed between the first packet and this packet. */
507 cf->esec = fdata->abs_secs - firstsec;
508 if (firstusec <= fdata->abs_usecs) {
509 cf->eusec = fdata->abs_usecs - firstusec;
511 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
515 fdata->cinfo = &cf->cinfo;
516 for (i = 0; i < fdata->cinfo->num_cols; i++) {
517 fdata->cinfo->col_data[i][0] = '\0';
520 /* Apply the filters */
521 if (cf->dfcode != NULL || filter_list != NULL) {
522 protocol_tree = proto_tree_create_root();
523 dissect_packet(buf, fdata, protocol_tree);
524 if (cf->dfcode != NULL)
525 fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
527 fdata->passed_dfilter = TRUE;
529 /* Apply color filters, if we have any. */
530 if (filter_list != NULL) {
531 args.protocol_tree = protocol_tree;
533 g_slist_foreach(filter_list, apply_color_filter, &args);
535 proto_tree_free(protocol_tree);
540 protocol_tree = proto_tree_create_root();
542 dissect_packet(buf, fdata, protocol_tree);
543 fdata->passed_dfilter = TRUE;
546 proto_tree_free(protocol_tree);
550 if (fdata->passed_dfilter) {
551 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
552 the first entry is added to it by "real_insert_row()", that row
553 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
554 our version and the vanilla GTK+ version).
556 This means that a "select-row" signal is emitted; this causes
557 "packet_list_select_cb()" to be called, which causes "select_packet()"
560 "select_packet()" searches the list of frames for a frame with the
561 row number passed into it; however, as "gtk_clist_append()", which
562 called "real_insert_row()", hasn't yet returned, we don't know what
563 the row number is, so we can't correctly set "fd->row" for that frame
566 This means that we won't find the frame for that row.
568 We can't assume that there's only one frame in the frame list,
569 either, as we may be filtering the display.
571 Therefore, we set "fdata->row" to 0, under the assumption that
572 the row number passed to "select_packet()" will be 0 (as we're
573 adding the first row to the list; it gets set to the proper
577 /* If we don't have the time stamp of the previous displayed packet,
578 it's because this is the first displayed packet. Save the time
579 stamp of this packet as the time stamp of the previous displayed
581 if (!prevsec && !prevusec) {
582 prevsec = fdata->abs_secs;
583 prevusec = fdata->abs_usecs;
586 /* Get the time elapsed between the first packet and this packet. */
587 fdata->rel_secs = cf->esec;
588 fdata->rel_usecs = cf->eusec;
590 /* Get the time elapsed between the previous displayed packet and
592 fdata->del_secs = fdata->abs_secs - prevsec;
593 if (prevusec <= fdata->abs_usecs) {
594 fdata->del_usecs = fdata->abs_usecs - prevusec;
596 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
599 prevsec = fdata->abs_secs;
600 prevusec = fdata->abs_usecs;
602 fill_in_columns(fdata);
604 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
607 if (filter_list != NULL && (args.colorf != NULL)) {
608 gtk_clist_set_background(GTK_CLIST(packet_list), row,
609 &args.colorf->bg_color);
610 gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
611 &args.colorf->fg_color);
613 gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
614 gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
617 /* If we haven't yet seen the first frame, this is it. */
618 if (cf->first_displayed == NULL)
619 cf->first_displayed = fdata;
621 /* This is the last frame we've seen so far. */
622 cf->last_displayed = fdata;
624 /* If this was the current frame, remember the row it's in, so
625 we can arrange that it's on the screen when we're done. */
626 if (cf->current_frame == fdata)
627 cf->current_row = row;
629 fdata->row = -1; /* not in the display */
634 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
637 capture_file *cf = (capture_file *) user;
639 proto_tree *protocol_tree;
640 frame_data *plist_end;
644 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
645 when we update it, we have to run the GTK+ main loop to get it
646 to repaint what's pending, and doing so may involve an "ioctl()"
647 to see if there's any pending input from an X server, and doing
648 that for every packet can be costly, especially on a big file.
650 Do so only if we were told to do so; when reading a capture file
651 being updated by a live capture, we don't do so (as we're not
652 "done" until the capture stops, so we don't know how close to
655 if (cf->update_progbar && offset >= cf->progbar_nextstep) {
656 file_pos = lseek(cf->filed, 0, SEEK_CUR);
657 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
658 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), prog_val);
659 cf->progbar_nextstep += cf->progbar_quantum;
660 while (gtk_events_pending())
661 gtk_main_iteration();
664 /* Allocate the next list entry, and add it to the list. */
665 fdata = (frame_data *) g_malloc(sizeof(frame_data));
669 fdata->pkt_len = phdr->len;
670 fdata->cap_len = phdr->caplen;
671 fdata->file_off = offset;
672 fdata->lnk_t = phdr->pkt_encap;
673 fdata->abs_secs = phdr->ts.tv_sec;
674 fdata->abs_usecs = phdr->ts.tv_usec;
675 fdata->encoding = CHAR_ASCII;
676 fdata->pseudo_header = phdr->pseudo_header;
681 protocol_tree = proto_tree_create_root();
682 dissect_packet(buf, fdata, protocol_tree);
683 passed = dfilter_apply(cf->rfcode, protocol_tree, cf->pd);
684 proto_tree_free(protocol_tree);
687 plist_end = cf->plist_end;
688 fdata->prev = plist_end;
689 if (plist_end != NULL)
690 plist_end->next = fdata;
693 cf->plist_end = fdata;
696 fdata->num = cf->count;
697 add_packet_to_packet_list(fdata, cf, buf);
703 filter_packets(capture_file *cf, gchar *dftext)
707 if (dftext == NULL) {
708 /* The new filter is an empty filter (i.e., display all packets). */
712 * We have a filter; try to compile it.
714 if (dfilter_compile(dftext, &dfcode) != 0) {
715 /* The attempt failed; report an error. */
716 simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
721 if (dfcode == NULL) {
722 /* Yes - free the filter text, and set it to null. */
728 /* We have a valid filter. Replace the current filter. */
729 if (cf->dfilter != NULL)
731 cf->dfilter = dftext;
732 if (cf->dfcode != NULL)
733 dfilter_destroy(cf->dfcode);
736 /* Now go through the list of packets we've read from the capture file,
737 applying the current display filter, and, if the packet passes the
738 display filter, add it to the summary display, appropriately
739 colored. (That's how we colorize the display - it's like filtering
740 the display, only we don't install a new filter.) */
741 colorize_packets(cf);
746 colorize_packets(capture_file *cf)
749 guint32 progbar_quantum;
750 guint32 progbar_nextstep;
753 /* We need to re-initialize all the state information that protocols
754 keep, because we're making a fresh pass through all the packets. */
756 /* Initialize the table of conversations. */
759 /* Initialize protocol-specific variables */
760 init_all_protocols();
762 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
764 /* Freeze the packet list while we redo it, so we don't get any
765 screen updates while it happens. */
766 gtk_clist_freeze(GTK_CLIST(packet_list));
769 gtk_clist_clear(GTK_CLIST(packet_list));
771 /* We don't yet know which will be the first and last frames displayed. */
772 cf->first_displayed = NULL;
773 cf->last_displayed = NULL;
775 /* If a packet was selected, we don't know yet what row, if any, it'll
777 cf->current_row = -1;
779 /* Iterate through the list of packets, calling a routine
780 to run the filter on the packet, see if it matches, and
781 put it in the display list if so. */
787 proto_tree_is_visible = FALSE;
789 /* Update the progress bar when it gets to this value. */
790 progbar_nextstep = 0;
791 /* When we reach the value that triggers a progress bar update,
792 bump that value by this amount. */
793 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
794 /* Count of packets at which we've looked. */
797 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
799 for (fd = cf->plist; fd != NULL; fd = fd->next) {
800 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
801 when we update it, we have to run the GTK+ main loop to get it
802 to repaint what's pending, and doing so may involve an "ioctl()"
803 to see if there's any pending input from an X server, and doing
804 that for every packet can be costly, especially on a big file. */
805 if (count >= progbar_nextstep) {
806 /* let's not divide by zero. I should never be started
807 * with count == 0, so let's assert that
809 g_assert(cf->count > 0);
811 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
812 (gfloat) count / cf->count);
814 progbar_nextstep += progbar_quantum;
815 while (gtk_events_pending())
816 gtk_main_iteration();
821 wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
823 add_packet_to_packet_list(fd, cf, cf->pd);
826 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
828 if (cf->current_row != -1) {
829 /* The current frame passed the filter; make sure it's visible. */
830 if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), cf->current_row))
831 gtk_clist_moveto(GTK_CLIST(packet_list), cf->current_row, -1, 0.0, 0.0);
832 if (cf->current_frame_is_selected) {
833 /* It was selected, so re-select it. */
834 gtk_clist_select_row(GTK_CLIST(packet_list), cf->current_row, -1);
836 finfo_selected = NULL;
838 /* The current frame didn't pass the filter; make the first frame
839 the current frame, and leave it unselected. */
841 cf->current_frame = cf->first_displayed;
844 /* Unfreeze the packet list. */
845 gtk_clist_thaw(GTK_CLIST(packet_list));
848 #define MAX_LINE_LENGTH 256
851 print_packets(capture_file *cf, print_args_t *print_args)
855 guint32 progbar_quantum;
856 guint32 progbar_nextstep;
858 proto_tree *protocol_tree;
859 gint *col_widths = NULL;
861 gboolean print_separator;
862 char line_buf[MAX_LINE_LENGTH+1]; /* static-sized buffer! */
866 cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
867 if (cf->print_fh == NULL)
868 return FALSE; /* attempt to open destination failed */
870 print_preamble(cf->print_fh, print_args->format);
872 if (print_args->print_summary) {
873 /* We're printing packet summaries.
875 Find the widths for each of the columns - maximum of the
876 width of the title and the width of the data - and print
877 the column titles. */
878 col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
880 for (i = 0; i < cf->cinfo.num_cols; i++) {
881 /* Don't pad the last column. */
882 if (i == cf->cinfo.num_cols - 1)
885 col_widths[i] = strlen(cf->cinfo.col_title[i]);
886 data_width = get_column_char_width(get_column_format(i));
887 if (data_width > col_widths[i])
888 col_widths[i] = data_width;
891 /* Right-justify the packet number column. */
892 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
893 sprintf_len = sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_title[i]);
895 sprintf_len = sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
897 if (i == cf->cinfo.num_cols - 1)
903 print_line(cf->print_fh, print_args->format, line_buf);
906 print_separator = FALSE;
907 proto_tree_is_visible = TRUE;
909 /* Update the progress bar when it gets to this value. */
910 progbar_nextstep = 0;
911 /* When we reach the value that triggers a progress bar update,
912 bump that value by this amount. */
913 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
914 /* Count of packets at which we've looked. */
917 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
919 /* Iterate through the list of packets, printing the packets that
920 were selected by the current display filter. */
921 for (fd = cf->plist; fd != NULL; fd = fd->next) {
922 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
923 when we update it, we have to run the GTK+ main loop to get it
924 to repaint what's pending, and doing so may involve an "ioctl()"
925 to see if there's any pending input from an X server, and doing
926 that for every packet can be costly, especially on a big file. */
927 if (count >= progbar_nextstep) {
928 /* let's not divide by zero. I should never be started
929 * with count == 0, so let's assert that
931 g_assert(cf->count > 0);
933 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
934 (gfloat) count / cf->count);
935 progbar_nextstep += progbar_quantum;
936 while (gtk_events_pending())
937 gtk_main_iteration();
941 if (fd->passed_dfilter) {
942 wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
943 if (print_args->print_summary) {
944 /* Fill in the column information, but don't bother creating
945 the logical protocol tree. */
946 fd->cinfo = &cf->cinfo;
947 for (i = 0; i < fd->cinfo->num_cols; i++) {
948 fd->cinfo->col_data[i][0] = '\0';
950 dissect_packet(cf->pd, fd, NULL);
953 for (i = 0; i < cf->cinfo.num_cols; i++) {
954 /* Right-justify the packet number column. */
955 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
956 sprintf_len = sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_data[i]);
958 sprintf_len = sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
960 if (i == cf->cinfo.num_cols - 1)
966 print_line(cf->print_fh, print_args->format, line_buf);
969 print_line(cf->print_fh, print_args->format, "\n");
971 /* Create the logical protocol tree. */
972 protocol_tree = proto_tree_create_root();
973 dissect_packet(cf->pd, fd, protocol_tree);
975 /* Print the information in that tree. */
976 proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
977 cf->pd, fd, cf->print_fh);
979 proto_tree_free(protocol_tree);
981 if (print_args->print_hex) {
982 /* Print the full packet data as hex. */
983 print_hex_data(cf->print_fh, print_args->format, cf->pd,
984 fd->cap_len, fd->encoding);
987 /* Print a blank line if we print anything after this. */
988 print_separator = TRUE;
993 if (col_widths != NULL)
996 print_finale(cf->print_fh, print_args->format);
998 close_print_dest(print_args->to_file, cf->print_fh);
1000 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1002 cf->print_fh = NULL;
1006 /* Scan through the packet list and change all columns that use the
1007 "command-line-specified" time stamp format to use the current
1008 value of that format. */
1010 change_time_formats(capture_file *cf)
1016 /* Freeze the packet list while we redo it, so we don't get any
1017 screen updates while it happens. */
1020 /* Iterate through the list of packets, checking whether the packet
1021 is in a row of the summary list and, if so, whether there are
1022 any columns that show the time in the "command-line-specified"
1023 format and, if so, update that row. */
1024 for (fd = cf->plist; fd != NULL; fd = fd->next) {
1025 if (fd->row != -1) {
1026 /* This packet is in the summary list, on row "fd->row". */
1028 /* XXX - there really should be a way of checking "cf->cinfo" for this;
1029 the answer isn't going to change from packet to packet, so we should
1030 simply skip all the "change_time_formats()" work if we're not
1031 changing anything. */
1032 fd->cinfo = &cf->cinfo;
1033 if (check_col(fd, COL_CLS_TIME)) {
1034 /* There are columns that show the time in the "command-line-specified"
1035 format; update them. */
1036 for (i = 0; i < cf->cinfo.num_cols; i++) {
1037 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1038 /* This is one of the columns that shows the time in
1039 "command-line-specified" format; update it. */
1040 cf->cinfo.col_data[i][0] = '\0';
1041 col_set_cls_time(fd, i);
1042 gtk_clist_set_text(GTK_CLIST(packet_list), fd->row, i,
1043 cf->cinfo.col_data[i]);
1050 /* Set the column widths of those columns that show the time in
1051 "command-line-specified" format. */
1052 pl_style = gtk_widget_get_style(packet_list);
1053 for (i = 0; i < cf->cinfo.num_cols; i++) {
1054 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1055 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1056 gdk_string_width(pl_style->font, get_column_longest_string(COL_CLS_TIME)));
1060 /* Unfreeze the packet list. */
1065 clear_tree_and_hex_views(void)
1067 /* Clear the hex dump. */
1068 gtk_text_freeze(GTK_TEXT(byte_view));
1069 gtk_text_set_point(GTK_TEXT(byte_view), 0);
1070 gtk_text_forward_delete(GTK_TEXT(byte_view),
1071 gtk_text_get_length(GTK_TEXT(byte_view)));
1072 gtk_text_thaw(GTK_TEXT(byte_view));
1074 /* Remove all nodes in ctree. This is how it's done in testgtk.c in GTK+ */
1075 gtk_clist_clear ( GTK_CLIST(tree_view) );
1080 find_packet(capture_file *cf, dfilter *sfcode)
1082 frame_data *start_fd;
1084 frame_data *new_fd = NULL;
1085 guint32 progbar_quantum;
1086 guint32 progbar_nextstep;
1088 proto_tree *protocol_tree;
1090 start_fd = cf->current_frame;
1091 if (start_fd != NULL) {
1092 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
1094 /* Iterate through the list of packets, starting at the packet we've
1095 picked, calling a routine to run the filter on the packet, see if
1096 it matches, and stop if so. */
1100 proto_tree_is_visible = FALSE;
1102 /* Update the progress bar when it gets to this value. */
1103 progbar_nextstep = 0;
1104 /* When we reach the value that triggers a progress bar update,
1105 bump that value by this amount. */
1106 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1107 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
1111 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1112 when we update it, we have to run the GTK+ main loop to get it
1113 to repaint what's pending, and doing so may involve an "ioctl()"
1114 to see if there's any pending input from an X server, and doing
1115 that for every packet can be costly, especially on a big file. */
1116 if (count >= progbar_nextstep) {
1117 /* let's not divide by zero. I should never be started
1118 * with count == 0, so let's assert that
1120 g_assert(cf->count > 0);
1122 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1123 (gfloat) count / cf->count);
1125 progbar_nextstep += progbar_quantum;
1126 while (gtk_events_pending())
1127 gtk_main_iteration();
1130 /* Go past the current frame. */
1131 if (cf->sbackward) {
1132 /* Go on to the previous frame. */
1135 fd = cf->plist_end; /* wrap around */
1137 /* Go on to the next frame. */
1140 fd = cf->plist; /* wrap around */
1143 if (fd == start_fd) {
1144 /* We're back to the frame we were on originally. The search
1151 /* Is this packet in the display? */
1152 if (fd->passed_dfilter) {
1153 /* Yes. Does it match the search filter? */
1154 protocol_tree = proto_tree_create_root();
1155 wtap_seek_read(cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1156 dissect_packet(cf->pd, fd, protocol_tree);
1157 if (dfilter_apply(sfcode, protocol_tree, cf->pd)) {
1159 break; /* found it! */
1164 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1167 if (new_fd != NULL) {
1168 /* We found a frame. Make it visible, and select it. */
1169 if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), new_fd->row))
1170 gtk_clist_moveto(GTK_CLIST(packet_list), new_fd->row, -1, 0.0, 0.0);
1172 /* XXX - why is there no "gtk_clist_set_focus_row()", so that we
1173 can make the row for the frame we found the focus row?
1177 http://www.gnome.org/mailing-lists/archives/gtk-list/2000-January/0038.shtml
1180 GTK_CLIST(packet_list)->focus_row = new_fd->row;
1181 gtk_clist_select_row(GTK_CLIST(packet_list), new_fd->row, -1);
1182 return TRUE; /* success */
1184 return FALSE; /* failure */
1188 goto_frame(capture_file *cf, guint fnumber)
1192 for (fd = cf->plist; fd != NULL && fd->num < fnumber; fd = fd->next)
1196 return NO_SUCH_FRAME; /* we didn't find that frame */
1197 if (!fd->passed_dfilter)
1198 return FRAME_NOT_DISPLAYED; /* the frame with that number isn't displayed */
1200 /* We found that frame, and it's currently being displayed.
1201 Make it visible, and select it. */
1202 if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), fd->row))
1203 gtk_clist_moveto(GTK_CLIST(packet_list), fd->row, -1, 0.0, 0.0);
1205 /* See above complaint about the lack of "gtk_clist_set_focus_row()". */
1206 GTK_CLIST(packet_list)->focus_row = fd->row;
1207 gtk_clist_select_row(GTK_CLIST(packet_list), fd->row, -1);
1211 /* Select the packet on a given row. */
1213 select_packet(capture_file *cf, int row)
1218 /* Search through the list of frames to see which one is in
1220 for (fd = cf->plist, i = 0; fd != NULL; fd = fd->next, i++) {
1225 g_assert(fd != NULL);
1227 /* Record that this frame is the current frame, and that it's selected. */
1228 cf->current_frame = fd;
1229 cf->current_frame_is_selected = TRUE;
1231 /* Get the data in that frame. */
1232 wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1234 /* Create the logical protocol tree. */
1235 if (cf->protocol_tree)
1236 proto_tree_free(cf->protocol_tree);
1237 cf->protocol_tree = proto_tree_create_root();
1238 proto_tree_is_visible = TRUE;
1239 dissect_packet(cf->pd, cf->current_frame, cf->protocol_tree);
1241 /* Display the GUI protocol tree and hex dump. */
1242 clear_tree_and_hex_views();
1243 proto_tree_draw(cf->protocol_tree, tree_view);
1244 packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->current_frame->cap_len,
1245 -1, -1, cf->current_frame->encoding);
1247 /* A packet is selected. */
1248 set_menus_for_selected_packet(TRUE);
1251 /* Unselect the selected packet, if any. */
1253 unselect_packet(capture_file *cf)
1255 cf->current_frame_is_selected = FALSE;
1257 /* Destroy the protocol tree for that packet. */
1258 if (cf->protocol_tree != NULL) {
1259 proto_tree_free(cf->protocol_tree);
1260 cf->protocol_tree = NULL;
1263 finfo_selected = NULL;
1265 /* Clear out the display of that packet. */
1266 clear_tree_and_hex_views();
1268 /* No packet is selected. */
1269 set_menus_for_selected_packet(FALSE);
1273 freeze_clist(capture_file *cf)
1277 /* Make the column sizes static, so they don't adjust while
1278 we're reading the capture file (freezing the clist doesn't
1279 seem to suffice). */
1280 for (i = 0; i < cf->cinfo.num_cols; i++)
1281 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1282 gtk_clist_freeze(GTK_CLIST(packet_list));
1286 thaw_clist(capture_file *cf)
1290 for (i = 0; i < cf->cinfo.num_cols; i++) {
1291 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1292 /* Set this column's width to the appropriate value. */
1293 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1294 cf->cinfo.col_width[i]);
1296 /* Make this column's size dynamic, so that it adjusts to the
1297 appropriate size. */
1298 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1301 gtk_clist_thaw(GTK_CLIST(packet_list));
1303 /* Hopefully, the columns have now gotten their appropriate sizes;
1304 make them resizeable - a column that auto-resizes cannot be
1305 resized by the user, and *vice versa*. */
1306 for (i = 0; i < cf->cinfo.num_cols; i++)
1307 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1311 save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
1314 gchar *from_filename;
1315 gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
1319 int from_fd, to_fd, nread, nwritten;
1322 struct wtap_pkthdr hdr;
1325 if ((name_ptr = (gchar *) strrchr(fname, PATH_SEPARATOR)) == NULL)
1329 msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
1330 save_msg = g_malloc(msg_len);
1331 snprintf(save_msg, msg_len, save_fmt, name_ptr);
1332 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
1335 if (!save_filtered && save_format == cf->cd_t) {
1336 /* We're not filtering packets, and we're saving it in the format
1337 it's already in, so we can just move or copy the raw data. */
1339 /* In this branch, we set "err" only if we get an error, so we
1340 must first clear it. */
1342 if (cf->is_tempfile) {
1343 /* The file being saved is a temporary file from a live
1344 capture, so it doesn't need to stay around under that name;
1345 first, try renaming the capture buffer file to the new name. */
1346 if (rename(cf->filename, fname) == 0) {
1347 /* That succeeded - there's no need to copy the source file. */
1348 from_filename = NULL;
1351 if (errno == EXDEV) {
1352 /* They're on different file systems, so we have to copy the
1355 from_filename = cf->filename;
1357 /* The rename failed, but not because they're on different
1358 file systems - put up an error message. (Or should we
1359 just punt and try to copy? The only reason why I'd
1360 expect the rename to fail and the copy to succeed would
1361 be if we didn't have permission to remove the file from
1362 the temporary directory, and that might be fixable - but
1363 is it worth requiring the user to go off and fix it?) */
1365 simple_dialog(ESD_TYPE_WARN, NULL,
1366 file_rename_error_message(err), fname);
1371 /* It's a permanent file, so we should copy it, and not remove the
1374 from_filename = cf->filename;
1377 /* Copy the file, if we haven't moved it. */
1379 /* Copy the raw bytes of the file. */
1380 from_fd = open(from_filename, O_RDONLY);
1383 simple_dialog(ESD_TYPE_WARN, NULL,
1384 file_open_error_message(err, TRUE), from_filename);
1388 to_fd = creat(fname, 0644);
1391 simple_dialog(ESD_TYPE_WARN, NULL,
1392 file_open_error_message(err, TRUE), fname);
1397 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
1398 nwritten = write(to_fd, pd, nread);
1399 if (nwritten < nread) {
1403 err = WTAP_ERR_SHORT_WRITE;
1404 simple_dialog(ESD_TYPE_WARN, NULL,
1405 file_write_error_message(err), fname);
1413 simple_dialog(ESD_TYPE_WARN, NULL,
1414 file_read_error_message(err), from_filename);
1420 if (close(to_fd) < 0) {
1422 simple_dialog(ESD_TYPE_WARN, NULL,
1423 file_close_error_message(err), fname);
1428 /* Either we're filtering packets, or we're saving in a different
1429 format; we can't do that by copying or moving the capture file,
1430 we have to do it by writing the packets out in Wiretap. */
1431 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
1433 simple_dialog(ESD_TYPE_WARN, NULL,
1434 file_open_error_message(err, TRUE), fname);
1438 /* XXX - have a way to save only the packets currently selected by
1441 If we do that, should we make that file the current file? If so,
1442 it means we can no longer get at the other packets. What does
1444 for (fd = cf->plist; fd != NULL; fd = fd->next) {
1445 /* XXX - do a progress bar */
1446 if (!save_filtered || fd->passed_dfilter) {
1447 /* Either we're saving all frames, or we're saving filtered frames
1448 and this one passed the display filter - save it. */
1449 hdr.ts.tv_sec = fd->abs_secs;
1450 hdr.ts.tv_usec = fd->abs_usecs;
1451 hdr.caplen = fd->cap_len;
1452 hdr.len = fd->pkt_len;
1453 hdr.pkt_encap = fd->lnk_t;
1454 hdr.pseudo_header = fd->pseudo_header;
1455 wtap_seek_read(cf->cd_t, cf->fh, fd->file_off, pd, fd->cap_len);
1457 if (!wtap_dump(pdh, &hdr, pd, &err)) {
1458 simple_dialog(ESD_TYPE_WARN, NULL,
1459 file_write_error_message(err), fname);
1460 wtap_dump_close(pdh, &err);
1466 if (!wtap_dump_close(pdh, &err)) {
1467 simple_dialog(ESD_TYPE_WARN, NULL,
1468 file_close_error_message(err), fname);
1475 /* Pop the "Saving:" message off the status bar. */
1476 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
1478 if (!save_filtered) {
1479 /* We saved the entire capture, not just some packets from it.
1480 Open and read the file we saved it to.
1482 XXX - this is somewhat of a waste; we already have the
1483 packets, all this gets us is updated file type information
1484 (which we could just stuff into "cf"), and having the new
1485 file be the one we have opened and from which we're reading
1486 the data, and it means we have to spend time opening and
1487 reading the file, which could be a significant amount of
1488 time if the file is large. */
1489 cf->user_saved = TRUE;
1491 if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
1492 /* XXX - report errors if this fails? */
1493 err = read_cap_file(cf);
1494 set_menus_for_unsaved_capture_file(FALSE);
1502 file_open_error_message(int err, int for_writing)
1505 static char errmsg_errno[1024+1];
1509 case WTAP_ERR_NOT_REGULAR_FILE:
1510 errmsg = "The file \"%s\" is invalid.";
1513 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1514 case WTAP_ERR_UNSUPPORTED:
1515 /* Seen only when opening a capture file for reading. */
1516 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1519 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1520 /* Seen only when opening a capture file for writing. */
1521 errmsg = "Ethereal does not support writing capture files in that format.";
1524 case WTAP_ERR_UNSUPPORTED_ENCAP:
1525 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1526 /* Seen only when opening a capture file for writing. */
1527 errmsg = "Ethereal cannot save this capture in that format.";
1530 case WTAP_ERR_BAD_RECORD:
1531 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1534 case WTAP_ERR_CANT_OPEN:
1536 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1538 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1541 case WTAP_ERR_SHORT_READ:
1542 errmsg = "The file \"%s\" appears to have been cut short"
1543 " in the middle of a packet.";
1546 case WTAP_ERR_SHORT_WRITE:
1547 errmsg = "A full header couldn't be written to the file \"%s\".";
1552 errmsg = "The path to the file \"%s\" does not exist.";
1554 errmsg = "The file \"%s\" does not exist.";
1559 errmsg = "You do not have permission to create or write to the file \"%s\".";
1561 errmsg = "You do not have permission to read the file \"%s\".";
1565 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
1566 wtap_strerror(err));
1567 errmsg = errmsg_errno;
1574 file_rename_error_message(int err)
1577 static char errmsg_errno[1024+1];
1582 errmsg = "The path to the file \"%s\" does not exist.";
1586 errmsg = "You do not have permission to move the capture file to \"%s\".";
1590 sprintf(errmsg_errno, "The file \"%%s\" could not be moved: %s.",
1591 wtap_strerror(err));
1592 errmsg = errmsg_errno;
1599 file_read_error_message(int err)
1601 static char errmsg_errno[1024+1];
1603 sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.",
1604 wtap_strerror(err));
1605 return errmsg_errno;
1609 file_write_error_message(int err)
1612 static char errmsg_errno[1024+1];
1617 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1622 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1627 sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.",
1628 wtap_strerror(err));
1629 errmsg = errmsg_errno;
1635 /* Check for write errors - if the file is being written to an NFS server,
1636 a write error may not show up until the file is closed, as NFS clients
1637 might not send writes to the server until the "write()" call finishes,
1638 so that the write may fail on the server but the "write()" may succeed. */
1640 file_close_error_message(int err)
1643 static char errmsg_errno[1024+1];
1647 case WTAP_ERR_CANT_CLOSE:
1648 errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
1651 case WTAP_ERR_SHORT_WRITE:
1652 errmsg = "Not all the data could be written to the file \"%s\".";
1656 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1661 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1666 sprintf(errmsg_errno, "An error occurred while closing the file \"%%s\": %s.",
1667 wtap_strerror(err));
1668 errmsg = errmsg_errno;