4 * $Id: file.c,v 1.99 1999/09/29 14:41:34 gram 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.
50 #ifdef NEED_SNPRINTF_H
56 # include "snprintf.h"
59 #ifdef NEED_STRERROR_H
63 #ifdef HAVE_SYS_TYPES_H
64 # include <sys/types.h>
67 #ifdef HAVE_NETINET_IN_H
68 # include <netinet/in.h>
78 #include "gtk/proto_draw.h"
80 #include "timestamp.h"
82 #include "packet-ncp.h"
84 extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view;
85 extern guint file_ctx;
86 extern int sync_pipe[];
89 gboolean auto_scroll_live = FALSE;
91 static guint32 firstsec, firstusec;
92 static guint32 prevsec, prevusec;
94 static void wtap_dispatch_cb(u_char *, const struct wtap_pkthdr *, int,
97 static void freeze_clist(capture_file *cf);
98 static void thaw_clist(capture_file *cf);
100 /* Update the progress bar this many times when reading a file. */
101 #define N_PROGBAR_UPDATES 100
104 open_cap_file(char *fname, capture_file *cf) {
111 wth = wtap_open_offline(fname, &err);
115 /* Find the size of the file. */
118 if (fstat(fd, &cf_stat) < 0) {
124 /* The open succeeded. Close whatever capture file we had open,
125 and fill in the information for this file. */
126 close_cap_file(cf, info_bar, file_ctx);
128 /* Initialize protocol-specific variables */
134 cf->f_len = cf_stat.st_size;
136 /* set the file name because we need it to set the follow stream filter */
137 cf->filename = g_strdup(fname);
139 cf->cd_t = wtap_file_type(cf->wth);
140 cf->cd_t_desc = wtap_file_type_string(cf->wth);
145 cf->snap = wtap_snapshot_length(cf->wth);
146 cf->update_progbar = FALSE;
147 cf->progbar_quantum = 0;
148 cf->progbar_nextstep = 0;
149 firstsec = 0, firstusec = 0;
150 prevsec = 0, prevusec = 0;
155 simple_dialog(ESD_TYPE_WARN, NULL,
156 file_open_error_message(err, FALSE), fname);
160 /* Reset everything to a pristine state */
162 close_cap_file(capture_file *cf, void *w, guint context) {
163 frame_data *fd, *fd_next;
173 for (fd = cf->plist; fd != NULL; fd = fd_next) {
177 if (cf->rfcode != NULL) {
178 dfilter_destroy(cf->rfcode);
182 cf->plist_end = NULL;
183 unselect_packet(cf); /* nothing to select */
185 gtk_clist_freeze(GTK_CLIST(packet_list));
186 gtk_clist_clear(GTK_CLIST(packet_list));
187 gtk_clist_thaw(GTK_CLIST(packet_list));
188 gtk_statusbar_pop(GTK_STATUSBAR(w), context);
190 /* Disable all menu items that make sense only if you have a capture. */
191 set_menu_sensitivity("/File/Save", FALSE);
192 set_menu_sensitivity("/File/Save As...", FALSE);
193 set_menu_sensitivity("/File/Close", FALSE);
194 set_menu_sensitivity("/File/Reload", FALSE);
195 set_menu_sensitivity("/File/Print...", FALSE);
196 set_menu_sensitivity("/Display/Options...", FALSE);
197 set_menu_sensitivity("/Tools/Summary", FALSE);
201 read_cap_file(capture_file *cf) {
202 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
203 gchar *done_fmt = " File: %s Drops: %d";
208 char errmsg_errno[1024+1];
209 gchar err_str[2048+1];
211 if ((name_ptr = (gchar *) strrchr(cf->filename, '/')) == NULL)
212 name_ptr = cf->filename;
216 load_msg = g_malloc(strlen(name_ptr) + strlen(load_fmt) + 2);
217 sprintf(load_msg, load_fmt, name_ptr);
218 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
220 cf->update_progbar = TRUE;
221 /* Update the progress bar when it gets to this value. */
222 cf->progbar_nextstep = 0;
223 /* When we reach the value that triggers a progress bar update,
224 bump that value by this amount. */
225 cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
228 proto_tree_is_visible = FALSE;
229 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
232 cf->filed = open(cf->filename, O_RDONLY);
233 cf->fh = filed_open(cf->filed, "r");
234 cf->unfiltered_count = cf->count;
237 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
238 gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
240 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
242 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
243 load_msg = g_realloc(load_msg, msg_len);
245 if (cf->user_saved || !cf->save_file)
246 snprintf(load_msg, msg_len, done_fmt, name_ptr, cf->drops);
248 snprintf(load_msg, msg_len, done_fmt, "<none>", cf->drops);
250 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
253 /* Enable menu items that make sense if you have a capture. */
254 set_menu_sensitivity("/File/Close", TRUE);
255 set_menu_sensitivity("/File/Reload", TRUE);
256 set_menu_sensitivity("/File/Print...", TRUE);
257 set_menu_sensitivity("/Display/Options...", TRUE);
258 set_menu_sensitivity("/Tools/Summary", TRUE);
261 /* Put up a message box noting that the read failed somewhere along
262 the line. Don't throw out the stuff we managed to read, though,
266 case WTAP_ERR_CANT_READ:
267 errmsg = "An attempt to read from the file failed for"
268 " some unknown reason.";
271 case WTAP_ERR_SHORT_READ:
272 errmsg = "The capture file appears to have been cut short"
273 " in the middle of a packet.";
276 case WTAP_ERR_BAD_RECORD:
277 errmsg = "The capture file appears to be damaged or corrupt.";
281 sprintf(errmsg_errno, "An error occurred while reading the"
282 " capture file: %s.", wtap_strerror(err));
283 errmsg = errmsg_errno;
286 snprintf(err_str, sizeof err_str, errmsg);
287 simple_dialog(ESD_TYPE_WARN, NULL, err_str);
295 cap_file_input_cb (gpointer data, gint source, GdkInputCondition condition) {
297 capture_file *cf = (capture_file *)data;
298 char buffer[256+1], *p = buffer, *q = buffer;
301 gboolean exit_loop = FALSE;
304 /* avoid reentrancy problems and stack overflow */
305 gtk_input_remove(cap_input_id);
307 if ((nread = read(sync_pipe[0], buffer, 256)) <= 0) {
309 /* The child has closed the sync pipe, meaning it's not going to be
310 capturing any more packets. Read what remains of the capture file,
311 and stop capture (restore menu items) */
312 gtk_clist_freeze(GTK_CLIST(packet_list));
314 /* XXX - do something if this fails? */
315 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
318 if (auto_scroll_live)
319 gtk_clist_moveto(GTK_CLIST(packet_list),
320 cf->plist_end->row, -1, 1.0, 1.0);
324 set_menu_sensitivity("/File/Open...", TRUE);
325 set_menu_sensitivity("/File/Close", TRUE);
326 set_menu_sensitivity("/File/Save As...", TRUE);
327 set_menu_sensitivity("/File/Print...", TRUE);
328 set_menu_sensitivity("/File/Reload", TRUE);
329 set_menu_sensitivity("/Capture/Start...", TRUE);
330 set_menu_sensitivity("/Tools/Summary", TRUE);
331 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, " File: <none>");
335 buffer[nread] = '\0';
338 /* look for (possibly multiple) '*' */
346 /* XXX should handle the case of a pipe full (i.e. no star found) */
355 gtk_clist_freeze(GTK_CLIST(packet_list));
356 /* XXX - do something if this fails? */
357 wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf, &err);
358 gtk_clist_thaw(GTK_CLIST(packet_list));
359 if (auto_scroll_live)
360 gtk_clist_moveto(GTK_CLIST(packet_list), cf->plist_end->row, -1, 1.0, 1.0);
362 /* restore pipe handler */
363 cap_input_id = gtk_input_add_full (sync_pipe[0],
372 tail_cap_file(char *fname, capture_file *cf) {
376 err = open_cap_file(fname, cf);
377 if ((err == 0) && (cf->cd_t != WTAP_FILE_UNKNOWN)) {
379 set_menu_sensitivity("/File/Open...", FALSE);
380 set_menu_sensitivity("/Display/Options...", TRUE);
381 set_menu_sensitivity("/Capture/Start...", FALSE);
383 for (i = 0; i < cf->cinfo.num_cols; i++) {
384 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
385 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
387 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
388 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
389 cf->cinfo.col_width[i]);
390 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
394 cf->fh = file_open(fname, "r");
396 cap_input_id = gtk_input_add_full (sync_pipe[0],
402 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
403 " <live capture in progress>");
410 #endif /* HAVE_LIBPCAP */
412 /* To do: Add check_col checks to the col_add* routines */
415 col_add_abs_time(frame_data *fd, gint el)
421 tmp = localtime(&then);
422 col_add_fstr(fd, el, "%02d:%02d:%02d.%04ld",
426 (long)fd->abs_usecs/100);
430 col_add_rel_time(frame_data *fd, gint el)
432 col_add_fstr(fd, el, "%d.%06d", fd->rel_secs, fd->rel_usecs);
436 col_add_delta_time(frame_data *fd, gint el)
438 col_add_fstr(fd, el, "%d.%06d", fd->del_secs, fd->del_usecs);
441 /* Add "command-line-specified" time. */
443 col_add_cls_time(frame_data *fd)
445 switch (timestamp_type) {
447 col_add_abs_time(fd, COL_CLS_TIME);
451 col_add_rel_time(fd, COL_CLS_TIME);
455 col_add_delta_time(fd, COL_CLS_TIME);
461 fill_in_columns(frame_data *fd)
463 if (check_col(fd, COL_NUMBER))
464 col_add_fstr(fd, COL_NUMBER, "%u", fd->num);
466 /* Set any time stamp columns. */
467 if (check_col(fd, COL_CLS_TIME))
468 col_add_cls_time(fd);
469 if (check_col(fd, COL_ABS_TIME))
470 col_add_abs_time(fd, COL_ABS_TIME);
471 if (check_col(fd, COL_REL_TIME))
472 col_add_rel_time(fd, COL_REL_TIME);
473 if (check_col(fd, COL_DELTA_TIME))
474 col_add_delta_time(fd, COL_DELTA_TIME);
476 if (check_col(fd, COL_PACKET_LENGTH))
477 col_add_fstr(fd, COL_PACKET_LENGTH, "%d", fd->pkt_len);
481 add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf)
486 proto_tree *protocol_tree;
488 fdata->num = cf->count;
490 /* If we don't have the time stamp of the first packet in the
491 capture, it's because this is the first packet. Save the time
492 stamp of this packet as the time stamp of the first packet. */
493 if (!firstsec && !firstusec) {
494 firstsec = fdata->abs_secs;
495 firstusec = fdata->abs_usecs;
498 /* Get the time elapsed between the first packet and this packet. */
499 cf->esec = fdata->abs_secs - firstsec;
500 if (firstusec <= fdata->abs_usecs) {
501 cf->eusec = fdata->abs_usecs - firstusec;
503 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
507 fdata->cinfo = &cf->cinfo;
508 for (i = 0; i < fdata->cinfo->num_cols; i++) {
509 fdata->cinfo->col_data[i][0] = '\0';
512 /* Apply the filters */
513 if (DFILTER_CONTAINS_FILTER(cf->dfcode) ||
514 CFILTERS_CONTAINS_FILTER(cf)) {
515 protocol_tree = proto_tree_create_root();
516 dissect_packet(buf, fdata, protocol_tree);
517 if( DFILTER_CONTAINS_FILTER(cf->dfcode) )
518 fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
520 fdata->passed_dfilter = TRUE;
521 /* Apply color filters. */
523 for(crow = 0; cf->colors->num_of_filters &&
524 crow < cf->colors->num_of_filters; crow++) {
526 if(color_filter(cf,crow)->c_colorfilter == NULL) {
529 if(dfilter_apply(color_filter(cf,crow)->c_colorfilter, protocol_tree,
536 proto_tree_free(protocol_tree);
539 dissect_packet(buf, fdata, NULL);
540 fdata->passed_dfilter = TRUE;
543 if (fdata->passed_dfilter) {
544 /* If we don't have the time stamp of the previous displayed packet,
545 it's because this is the first displayed packet. Save the time
546 stamp of this packet as the time stamp of the previous displayed
548 if (!prevsec && !prevusec) {
549 prevsec = fdata->abs_secs;
550 prevusec = fdata->abs_usecs;
553 /* Get the time elapsed between the first packet and this packet. */
554 fdata->rel_secs = cf->esec;
555 fdata->rel_usecs = cf->eusec;
557 /* Get the time elapsed between the previous displayed packet and
559 fdata->del_secs = fdata->abs_secs - prevsec;
560 if (prevusec <= fdata->abs_usecs) {
561 fdata->del_usecs = fdata->abs_usecs - prevusec;
563 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
566 prevsec = fdata->abs_secs;
567 prevusec = fdata->abs_usecs;
569 fill_in_columns(fdata);
571 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
574 if (cf->colors->color_filters && (color != -1)){
575 gtk_clist_set_background(GTK_CLIST(packet_list), row,
576 &(color_filter(cf,color)->bg_color));
577 gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
578 &(color_filter(cf,color)->fg_color));
580 gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
581 gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
584 /* If this was the selected packet, remember the row it's in, so
585 we can re-select it. ("selected_packet" is 0-origin, as it's
586 a GList index; "num", however, is 1-origin.) */
587 if (cf->selected_packet == fdata->num - 1)
588 cf->selected_row = row;
590 fdata->row = -1; /* not in the display */
595 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
598 capture_file *cf = (capture_file *) user;
600 proto_tree *protocol_tree;
601 frame_data *plist_end;
605 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
606 when we update it, we have to run the GTK+ main loop to get it
607 to repaint what's pending, and doing so may involve an "ioctl()"
608 to see if there's any pending input from an X server, and doing
609 that for every packet can be costly, especially on a big file.
611 Do so only if we were told to do so; when reading a capture file
612 being updated by a live capture, we don't do so (as we're not
613 "done" until the capture stops, so we don't know how close to
616 if (cf->update_progbar && offset >= cf->progbar_nextstep) {
617 file_pos = lseek(cf->filed, 0, SEEK_CUR);
618 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
619 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), prog_val);
620 cf->progbar_nextstep += cf->progbar_quantum;
621 while (gtk_events_pending())
622 gtk_main_iteration();
625 /* Allocate the next list entry, and add it to the list. */
626 fdata = (frame_data *) g_malloc(sizeof(frame_data));
629 fdata->pkt_len = phdr->len;
630 fdata->cap_len = phdr->caplen;
631 fdata->file_off = offset;
632 fdata->lnk_t = phdr->pkt_encap;
633 fdata->abs_secs = phdr->ts.tv_sec;
634 fdata->abs_usecs = phdr->ts.tv_usec;
635 fdata->pseudo_header = phdr->pseudo_header;
640 if (DFILTER_CONTAINS_FILTER(cf->rfcode)) {
641 protocol_tree = proto_tree_create_root();
642 dissect_packet(buf, fdata, protocol_tree);
643 passed = dfilter_apply(cf->rfcode, protocol_tree, cf->pd);
644 proto_tree_free(protocol_tree);
648 plist_end = cf->plist_end;
649 if (plist_end != NULL)
650 plist_end->next = fdata;
653 cf->plist_end = fdata;
656 add_packet_to_packet_list(fdata, cf, buf);
662 filter_packets(capture_file *cf)
665 guint32 progbar_quantum;
666 guint32 progbar_nextstep;
668 if (cf->dfilter == NULL) {
669 dfilter_clear_filter(cf->dfcode);
673 * Compile the filter.
675 if (dfilter_compile(cf->dfcode, cf->dfilter) != 0) {
676 simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
681 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
683 /* Freeze the packet list while we redo it, so we don't get any
684 screen updates while it happens. */
685 gtk_clist_freeze(GTK_CLIST(packet_list));
688 gtk_clist_clear(GTK_CLIST(packet_list));
690 /* If a packet was selected, we don't know yet what row, if any, it'll
692 cf->selected_row = -1;
694 /* Iterate through the list of packets, calling a routine
695 to run the filter on the packet, see if it matches, and
696 put it in the display list if so. */
701 cf->unfiltered_count = cf->count;
704 proto_tree_is_visible = FALSE;
706 /* Update the progress bar when it gets to this value. */
707 progbar_nextstep = 0;
708 /* When we reach the value that triggers a progress bar update,
709 bump that value by this amount. */
710 progbar_quantum = cf->unfiltered_count/N_PROGBAR_UPDATES;
711 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
713 for (fd = cf->plist; fd != NULL; fd = fd->next) {
714 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
715 when we update it, we have to run the GTK+ main loop to get it
716 to repaint what's pending, and doing so may involve an "ioctl()"
717 to see if there's any pending input from an X server, and doing
718 that for every packet can be costly, especially on a big file. */
719 if (cf->count >= progbar_nextstep) {
720 /* let's not divide by zero. I should never be started
721 * with unfiltered_count == 0, so let's assert that
723 g_assert(cf->unfiltered_count > 0);
725 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
726 (gfloat) cf->count / cf->unfiltered_count);
728 progbar_nextstep += progbar_quantum;
729 while (gtk_events_pending())
730 gtk_main_iteration();
735 wtap_seek_read (cf-> cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
737 add_packet_to_packet_list(fd, cf, cf->pd);
740 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
742 if (cf->selected_row != -1) {
743 /* We had a selected packet and it passed the filter. */
744 gtk_clist_select_row(GTK_CLIST(packet_list), cf->selected_row, -1);
746 /* If we had one, it didn't pass the filter. */
750 /* Unfreeze the packet list. */
751 gtk_clist_thaw(GTK_CLIST(packet_list));
755 print_packets(capture_file *cf, print_args_t *print_args)
759 guint32 progbar_quantum;
760 guint32 progbar_nextstep;
762 proto_tree *protocol_tree;
763 gint *col_widths = NULL;
765 gboolean print_separator;
767 cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
768 if (cf->print_fh == NULL)
769 return FALSE; /* attempt to open destination failed */
771 /* XXX - printing multiple frames in PostScript looks as if it's
772 tricky - you have to deal with page boundaries, I think -
773 and I'll have to spend some time learning enough about
774 PostScript to figure it out, so, for now, we only print
775 multiple frames as text. */
777 print_preamble(cf->print_fh);
780 if (print_args->print_summary) {
781 /* We're printing packet summaries.
783 Find the widths for each of the columns - maximum of the
784 width of the title and the width of the data - and print
785 the column titles. */
786 col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
787 for (i = 0; i < cf->cinfo.num_cols; i++) {
788 /* Don't pad the last column. */
789 if (i == cf->cinfo.num_cols - 1)
792 col_widths[i] = strlen(cf->cinfo.col_title[i]);
793 data_width = get_column_char_width(get_column_format(i));
794 if (data_width > col_widths[i])
795 col_widths[i] = data_width;
798 /* Right-justify the packet number column. */
799 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
800 fprintf(cf->print_fh, "%*s", col_widths[i], cf->cinfo.col_title[i]);
802 fprintf(cf->print_fh, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
803 if (i == cf->cinfo.num_cols - 1)
804 fputc('\n', cf->print_fh);
806 fputc(' ', cf->print_fh);
810 print_separator = FALSE;
811 proto_tree_is_visible = TRUE;
813 /* Update the progress bar when it gets to this value. */
814 progbar_nextstep = 0;
815 /* When we reach the value that triggers a progress bar update,
816 bump that value by this amount. */
817 progbar_quantum = cf->unfiltered_count/N_PROGBAR_UPDATES;
818 /* Count of packets we've looked at. */
821 /* Iterate through the list of packets, printing the packets that
822 were selected by the current display filter. */
823 for (fd = cf->plist; fd != NULL; fd = fd->next) {
824 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
825 when we update it, we have to run the GTK+ main loop to get it
826 to repaint what's pending, and doing so may involve an "ioctl()"
827 to see if there's any pending input from an X server, and doing
828 that for every packet can be costly, especially on a big file. */
829 if (count >= progbar_nextstep) {
830 /* let's not divide by zero. I should never be started
831 * with unfiltered_count == 0, so let's assert that
833 g_assert(cf->unfiltered_count > 0);
835 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
836 (gfloat) count / cf->unfiltered_count);
837 progbar_nextstep += progbar_quantum;
838 while (gtk_events_pending())
839 gtk_main_iteration();
843 if (fd->passed_dfilter) {
844 wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
845 if (print_args->print_summary) {
846 /* Fill in the column information, but don't bother creating
847 the logical protocol tree. */
848 fd->cinfo = &cf->cinfo;
849 for (i = 0; i < fd->cinfo->num_cols; i++) {
850 fd->cinfo->col_data[i][0] = '\0';
852 dissect_packet(cf->pd, fd, NULL);
854 for (i = 0; i < cf->cinfo.num_cols; i++) {
855 /* Right-justify the packet number column. */
856 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
857 fprintf(cf->print_fh, "%*s", col_widths[i], cf->cinfo.col_data[i]);
859 fprintf(cf->print_fh, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
860 if (i == cf->cinfo.num_cols - 1)
861 fputc('\n', cf->print_fh);
863 fputc(' ', cf->print_fh);
867 fputc('\n', cf->print_fh);
869 /* Create the logical protocol tree. */
870 protocol_tree = proto_tree_create_root();
871 dissect_packet(cf->pd, fd, protocol_tree);
873 /* Print the information in that tree. */
874 proto_tree_print(FALSE, print_args->expand_all, (GNode *)protocol_tree,
875 cf->pd, fd, cf->print_fh);
877 proto_tree_free(protocol_tree);
879 /* Print a blank line if we print anything after this. */
880 print_separator = TRUE;
885 if (col_widths != NULL)
889 print_finale(cf->print_fh);
892 close_print_dest(print_args->to_file, cf->print_fh);
894 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
900 /* Scan through the packet list and change all columns that use the
901 "command-line-specified" time stamp format to use the current
902 value of that format. */
904 change_time_formats(capture_file *cf)
910 /* Freeze the packet list while we redo it, so we don't get any
911 screen updates while it happens. */
914 /* Iterate through the list of packets, checking whether the packet
915 is in a row of the summary list and, if so, whether there are
916 any columns that show the time in the "command-line-specified"
917 format and, if so, update that row. */
918 for (fd = cf->plist; fd != NULL; fd = fd->next) {
920 /* This packet is in the summary list, on row "fd->row". */
922 /* XXX - there really should be a way of checking "cf->cinfo" for this;
923 the answer isn't going to change from packet to packet, so we should
924 simply skip all the "change_time_formats()" work if we're not
925 changing anything. */
926 fd->cinfo = &cf->cinfo;
927 if (check_col(fd, COL_CLS_TIME)) {
928 /* There are columns that show the time in the "command-line-specified"
929 format; update them. */
930 for (i = 0; i < cf->cinfo.num_cols; i++) {
931 cf->cinfo.col_data[i][0] = '\0';
933 col_add_cls_time(fd);
934 for (i = 0; i < cf->cinfo.num_cols; i++) {
935 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
936 /* This is one of the columns that shows the time in
937 "command-line-specified" format; update it. */
938 gtk_clist_set_text(GTK_CLIST(packet_list), fd->row, i,
939 cf->cinfo.col_data[i]);
946 /* Set the column widths of those columns that show the time in
947 "command-line-specified" format. */
948 pl_style = gtk_widget_get_style(packet_list);
949 for (i = 0; i < cf->cinfo.num_cols; i++) {
950 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
951 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
952 get_column_width(COL_CLS_TIME, pl_style->font));
956 /* Unfreeze the packet list. */
961 clear_tree_and_hex_views(void)
966 /* Clear the hex dump. */
967 gtk_text_freeze(GTK_TEXT(byte_view));
968 gtk_text_set_point(GTK_TEXT(byte_view), 0);
969 gtk_text_forward_delete(GTK_TEXT(byte_view),
970 gtk_text_get_length(GTK_TEXT(byte_view)));
971 gtk_text_thaw(GTK_TEXT(byte_view));
973 /* Deselect any selected tree item. gtktree.c should
974 * do this when we clear_items, but it doesn't. I copied
975 * this while() loop from gtktree.c, gtk_real_tree_select_child()
977 if (GTK_TREE(tree_view)->root_tree) {
978 selection = GTK_TREE(tree_view)->root_tree->selection;
980 tmp_item = selection->data;
981 gtk_tree_item_deselect(GTK_TREE_ITEM(tmp_item));
982 gtk_widget_unref(tmp_item);
983 selection = selection->next;
985 g_list_free(GTK_TREE(tree_view)->root_tree->selection);
986 GTK_TREE(tree_view)->root_tree->selection = NULL;
989 /* Clear the protocol tree view. The length arg of -1
990 * means to clear all items up to the end. */
991 gtk_tree_clear_items(GTK_TREE(tree_view), 0, -1);
995 /* Select the packet on a given row. */
997 select_packet(capture_file *cf, int row)
1002 /* Clear out whatever's currently in the hex dump. */
1003 gtk_text_freeze(GTK_TEXT(byte_view));
1004 gtk_text_set_point(GTK_TEXT(byte_view), 0);
1005 gtk_text_forward_delete(GTK_TEXT(byte_view),
1006 gtk_text_get_length(GTK_TEXT(byte_view)));
1008 /* Search through the list of frames to see which one is in
1010 for (fd = cf->plist, i = 0; fd != NULL; fd = fd->next, i++) {
1016 /* Remember the ordinal number of that frame. */
1017 cf->selected_packet = i;
1019 /* Get the data in that frame. */
1020 wtap_seek_read (cf-> cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1022 /* Create the logical protocol tree. */
1023 if (cf->protocol_tree)
1024 proto_tree_free(cf->protocol_tree);
1025 cf->protocol_tree = proto_tree_create_root();
1026 proto_tree_is_visible = TRUE;
1027 dissect_packet(cf->pd, cf->fd, cf->protocol_tree);
1029 /* Display the GUI protocol tree and hex dump. */
1030 clear_tree_and_hex_views();
1031 proto_tree_draw(cf->protocol_tree, tree_view);
1032 packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->fd->cap_len, -1, -1);
1033 gtk_text_thaw(GTK_TEXT(byte_view));
1035 /* A packet is selected, so "File/Print Packet" has something to print. */
1036 set_menu_sensitivity("/File/Print Packet", TRUE);
1037 set_menu_sensitivity("/Display/Collapse All", TRUE);
1038 set_menu_sensitivity("/Display/Expand All", TRUE);
1041 /* Unselect the selected packet, if any. */
1043 unselect_packet(capture_file *cf)
1045 cf->selected_packet = -1; /* nothing there to be selected */
1046 cf->selected_row = -1;
1048 /* Destroy the protocol tree for that packet. */
1049 if (cf->protocol_tree != NULL) {
1050 proto_tree_free(cf->protocol_tree);
1051 cf->protocol_tree = NULL;
1054 /* Clear out the display of that packet. */
1055 clear_tree_and_hex_views();
1057 /* No packet is selected, so "File/Print Packet" has nothing to print. */
1058 set_menu_sensitivity("/File/Print Packet", FALSE);
1059 set_menu_sensitivity("/Display/Collapse All", FALSE);
1060 set_menu_sensitivity("/Display/Expand All", FALSE);
1064 freeze_clist(capture_file *cf)
1068 /* Make the column sizes static, so they don't adjust while
1069 we're reading the capture file (freezing the clist doesn't
1070 seem to suffice). */
1071 for (i = 0; i < cf->cinfo.num_cols; i++)
1072 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1073 gtk_clist_freeze(GTK_CLIST(packet_list));
1077 thaw_clist(capture_file *cf)
1081 for (i = 0; i < cf->cinfo.num_cols; i++) {
1082 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1083 /* Set this column's width to the appropriate value. */
1084 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1085 cf->cinfo.col_width[i]);
1087 /* Make this column's size dynamic, so that it adjusts to the
1088 appropriate size. */
1089 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1092 gtk_clist_thaw(GTK_CLIST(packet_list));
1094 /* Hopefully, the columns have now gotten their appropriate sizes;
1095 make them resizeable - a column that auto-resizes cannot be
1096 resized by the user, and *vice versa*. */
1097 for (i = 0; i < cf->cinfo.num_cols; i++)
1098 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1101 /* Tries to mv a file. If unsuccessful, tries to cp the file.
1102 * Returns 0 on failure to do either, 1 on success of either
1105 file_mv(char *from, char *to)
1108 #define COPY_BUFFER_SIZE 8192
1113 /* try a hard link */
1114 retval = link(from, to);
1119 retval = file_cp(from, to);
1132 * Returns 0 on failure to do either, 1 on success of either
1135 file_cp(char *from, char *to)
1138 #define COPY_BUFFER_SIZE 8192
1140 int from_fd, to_fd, nread, nwritten;
1143 buffer = g_malloc(COPY_BUFFER_SIZE);
1145 from_fd = open(from, O_RDONLY);
1147 simple_dialog(ESD_TYPE_WARN, NULL,
1148 file_open_error_message(errno, TRUE), from);
1152 to_fd = creat(to, 0644);
1154 simple_dialog(ESD_TYPE_WARN, NULL,
1155 file_open_error_message(errno, TRUE), to);
1160 while( (nread = read(from_fd, buffer, COPY_BUFFER_SIZE)) > 0) {
1161 nwritten = write(to_fd, buffer, nread);
1162 if (nwritten < nread) {
1164 simple_dialog(ESD_TYPE_WARN, NULL,
1165 file_write_error_message(errno), to);
1167 simple_dialog(ESD_TYPE_WARN, NULL,
1168 "The file \"%s\" could not be saved: tried writing %d, wrote %d.\n",
1169 to, nread, nwritten);
1177 simple_dialog(ESD_TYPE_WARN, NULL,
1178 file_read_error_message(errno), from);
1190 file_open_error_message(int err, int for_writing)
1193 static char errmsg_errno[1024+1];
1197 case WTAP_ERR_NOT_REGULAR_FILE:
1198 errmsg = "The file \"%s\" is invalid.";
1201 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1202 case WTAP_ERR_UNSUPPORTED:
1203 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1206 case WTAP_ERR_BAD_RECORD:
1207 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1210 case WTAP_ERR_CANT_OPEN:
1212 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1214 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1217 case WTAP_ERR_SHORT_READ:
1218 errmsg = "The file \"%s\" appears to have been cut short"
1219 " in the middle of a packet.";
1224 errmsg = "The path to the file \"%s\" does not exist.";
1226 errmsg = "The file \"%s\" does not exist.";
1231 errmsg = "You do not have permission to create or write to the file \"%s\".";
1233 errmsg = "You do not have permission to read the file \"%s\".";
1237 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
1238 wtap_strerror(err));
1239 errmsg = errmsg_errno;
1246 file_read_error_message(int err)
1248 static char errmsg_errno[1024+1];
1250 sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.",
1251 wtap_strerror(err));
1252 return errmsg_errno;
1256 file_write_error_message(int err)
1259 static char errmsg_errno[1024+1];
1264 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1269 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1274 sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.",
1275 wtap_strerror(err));
1276 errmsg = errmsg_errno;