4 * $Id: file.c,v 1.270 2002/04/24 05:48:43 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
47 #ifdef HAVE_SYS_STAT_H
55 #ifdef NEED_SNPRINTF_H
56 # include "snprintf.h"
59 #ifdef NEED_STRERROR_H
63 #ifdef HAVE_SYS_TYPES_H
64 # include <sys/types.h>
67 #ifdef HAVE_NETINET_IN_H
68 # include <netinet/in.h>
71 #include <epan/epan.h>
72 #include <epan/filesystem.h>
76 #include "gtk/color_utils.h"
78 #include <epan/packet.h>
83 #include "simple_dialog.h"
84 #include "progress_dlg.h"
86 #include "statusbar.h"
88 #include "gtk/proto_draw.h"
89 #include "gtk/packet_win.h"
90 #include <epan/dfilter/dfilter.h>
91 #include <epan/conversation.h>
93 #include "gtk/colors.h"
94 #include <epan/epan_dissect.h>
96 extern GtkWidget *packet_list, *byte_nb_ptr, *tree_view;
99 gboolean auto_scroll_live;
102 static guint32 firstsec, firstusec;
103 static guint32 prevsec, prevusec;
105 static void read_packet(capture_file *cf, long offset);
107 static void rescan_packets(capture_file *cf, const char *action,
108 gboolean refilter, gboolean redissect);
110 static void set_selected_row(int row);
112 static void freeze_clist(capture_file *cf);
113 static void thaw_clist(capture_file *cf);
115 static char *file_rename_error_message(int err);
116 static char *file_close_error_message(int err);
117 static gboolean copy_binary_file(char *from_filename, char *to_filename);
119 /* Update the progress bar this many times when reading a file. */
120 #define N_PROGBAR_UPDATES 100
122 /* Number of "frame_data" structures per memory chunk.
123 XXX - is this the right number? */
124 #define FRAME_DATA_CHUNK_SIZE 1024
127 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
134 wth = wtap_open_offline(fname, &err, TRUE);
138 /* Find the size of the file. */
140 if (fstat(fd, &cf_stat) < 0) {
146 /* The open succeeded. Close whatever capture file we had open,
147 and fill in the information for this file. */
150 /* Initialize all data structures used for dissection. */
153 /* We're about to start reading the file. */
154 cf->state = FILE_READ_IN_PROGRESS;
158 cf->f_len = cf_stat.st_size;
160 /* Set the file name because we need it to set the follow stream filter.
161 XXX - is that still true? We need it for other reasons, though,
163 cf->filename = g_strdup(fname);
165 /* Indicate whether it's a permanent or temporary file. */
166 cf->is_tempfile = is_tempfile;
168 /* If it's a temporary capture buffer file, mark it as not saved. */
169 cf->user_saved = !is_tempfile;
171 cf->cd_t = wtap_file_type(cf->wth);
173 cf->marked_count = 0;
174 cf->drops_known = FALSE;
178 cf->snap = wtap_snapshot_length(cf->wth);
180 /* Snapshot length not known. */
181 cf->has_snap = FALSE;
182 cf->snap = WTAP_MAX_PACKET_SIZE;
185 cf->progbar_quantum = 0;
186 cf->progbar_nextstep = 0;
187 firstsec = 0, firstusec = 0;
188 prevsec = 0, prevusec = 0;
190 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
192 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
194 g_assert(cf->plist_chunk);
199 simple_dialog(ESD_TYPE_CRIT, NULL,
200 file_open_error_message(err, FALSE), fname);
204 /* Reset everything to a pristine state */
206 close_cap_file(capture_file *cf)
208 /* Die if we're in the middle of reading a file. */
209 g_assert(cf->state != FILE_READ_IN_PROGRESS);
211 /* Destroy all popup packet windows, as they refer to packets in the
212 capture file we're closing. */
213 destroy_packet_wins();
219 /* We have no file open... */
220 if (cf->filename != NULL) {
221 /* If it's a temporary file, remove it. */
223 unlink(cf->filename);
224 g_free(cf->filename);
227 /* ...which means we have nothing to save. */
228 cf->user_saved = FALSE;
230 if (cf->plist_chunk != NULL) {
231 g_mem_chunk_destroy(cf->plist_chunk);
232 cf->plist_chunk = NULL;
234 if (cf->rfcode != NULL) {
235 dfilter_free(cf->rfcode);
239 cf->plist_end = NULL;
240 unselect_packet(cf); /* nothing to select */
241 cf->first_displayed = NULL;
242 cf->last_displayed = NULL;
244 /* Clear the packet list. */
245 gtk_clist_freeze(GTK_CLIST(packet_list));
246 gtk_clist_clear(GTK_CLIST(packet_list));
247 gtk_clist_thaw(GTK_CLIST(packet_list));
249 /* Clear any file-related status bar messages.
250 XXX - should be "clear *ALL* file-related status bar messages;
251 will there ever be more than one on the stack? */
252 statusbar_pop_file_msg();
254 /* Restore the standard title bar message. */
255 set_main_window_name("The Ethereal Network Analyzer");
257 /* Disable all menu items that make sense only if you have a capture. */
258 set_menus_for_capture_file(FALSE);
259 set_menus_for_unsaved_capture_file(FALSE);
260 set_menus_for_captured_packets(FALSE);
261 set_menus_for_selected_packet(FALSE);
262 set_menus_for_capture_in_progress(FALSE);
263 set_menus_for_selected_tree_row(FALSE);
265 /* We have no file open. */
266 cf->state = FILE_CLOSED;
269 /* Set the file name in the status line, in the name for the main window,
270 and in the name for the main window's icon. */
272 set_display_filename(capture_file *cf)
276 static const gchar done_fmt_nodrops[] = " File: %s";
277 static const gchar done_fmt_drops[] = " File: %s Drops: %u";
279 gchar *win_name_fmt = "%s - Ethereal";
282 if (!cf->is_tempfile) {
283 /* Get the last component of the file name, and put that in the
285 name_ptr = get_basename(cf->filename);
287 /* The file we read is a temporary file from a live capture;
288 we don't mention its name in the status bar. */
289 name_ptr = "<capture>";
292 if (cf->drops_known) {
293 msg_len = strlen(name_ptr) + strlen(done_fmt_drops) + 64;
294 done_msg = g_malloc(msg_len);
295 snprintf(done_msg, msg_len, done_fmt_drops, name_ptr, cf->drops);
297 msg_len = strlen(name_ptr) + strlen(done_fmt_nodrops);
298 done_msg = g_malloc(msg_len);
299 snprintf(done_msg, msg_len, done_fmt_nodrops, name_ptr);
301 statusbar_push_file_msg(done_msg);
304 msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
305 win_name = g_malloc(msg_len);
306 snprintf(win_name, msg_len, win_name_fmt, name_ptr);
307 set_main_window_name(win_name);
312 read_cap_file(capture_file *cf, int *err)
314 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
317 char errmsg_errno[1024+1];
318 gchar err_str[2048+1];
327 name_ptr = get_basename(cf->filename);
329 msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
330 load_msg = g_malloc(msg_len);
331 snprintf(load_msg, msg_len, load_fmt, name_ptr);
332 statusbar_push_file_msg(load_msg);
334 /* Update the progress bar when it gets to this value. */
335 cf->progbar_nextstep = 0;
336 /* When we reach the value that triggers a progress bar update,
337 bump that value by this amount. */
338 cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
347 progbar = create_progress_dlg(load_msg, "Stop", &stop_flag);
350 while ((wtap_read(cf->wth, err, &data_offset))) {
351 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
352 when we update it, we have to run the GTK+ main loop to get it
353 to repaint what's pending, and doing so may involve an "ioctl()"
354 to see if there's any pending input from an X server, and doing
355 that for every packet can be costly, especially on a big file. */
356 if (data_offset >= cf->progbar_nextstep) {
357 file_pos = lseek(cf->filed, 0, SEEK_CUR);
358 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
359 if (prog_val > 1.0) {
360 /* The file probably grew while we were reading it.
361 Update "cf->f_len", and try again. */
362 fd = wtap_fd(cf->wth);
363 if (fstat(fd, &cf_stat) >= 0) {
364 cf->f_len = cf_stat.st_size;
365 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
367 /* If it's still > 1, either the "fstat()" failed (in which
368 case there's not much we can do about it), or the file
369 *shrank* (in which case there's not much we can do about
370 it); just clip the progress value at 1.0. */
374 update_progress_dlg(progbar, prog_val);
375 cf->progbar_nextstep += cf->progbar_quantum;
379 /* Well, the user decided to abort the read. Destroy the progress
380 bar, close the capture file, and return READ_ABORTED so our caller
381 can do whatever is appropriate when that happens. */
382 destroy_progress_dlg(progbar);
383 cf->state = FILE_READ_ABORTED; /* so that we're allowed to close it */
384 gtk_clist_thaw(GTK_CLIST(packet_list)); /* undo our freeze */
386 return (READ_ABORTED);
388 read_packet(cf, data_offset);
391 /* We're done reading the file; destroy the progress bar. */
392 destroy_progress_dlg(progbar);
394 /* We're done reading sequentially through the file. */
395 cf->state = FILE_READ_DONE;
397 /* Close the sequential I/O side, to free up memory it requires. */
398 wtap_sequential_close(cf->wth);
400 /* Allow the protocol dissectors to free up memory that they
401 * don't need after the sequential run-through of the packets. */
402 postseq_cleanup_all_protocols();
404 /* Set the file encapsulation type now; we don't know what it is until
405 we've looked at all the packets, as we don't know until then whether
406 there's more than one type (and thus whether it's
407 WTAP_ENCAP_PER_PACKET). */
408 cf->lnk_t = wtap_file_encap(cf->wth);
410 cf->current_frame = cf->first_displayed;
413 statusbar_pop_file_msg();
414 set_display_filename(cf);
416 /* Enable menu items that make sense if you have a capture file you've
418 set_menus_for_capture_file(TRUE);
419 set_menus_for_unsaved_capture_file(!cf->user_saved);
421 /* Enable menu items that make sense if you have some captured packets. */
422 set_menus_for_captured_packets(TRUE);
424 /* If we have any displayed packets to select, select the first of those
425 packets by making the first row the selected row. */
426 if (cf->first_displayed != NULL)
427 gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
430 /* Put up a message box noting that the read failed somewhere along
431 the line. Don't throw out the stuff we managed to read, though,
435 case WTAP_ERR_UNSUPPORTED_ENCAP:
436 errmsg = "The capture file is for a network type that Ethereal doesn't support.";
439 case WTAP_ERR_CANT_READ:
440 errmsg = "An attempt to read from the file failed for"
441 " some unknown reason.";
444 case WTAP_ERR_SHORT_READ:
445 errmsg = "The capture file appears to have been cut short"
446 " in the middle of a packet.";
449 case WTAP_ERR_BAD_RECORD:
450 errmsg = "The capture file appears to be damaged or corrupt.";
454 snprintf(errmsg_errno, sizeof(errmsg_errno),
455 "An error occurred while reading the"
456 " capture file: %s.", wtap_strerror(*err));
457 errmsg = errmsg_errno;
460 snprintf(err_str, sizeof err_str, errmsg);
461 simple_dialog(ESD_TYPE_CRIT, NULL, err_str);
464 return (READ_SUCCESS);
469 start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
474 err = open_cap_file(fname, is_tempfile, cf);
476 /* Disable menu items that make no sense if you're currently running
478 set_menus_for_capture_in_progress(TRUE);
480 /* Enable menu items that make sense if you have some captured
481 packets (yes, I know, we don't have any *yet*). */
482 set_menus_for_captured_packets(TRUE);
484 for (i = 0; i < cf->cinfo.num_cols; i++) {
485 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
486 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
488 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
489 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
490 cf->cinfo.col_width[i]);
491 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
495 statusbar_push_file_msg(" <live capture in progress>");
501 continue_tail_cap_file(capture_file *cf, int to_read, int *err)
503 long data_offset = 0;
505 gtk_clist_freeze(GTK_CLIST(packet_list));
507 while (to_read != 0 && (wtap_read(cf->wth, err, &data_offset))) {
508 if (cf->state == FILE_READ_ABORTED) {
509 /* Well, the user decided to exit Ethereal. Break out of the
510 loop, and let the code below (which is called even if there
511 aren't any packets left to read) exit. */
514 read_packet(cf, data_offset);
518 gtk_clist_thaw(GTK_CLIST(packet_list));
520 /* XXX - this cheats and looks inside the packet list to find the final
522 if (auto_scroll_live && cf->plist_end != NULL)
523 gtk_clist_moveto(GTK_CLIST(packet_list),
524 GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
526 if (cf->state == FILE_READ_ABORTED) {
527 /* Well, the user decided to exit Ethereal. Return READ_ABORTED
528 so that our caller can kill off the capture child process;
529 this will cause an EOF on the pipe from the child, so
530 "finish_tail_cap_file()" will be called, and it will clean up
533 } else if (*err != 0) {
534 /* We got an error reading the capture file.
535 XXX - pop up a dialog box? */
538 return (READ_SUCCESS);
542 finish_tail_cap_file(capture_file *cf, int *err)
546 gtk_clist_freeze(GTK_CLIST(packet_list));
548 while ((wtap_read(cf->wth, err, &data_offset))) {
549 if (cf->state == FILE_READ_ABORTED) {
550 /* Well, the user decided to abort the read. Break out of the
551 loop, and let the code below (which is called even if there
552 aren't any packets left to read) exit. */
555 read_packet(cf, data_offset);
558 if (cf->state == FILE_READ_ABORTED) {
559 /* Well, the user decided to abort the read. We're only called
560 when the child capture process closes the pipe to us (meaning
561 it's probably exited), so we can just close the capture
562 file; we return READ_ABORTED so our caller can do whatever
563 is appropriate when that happens. */
569 if (auto_scroll_live && cf->plist_end != NULL)
570 /* XXX - this cheats and looks inside the packet list to find the final
572 gtk_clist_moveto(GTK_CLIST(packet_list),
573 GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
575 /* We're done reading sequentially through the file. */
576 cf->state = FILE_READ_DONE;
578 /* We're done reading sequentially through the file; close the
579 sequential I/O side, to free up memory it requires. */
580 wtap_sequential_close(cf->wth);
582 /* Allow the protocol dissectors to free up memory that they
583 * don't need after the sequential run-through of the packets. */
584 postseq_cleanup_all_protocols();
586 /* Set the file encapsulation type now; we don't know what it is until
587 we've looked at all the packets, as we don't know until then whether
588 there's more than one type (and thus whether it's
589 WTAP_ENCAP_PER_PACKET). */
590 cf->lnk_t = wtap_file_encap(cf->wth);
592 /* Pop the "<live capture in progress>" message off the status bar. */
593 statusbar_pop_file_msg();
595 set_display_filename(cf);
597 /* Enable menu items that make sense if you're not currently running
599 set_menus_for_capture_in_progress(FALSE);
601 /* Enable menu items that make sense if you have a capture file
602 you've finished reading. */
603 set_menus_for_capture_file(TRUE);
604 set_menus_for_unsaved_capture_file(!cf->user_saved);
607 /* We got an error reading the capture file.
608 XXX - pop up a dialog box? */
611 return (READ_SUCCESS);
613 #endif /* HAVE_LIBPCAP */
616 color_filter_t *colorf;
618 } apply_color_filter_args;
621 * If no color filter has been applied, apply this one.
622 * (The "if no color filter has been applied" is to handle the case where
623 * more than one color filter matches the packet.)
626 apply_color_filter(gpointer filter_arg, gpointer argp)
628 color_filter_t *colorf = filter_arg;
629 apply_color_filter_args *args = argp;
631 if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
632 if (dfilter_apply_edt(colorf->c_colorfilter, args->edt))
633 args->colorf = colorf;
638 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
639 union wtap_pseudo_header *pseudo_header, const u_char *buf,
642 apply_color_filter_args args;
644 gboolean create_proto_tree = FALSE;
648 /* We don't yet have a color filter to apply. */
651 /* If we don't have the time stamp of the first packet in the
652 capture, it's because this is the first packet. Save the time
653 stamp of this packet as the time stamp of the first packet. */
654 if (!firstsec && !firstusec) {
655 firstsec = fdata->abs_secs;
656 firstusec = fdata->abs_usecs;
661 we have a display filter and are re-applying it;
663 we have a list of color filters;
665 allocate a protocol tree root node, so that we'll construct
666 a protocol tree against which a filter expression can be
668 if ((cf->dfcode != NULL && refilter) || filter_list != NULL)
669 create_proto_tree = TRUE;
671 /* Dissect the frame. */
672 edt = epan_dissect_new(create_proto_tree, FALSE);
674 if (cf->dfcode != NULL && refilter) {
675 epan_dissect_prime_dfilter(edt, cf->dfcode);
678 filter_list_prime_edt(edt);
680 epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
683 /* If we have a display filter, apply it if we're refiltering, otherwise
684 leave the "passed_dfilter" flag alone.
686 If we don't have a display filter, set "passed_dfilter" to 1. */
687 if (cf->dfcode != NULL) {
689 if (cf->dfcode != NULL)
690 fdata->flags.passed_dfilter = dfilter_apply_edt(cf->dfcode, edt) ? 1 : 0;
692 fdata->flags.passed_dfilter = 1;
695 fdata->flags.passed_dfilter = 1;
697 /* If we have color filters, and the frame is to be displayed, apply
698 the color filters. */
699 if (fdata->flags.passed_dfilter) {
700 if (filter_list != NULL) {
702 g_slist_foreach(filter_list, apply_color_filter, &args);
707 if (fdata->flags.passed_dfilter) {
708 /* This frame passed the display filter, so add it to the clist. */
710 /* If we don't have the time stamp of the previous displayed packet,
711 it's because this is the first displayed packet. Save the time
712 stamp of this packet as the time stamp of the previous displayed
714 if (!prevsec && !prevusec) {
715 prevsec = fdata->abs_secs;
716 prevusec = fdata->abs_usecs;
719 /* Get the time elapsed between the first packet and this packet. */
720 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
721 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
723 /* If it's greater than the current elapsed time, set the elapsed time
724 to it (we check for "greater than" so as not to be confused by
725 time moving backwards). */
726 if ((gint32)cf->esec < fdata->rel_secs
727 || ((gint32)cf->esec == fdata->rel_secs && (gint32)cf->eusec < fdata->rel_usecs)) {
728 cf->esec = fdata->rel_secs;
729 cf->eusec = fdata->rel_usecs;
732 /* Get the time elapsed between the previous displayed packet and
734 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
735 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
736 prevsec = fdata->abs_secs;
737 prevusec = fdata->abs_usecs;
739 epan_dissect_fill_in_columns(edt);
741 /* If we haven't yet seen the first frame, this is it.
743 XXX - we must do this before we add the row to the display,
744 as, if the display's GtkCList's selection mode is
745 GTK_SELECTION_BROWSE, when the first entry is added to it,
746 "select_packet()" will be called, and it will fetch the row
747 data for the 0th row, and will get a null pointer rather than
748 "fdata", as "gtk_clist_append()" won't yet have returned and
749 thus "gtk_clist_set_row_data()" won't yet have been called.
751 We thus need to leave behind bread crumbs so that
752 "select_packet()" can find this frame. See the comment
753 in "select_packet()". */
754 if (cf->first_displayed == NULL)
755 cf->first_displayed = fdata;
757 /* This is the last frame we've seen so far. */
758 cf->last_displayed = fdata;
760 row = gtk_clist_append(GTK_CLIST(packet_list), cf->cinfo.col_data);
761 gtk_clist_set_row_data(GTK_CLIST(packet_list), row, fdata);
763 if (fdata->flags.marked) {
764 color_t_to_gdkcolor(&bg, &prefs.gui_marked_bg);
765 color_t_to_gdkcolor(&fg, &prefs.gui_marked_fg);
766 } else if (filter_list != NULL && (args.colorf != NULL)) {
767 bg = args.colorf->bg_color;
768 fg = args.colorf->fg_color;
773 gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
774 gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
776 /* This frame didn't pass the display filter, so it's not being added
777 to the clist, and thus has no row. */
780 epan_dissect_free(edt);
785 read_packet(capture_file *cf, long offset)
787 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
788 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
789 const u_char *buf = wtap_buf_ptr(cf->wth);
792 frame_data *plist_end;
795 /* Allocate the next list entry, and add it to the list. */
796 fdata = g_mem_chunk_alloc(cf->plist_chunk);
801 fdata->data_src = NULL;
802 fdata->pkt_len = phdr->len;
803 fdata->cap_len = phdr->caplen;
804 fdata->file_off = offset;
805 fdata->lnk_t = phdr->pkt_encap;
806 fdata->abs_secs = phdr->ts.tv_sec;
807 fdata->abs_usecs = phdr->ts.tv_usec;
808 fdata->flags.encoding = CHAR_ASCII;
809 fdata->flags.visited = 0;
810 fdata->flags.marked = 0;
814 edt = epan_dissect_new(TRUE, FALSE);
815 epan_dissect_prime_dfilter(edt, cf->rfcode);
816 epan_dissect_run(edt, pseudo_header, buf, fdata, NULL);
817 passed = dfilter_apply_edt(cf->rfcode, edt);
818 epan_dissect_free(edt);
821 plist_end = cf->plist_end;
822 fdata->prev = plist_end;
823 if (plist_end != NULL)
824 plist_end->next = fdata;
827 cf->plist_end = fdata;
830 fdata->num = cf->count;
831 add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE);
833 /* XXX - if we didn't have read filters, or if we could avoid
834 allocating the "frame_data" structure until we knew whether
835 the frame passed the read filter, we could use a G_ALLOC_ONLY
838 ...but, at least in one test I did, where I just made the chunk
839 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
840 seem to save a noticeable amount of time or space. */
841 g_mem_chunk_free(cf->plist_chunk, fdata);
846 filter_packets(capture_file *cf, gchar *dftext)
850 if (dftext == NULL) {
851 /* The new filter is an empty filter (i.e., display all packets). */
855 * We have a filter; try to compile it.
857 if (!dfilter_compile(dftext, &dfcode)) {
858 /* The attempt failed; report an error. */
859 simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
864 if (dfcode == NULL) {
865 /* Yes - free the filter text, and set it to null. */
871 /* We have a valid filter. Replace the current filter. */
872 if (cf->dfilter != NULL)
874 cf->dfilter = dftext;
875 if (cf->dfcode != NULL)
876 dfilter_free(cf->dfcode);
879 /* Now rescan the packet list, applying the new filter, but not
880 throwing away information constructed on a previous pass. */
881 rescan_packets(cf, "Filtering", TRUE, FALSE);
886 colorize_packets(capture_file *cf)
888 rescan_packets(cf, "Colorizing", FALSE, FALSE);
892 redissect_packets(capture_file *cf)
894 rescan_packets(cf, "Reprocessing", TRUE, TRUE);
897 /* Rescan the list of packets, reconstructing the CList.
899 "action" describes why we're doing this; it's used in the progress
902 "refilter" is TRUE if we need to re-evaluate the filter expression.
904 "redissect" is TRUE if we need to make the dissectors reconstruct
905 any state information they have (because a preference that affects
906 some dissector has changed, meaning some dissector might construct
907 its state differently from the way it was constructed the last time). */
909 rescan_packets(capture_file *cf, const char *action, gboolean refilter,
915 guint32 progbar_quantum;
916 guint32 progbar_nextstep;
919 frame_data *selected_frame;
923 /* Which frame, if any, is the currently selected frame?
924 XXX - should the selected frame or the focus frame be the "current"
925 frame, that frame being the one from which "Find Frame" searches
927 selected_frame = cf->current_frame;
929 /* We don't yet know what row that frame will be on, if any, after we
930 rebuild the clist, however. */
934 /* We need to re-initialize all the state information that protocols
935 keep, because some preference that controls a dissector has changed,
936 which might cause the state information to be constructed differently
937 by that dissector. */
939 /* Initialize all data structures used for dissection. */
943 /* Freeze the packet list while we redo it, so we don't get any
944 screen updates while it happens. */
945 gtk_clist_freeze(GTK_CLIST(packet_list));
948 gtk_clist_clear(GTK_CLIST(packet_list));
950 /* We don't yet know which will be the first and last frames displayed. */
951 cf->first_displayed = NULL;
952 cf->last_displayed = NULL;
954 /* Iterate through the list of frames. Call a routine for each frame
955 to check whether it should be displayed and, if so, add it to
962 /* Update the progress bar when it gets to this value. */
963 progbar_nextstep = 0;
964 /* When we reach the value that triggers a progress bar update,
965 bump that value by this amount. */
966 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
967 /* Count of packets at which we've looked. */
971 progbar = create_progress_dlg(action, "Stop", &stop_flag);
973 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
974 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
975 when we update it, we have to run the GTK+ main loop to get it
976 to repaint what's pending, and doing so may involve an "ioctl()"
977 to see if there's any pending input from an X server, and doing
978 that for every packet can be costly, especially on a big file. */
979 if (count >= progbar_nextstep) {
980 /* let's not divide by zero. I should never be started
981 * with count == 0, so let's assert that
983 g_assert(cf->count > 0);
985 update_progress_dlg(progbar, (gfloat) count / cf->count);
987 progbar_nextstep += progbar_quantum;
991 /* Well, the user decided to abort the filtering. Just stop.
993 XXX - go back to the previous filter? Users probably just
994 want not to wait for a filtering operation to finish;
995 unless we cancel by having no filter, reverting to the
996 previous filter will probably be even more expensive than
997 continuing the filtering, as it involves going back to the
998 beginning and filtering, and even with no filter we currently
999 have to re-generate the entire clist, which is also expensive.
1001 I'm not sure what Network Monitor does, but it doesn't appear
1002 to give you an unfiltered display if you cancel. */
1009 /* Since all state for the frame was destroyed, mark the frame
1010 * as not visited, free the GSList referring to the state
1011 * data (the per-frame data itself was freed by
1012 * "init_dissection()"), and null out the GSList pointer. */
1013 fdata->flags.visited = 0;
1015 g_slist_free(fdata->pfd);
1018 free_data_sources(fdata); /* release data source list */
1021 /* XXX - do something with "err" */
1022 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1023 cf->pd, fdata->cap_len, &err);
1025 row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
1027 if (fdata == selected_frame)
1032 /* Clear out what remains of the visited flags and per-frame data
1035 XXX - that may cause various forms of bogosity when dissecting
1036 these frames, as they won't have been seen by this sequential
1037 pass, but the only alternative I see is to keep scanning them
1038 even though the user requested that the scan stop, and that
1039 would leave the user stuck with an Ethereal grinding on
1040 until it finishes. Should we just stick them with that? */
1041 for (; fdata != NULL; fdata = fdata->next) {
1042 fdata->flags.visited = 0;
1044 g_slist_free(fdata->pfd);
1047 free_data_sources(fdata); /* release data source list */
1051 /* We're done filtering the packets; destroy the progress bar. */
1052 destroy_progress_dlg(progbar);
1054 /* Unfreeze the packet list. */
1055 gtk_clist_thaw(GTK_CLIST(packet_list));
1057 if (selected_row != -1) {
1058 /* The frame that was selected passed the filter; select it, make it
1059 the focus row, and make it visible. */
1060 set_selected_row(selected_row);
1061 finfo_selected = NULL;
1063 /* The selected frame didn't pass the filter; make the first frame
1064 the current frame, and leave it unselected. */
1065 unselect_packet(cf);
1066 cf->current_frame = cf->first_displayed;
1071 print_packets(capture_file *cf, print_args_t *print_args)
1077 guint32 progbar_quantum;
1078 guint32 progbar_nextstep;
1081 gint *col_widths = NULL;
1083 gboolean print_separator;
1084 char *line_buf = NULL;
1085 int line_buf_len = 256;
1089 epan_dissect_t *edt = NULL;
1091 cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
1092 if (cf->print_fh == NULL)
1093 return FALSE; /* attempt to open destination failed */
1095 print_preamble(cf->print_fh, print_args->format);
1097 if (print_args->print_summary) {
1098 /* We're printing packet summaries. Allocate the line buffer at
1099 its initial length. */
1100 line_buf = g_malloc(line_buf_len + 1);
1102 /* Find the widths for each of the columns - maximum of the
1103 width of the title and the width of the data - and print
1104 the column titles. */
1105 col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1108 for (i = 0; i < cf->cinfo.num_cols; i++) {
1109 /* Don't pad the last column. */
1110 if (i == cf->cinfo.num_cols - 1)
1113 col_widths[i] = strlen(cf->cinfo.col_title[i]);
1114 data_width = get_column_char_width(get_column_format(i));
1115 if (data_width > col_widths[i])
1116 col_widths[i] = data_width;
1119 /* Find the length of the string for this column. */
1120 column_len = strlen(cf->cinfo.col_title[i]);
1121 if (col_widths[i] > column_len)
1122 column_len = col_widths[i];
1124 /* Make sure there's room in the line buffer for the column; if not,
1125 double its length. */
1126 line_len += column_len + 1; /* "+1" for space or \n */
1127 if (line_len > line_buf_len) {
1129 line_buf = g_realloc(line_buf, line_buf_len + 1);
1132 /* Right-justify the packet number column. */
1133 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1134 sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_title[i]);
1136 sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
1138 if (i == cf->cinfo.num_cols - 1)
1144 print_line(cf->print_fh, print_args->format, line_buf);
1147 print_separator = FALSE;
1149 /* Update the progress bar when it gets to this value. */
1150 progbar_nextstep = 0;
1151 /* When we reach the value that triggers a progress bar update,
1152 bump that value by this amount. */
1153 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1154 /* Count of packets at which we've looked. */
1158 progbar = create_progress_dlg("Printing", "Stop", &stop_flag);
1160 /* Iterate through the list of packets, printing the packets that
1161 were selected by the current display filter. */
1162 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1163 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1164 when we update it, we have to run the GTK+ main loop to get it
1165 to repaint what's pending, and doing so may involve an "ioctl()"
1166 to see if there's any pending input from an X server, and doing
1167 that for every packet can be costly, especially on a big file. */
1168 if (count >= progbar_nextstep) {
1169 /* let's not divide by zero. I should never be started
1170 * with count == 0, so let's assert that
1172 g_assert(cf->count > 0);
1174 update_progress_dlg(progbar, (gfloat) count / cf->count);
1176 progbar_nextstep += progbar_quantum;
1180 /* Well, the user decided to abort the printing. Just stop.
1182 XXX - note that what got generated before they did that
1183 will get printed, as we're piping to a print program; we'd
1184 have to write to a file and then hand that to the print
1185 program to make it actually not print anything. */
1190 /* Check to see if we are suppressing unmarked packets, if so,
1191 * suppress them and then proceed to check for visibility.
1193 if (((print_args->suppress_unmarked && fdata->flags.marked ) ||
1194 !(print_args->suppress_unmarked)) && fdata->flags.passed_dfilter) {
1195 /* XXX - do something with "err" */
1196 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1197 cf->pd, fdata->cap_len, &err);
1198 if (print_args->print_summary) {
1199 /* Fill in the column information, but don't bother creating
1200 the logical protocol tree. */
1201 edt = epan_dissect_new(FALSE, FALSE);
1202 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
1203 epan_dissect_fill_in_columns(edt);
1206 for (i = 0; i < cf->cinfo.num_cols; i++) {
1207 /* Find the length of the string for this column. */
1208 column_len = strlen(cf->cinfo.col_data[i]);
1209 if (col_widths[i] > column_len)
1210 column_len = col_widths[i];
1212 /* Make sure there's room in the line buffer for the column; if not,
1213 double its length. */
1214 line_len += column_len + 1; /* "+1" for space or \n */
1215 if (line_len > line_buf_len) {
1217 line_buf = g_realloc(line_buf, line_buf_len + 1);
1220 /* Right-justify the packet number column. */
1221 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1222 sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_data[i]);
1224 sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
1226 if (i == cf->cinfo.num_cols - 1)
1232 print_line(cf->print_fh, print_args->format, line_buf);
1234 if (print_separator)
1235 print_line(cf->print_fh, print_args->format, "\n");
1237 /* Create the logical protocol tree, complete with the display
1238 representation of the items; we don't need the columns here,
1240 edt = epan_dissect_new(TRUE, TRUE);
1241 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
1243 /* Print the information in that tree. */
1244 proto_tree_print(print_args, (GNode *)edt->tree,
1245 fdata, cf->print_fh);
1247 if (print_args->print_hex) {
1248 /* Print the full packet data as hex. */
1249 print_hex_data(cf->print_fh, print_args->format, fdata);
1252 /* Print a blank line if we print anything after this. */
1253 print_separator = TRUE;
1255 epan_dissect_free(edt);
1259 /* We're done printing the packets; destroy the progress bar. */
1260 destroy_progress_dlg(progbar);
1262 if (col_widths != NULL)
1264 if (line_buf != NULL)
1267 print_finale(cf->print_fh, print_args->format);
1269 close_print_dest(print_args->to_file, cf->print_fh);
1271 cf->print_fh = NULL;
1276 /* Scan through the packet list and change all columns that use the
1277 "command-line-specified" time stamp format to use the current
1278 value of that format. */
1280 change_time_formats(capture_file *cf)
1285 guint32 progbar_quantum;
1286 guint32 progbar_nextstep;
1292 /* Are there any columns with time stamps in the "command-line-specified"
1295 XXX - we have to force the "column is writable" flag on, as it
1296 might be off from the last frame that was dissected. */
1297 col_set_writable(&cf->cinfo, TRUE);
1298 if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
1299 /* No, there aren't any columns in that format, so we have no work
1304 /* Freeze the packet list while we redo it, so we don't get any
1305 screen updates while it happens. */
1308 /* Update the progress bar when it gets to this value. */
1309 progbar_nextstep = 0;
1310 /* When we reach the value that triggers a progress bar update,
1311 bump that value by this amount. */
1312 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1313 /* Count of packets at which we've looked. */
1317 progbar = create_progress_dlg("Changing time display", "Stop", &stop_flag);
1319 /* Iterate through the list of packets, checking whether the packet
1320 is in a row of the summary list and, if so, whether there are
1321 any columns that show the time in the "command-line-specified"
1322 format and, if so, update that row. */
1323 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1324 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1325 when we update it, we have to run the GTK+ main loop to get it
1326 to repaint what's pending, and doing so may involve an "ioctl()"
1327 to see if there's any pending input from an X server, and doing
1328 that for every packet can be costly, especially on a big file. */
1329 if (count >= progbar_nextstep) {
1330 /* let's not divide by zero. I should never be started
1331 * with count == 0, so let's assert that
1333 g_assert(cf->count > 0);
1335 update_progress_dlg(progbar, (gfloat) count / cf->count);
1337 progbar_nextstep += progbar_quantum;
1341 /* Well, the user decided to abort the redisplay. Just stop.
1343 XXX - this leaves the time field in the old format in
1344 frames we haven't yet processed. So it goes; should we
1345 simply not offer them the option of stopping? */
1351 /* Find what row this packet is in. */
1352 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1355 /* This packet is in the summary list, on row "row". */
1357 for (i = 0; i < cf->cinfo.num_cols; i++) {
1358 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1359 /* This is one of the columns that shows the time in
1360 "command-line-specified" format; update it. */
1361 cf->cinfo.col_buf[i][0] = '\0';
1362 col_set_cls_time(fdata, &cf->cinfo, i);
1363 gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
1364 cf->cinfo.col_data[i]);
1370 /* We're done redisplaying the packets; destroy the progress bar. */
1371 destroy_progress_dlg(progbar);
1373 /* Set the column widths of those columns that show the time in
1374 "command-line-specified" format. */
1375 pl_style = gtk_widget_get_style(packet_list);
1376 for (i = 0; i < cf->cinfo.num_cols; i++) {
1377 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1378 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1379 gdk_string_width(pl_style->font, get_column_longest_string(COL_CLS_TIME)));
1383 /* Unfreeze the packet list. */
1388 find_packet(capture_file *cf, dfilter_t *sfcode)
1390 frame_data *start_fd;
1392 frame_data *new_fd = NULL;
1395 guint32 progbar_quantum;
1396 guint32 progbar_nextstep;
1399 gboolean frame_matched;
1401 epan_dissect_t *edt;
1403 start_fd = cf->current_frame;
1404 if (start_fd != NULL) {
1405 /* Iterate through the list of packets, starting at the packet we've
1406 picked, calling a routine to run the filter on the packet, see if
1407 it matches, and stop if so. */
1411 /* Update the progress bar when it gets to this value. */
1412 progbar_nextstep = 0;
1413 /* When we reach the value that triggers a progress bar update,
1414 bump that value by this amount. */
1415 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1418 progbar = create_progress_dlg("Searching", "Cancel", &stop_flag);
1422 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1423 when we update it, we have to run the GTK+ main loop to get it
1424 to repaint what's pending, and doing so may involve an "ioctl()"
1425 to see if there's any pending input from an X server, and doing
1426 that for every packet can be costly, especially on a big file. */
1427 if (count >= progbar_nextstep) {
1428 /* let's not divide by zero. I should never be started
1429 * with count == 0, so let's assert that
1431 g_assert(cf->count > 0);
1433 update_progress_dlg(progbar, (gfloat) count / cf->count);
1435 progbar_nextstep += progbar_quantum;
1439 /* Well, the user decided to abort the search. Go back to the
1440 frame where we started. */
1445 /* Go past the current frame. */
1446 if (cf->sbackward) {
1447 /* Go on to the previous frame. */
1448 fdata = fdata->prev;
1450 fdata = cf->plist_end; /* wrap around */
1452 /* Go on to the next frame. */
1453 fdata = fdata->next;
1455 fdata = cf->plist; /* wrap around */
1460 /* Is this packet in the display? */
1461 if (fdata->flags.passed_dfilter) {
1462 /* Yes. Does it match the search filter? */
1463 /* XXX - do something with "err" */
1464 wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
1465 cf->pd, fdata->cap_len, &err);
1466 edt = epan_dissect_new(TRUE, FALSE);
1467 epan_dissect_prime_dfilter(edt, sfcode);
1468 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
1469 frame_matched = dfilter_apply_edt(sfcode, edt);
1470 epan_dissect_free(edt);
1471 if (frame_matched) {
1473 break; /* found it! */
1477 if (fdata == start_fd) {
1478 /* We're back to the frame we were on originally, and that frame
1479 doesn't match the search filter. The search failed. */
1484 /* We're done scanning the packets; destroy the progress bar. */
1485 destroy_progress_dlg(progbar);
1488 if (new_fd != NULL) {
1489 /* We found a frame. Find what row it's in. */
1490 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), new_fd);
1491 g_assert(row != -1);
1493 /* Select that row, make it the focus row, and make it visible. */
1494 set_selected_row(row);
1495 return TRUE; /* success */
1497 return FALSE; /* failure */
1501 goto_frame(capture_file *cf, guint fnumber)
1506 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
1510 return NO_SUCH_FRAME; /* we didn't find that frame */
1511 if (!fdata->flags.passed_dfilter)
1512 return FRAME_NOT_DISPLAYED; /* the frame with that number isn't displayed */
1514 /* We found that frame, and it's currently being displayed.
1515 Find what row it's in. */
1516 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1517 g_assert(row != -1);
1519 /* Select that row, make it the focus row, and make it visible. */
1520 set_selected_row(row);
1524 /* Select the packet on a given row. */
1526 select_packet(capture_file *cf, int row)
1531 /* Get the frame data struct pointer for this frame */
1532 fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
1534 if (fdata == NULL) {
1535 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
1536 the first entry is added to it by "real_insert_row()", that row
1537 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
1538 our version and the vanilla GTK+ version).
1540 This means that a "select-row" signal is emitted; this causes
1541 "packet_list_select_cb()" to be called, which causes "select_packet()"
1544 "select_packet()" fetches, above, the data associated with the
1545 row that was selected; however, as "gtk_clist_append()", which
1546 called "real_insert_row()", hasn't yet returned, we haven't yet
1547 associated any data with that row, so we get back a null pointer.
1549 We can't assume that there's only one frame in the frame list,
1550 either, as we may be filtering the display.
1552 We therefore assume that, if "row" is 0, i.e. the first row
1553 is being selected, and "cf->first_displayed" equals
1554 "cf->last_displayed", i.e. there's only one frame being
1555 displayed, that frame is the frame we want.
1557 This means we have to set "cf->first_displayed" and
1558 "cf->last_displayed" before adding the row to the
1559 GtkCList; see the comment in "add_packet_to_packet_list()". */
1561 if (row == 0 && cf->first_displayed == cf->last_displayed)
1562 fdata = cf->first_displayed;
1565 /* Record that this frame is the current frame. */
1566 cf->current_frame = fdata;
1568 /* Get the data in that frame. */
1569 /* XXX - do something with "err" */
1570 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1571 cf->pd, fdata->cap_len, &err);
1573 /* Create the logical protocol tree. */
1574 if (cf->edt != NULL) {
1575 epan_dissect_free(cf->edt);
1578 /* We don't need the columns here. */
1579 cf->edt = epan_dissect_new(TRUE, TRUE);
1580 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
1583 /* Display the GUI protocol tree and hex dump.
1584 XXX - why do we dump core if we call "proto_tree_draw()"
1585 before calling "add_byte_views()"? */
1586 add_byte_views(cf->current_frame, cf->edt->tree, tree_view,
1588 proto_tree_draw(cf->edt->tree, tree_view);
1590 /* A packet is selected. */
1591 set_menus_for_selected_packet(TRUE);
1594 /* Unselect the selected packet, if any. */
1596 unselect_packet(capture_file *cf)
1598 /* Destroy the epan_dissect_t for the unselected packet. */
1599 if (cf->edt != NULL) {
1600 epan_dissect_free(cf->edt);
1604 /* Clear out the display of that packet. */
1605 clear_tree_and_hex_views();
1607 /* No packet is selected. */
1608 set_menus_for_selected_packet(FALSE);
1610 /* No protocol tree means no selected field. */
1614 /* Set the selected row and the focus row of the packet list to the specified
1615 row, and make it visible if it's not currently visible. */
1617 set_selected_row(int row)
1619 if (gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) != GTK_VISIBILITY_FULL)
1620 gtk_clist_moveto(GTK_CLIST(packet_list), row, -1, 0.0, 0.0);
1622 /* XXX - why is there no "gtk_clist_set_focus_row()", so that we
1623 can make the row for the frame we found the focus row?
1627 http://www.gnome.org/mailing-lists/archives/gtk-list/2000-January/0038.shtml
1630 GTK_CLIST(packet_list)->focus_row = row;
1632 gtk_clist_select_row(GTK_CLIST(packet_list), row, -1);
1635 /* Unset the selected protocol tree field, if any. */
1637 unselect_field(void)
1639 statusbar_pop_field_msg();
1640 finfo_selected = NULL;
1641 set_menus_for_selected_tree_row(FALSE);
1645 * Mark a particular frame.
1648 mark_frame(capture_file *cf, frame_data *frame)
1650 frame->flags.marked = TRUE;
1655 * Unmark a particular frame.
1658 unmark_frame(capture_file *cf, frame_data *frame)
1660 frame->flags.marked = FALSE;
1665 freeze_clist(capture_file *cf)
1669 /* Make the column sizes static, so they don't adjust while
1670 we're reading the capture file (freezing the clist doesn't
1671 seem to suffice). */
1672 for (i = 0; i < cf->cinfo.num_cols; i++)
1673 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1674 gtk_clist_freeze(GTK_CLIST(packet_list));
1678 thaw_clist(capture_file *cf)
1682 for (i = 0; i < cf->cinfo.num_cols; i++) {
1683 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1684 /* Set this column's width to the appropriate value. */
1685 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1686 cf->cinfo.col_width[i]);
1688 /* Make this column's size dynamic, so that it adjusts to the
1689 appropriate size. */
1690 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1693 gtk_clist_thaw(GTK_CLIST(packet_list));
1695 /* Hopefully, the columns have now gotten their appropriate sizes;
1696 make them resizeable - a column that auto-resizes cannot be
1697 resized by the user, and *vice versa*. */
1698 for (i = 0; i < cf->cinfo.num_cols; i++)
1699 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1703 save_cap_file(char *fname, capture_file *cf, gboolean save_filtered, gboolean save_marked,
1706 gchar *from_filename;
1707 gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
1713 struct wtap_pkthdr hdr;
1714 union wtap_pseudo_header pseudo_header;
1717 name_ptr = get_basename(fname);
1718 msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
1719 save_msg = g_malloc(msg_len);
1720 snprintf(save_msg, msg_len, save_fmt, name_ptr);
1721 statusbar_push_file_msg(save_msg);
1724 if (!save_filtered && !save_marked && save_format == cf->cd_t) {
1725 /* We're not filtering packets, and we're saving it in the format
1726 it's already in, so we can just move or copy the raw data. */
1728 /* In this branch, we set "err" only if we get an error, so we
1729 must first clear it. */
1731 if (cf->is_tempfile) {
1732 /* The file being saved is a temporary file from a live
1733 capture, so it doesn't need to stay around under that name;
1734 first, try renaming the capture buffer file to the new name. */
1736 if (rename(cf->filename, fname) == 0) {
1737 /* That succeeded - there's no need to copy the source file. */
1738 from_filename = NULL;
1741 if (errno == EXDEV) {
1742 /* They're on different file systems, so we have to copy the
1745 from_filename = cf->filename;
1747 /* The rename failed, but not because they're on different
1748 file systems - put up an error message. (Or should we
1749 just punt and try to copy? The only reason why I'd
1750 expect the rename to fail and the copy to succeed would
1751 be if we didn't have permission to remove the file from
1752 the temporary directory, and that might be fixable - but
1753 is it worth requiring the user to go off and fix it?) */
1755 simple_dialog(ESD_TYPE_CRIT, NULL,
1756 file_rename_error_message(err), fname);
1762 from_filename = cf->filename;
1765 /* It's a permanent file, so we should copy it, and not remove the
1768 from_filename = cf->filename;
1771 /* Check that the from file is not the same as to file */
1775 /* Copy the file, if we haven't moved it. */
1776 if (strncmp(from_filename, fname, sizeof(cf->filename)) == 0) {
1777 simple_dialog(ESD_TYPE_WARN, NULL,
1778 "Can't save over current capture file: %s!", from_filename);
1782 if (!copy_binary_file(from_filename, fname)) {
1787 /* Either we're filtering packets, or we're saving in a different
1788 format; we can't do that by copying or moving the capture file,
1789 we have to do it by writing the packets out in Wiretap. */
1790 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
1792 simple_dialog(ESD_TYPE_CRIT, NULL,
1793 file_open_error_message(err, TRUE), fname);
1797 /* XXX - have a way to save only the packets currently selected by
1798 the display filter or the marked ones.
1800 If we do that, should we make that file the current file? If so,
1801 it means we can no longer get at the other packets. What does
1803 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1804 /* XXX - do a progress bar */
1805 if ((!save_filtered && !save_marked) ||
1806 (save_filtered && fdata->flags.passed_dfilter && !save_marked) ||
1807 (save_marked && fdata->flags.marked && !save_filtered) ||
1808 (save_filtered && save_marked && fdata->flags.passed_dfilter &&
1809 fdata->flags.marked)) {
1811 - we're saving all frames, or
1812 - we're saving filtered frames and this one passed the display filter or
1813 - we're saving marked frames (and it has been marked) or
1814 - we're saving filtered _and_ marked frames,
1816 hdr.ts.tv_sec = fdata->abs_secs;
1817 hdr.ts.tv_usec = fdata->abs_usecs;
1818 hdr.caplen = fdata->cap_len;
1819 hdr.len = fdata->pkt_len;
1820 hdr.pkt_encap = fdata->lnk_t;
1821 if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1822 pd, fdata->cap_len, &err)) {
1823 simple_dialog(ESD_TYPE_CRIT, NULL,
1824 file_read_error_message(err), cf->filename);
1825 wtap_dump_close(pdh, &err);
1829 if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
1830 simple_dialog(ESD_TYPE_CRIT, NULL,
1831 file_write_error_message(err), fname);
1832 wtap_dump_close(pdh, &err);
1838 if (!wtap_dump_close(pdh, &err)) {
1839 simple_dialog(ESD_TYPE_WARN, NULL,
1840 file_close_error_message(err), fname);
1847 /* Pop the "Saving:" message off the status bar. */
1848 statusbar_pop_file_msg();
1850 if (!save_filtered && !save_marked) {
1851 /* We saved the entire capture, not just some packets from it.
1852 Open and read the file we saved it to.
1854 XXX - this is somewhat of a waste; we already have the
1855 packets, all this gets us is updated file type information
1856 (which we could just stuff into "cf"), and having the new
1857 file be the one we have opened and from which we're reading
1858 the data, and it means we have to spend time opening and
1859 reading the file, which could be a significant amount of
1860 time if the file is large. */
1861 cf->user_saved = TRUE;
1863 if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
1864 /* XXX - report errors if this fails? */
1865 switch (read_cap_file(cf, &err)) {
1869 /* Just because we got an error, that doesn't mean we were unable
1870 to read any of the file; we handle what we could get from the
1875 /* The user bailed out of re-reading the capture file; the
1876 capture file has been closed - just return (without
1877 changing any menu settings; "close_cap_file()" set them
1878 correctly for the "no capture file open" state). */
1881 set_menus_for_unsaved_capture_file(FALSE);
1889 file_open_error_message(int err, gboolean for_writing)
1892 static char errmsg_errno[1024+1];
1896 case WTAP_ERR_NOT_REGULAR_FILE:
1897 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1900 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1901 case WTAP_ERR_UNSUPPORTED:
1902 /* Seen only when opening a capture file for reading. */
1903 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1906 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1907 /* Seen only when opening a capture file for writing. */
1908 errmsg = "Ethereal does not support writing capture files in that format.";
1911 case WTAP_ERR_UNSUPPORTED_ENCAP:
1912 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1914 errmsg = "Ethereal cannot save this capture in that format.";
1916 errmsg = "The file \"%s\" is a capture for a network type that Ethereal doesn't support.";
1919 case WTAP_ERR_BAD_RECORD:
1920 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1923 case WTAP_ERR_CANT_OPEN:
1925 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1927 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1930 case WTAP_ERR_SHORT_READ:
1931 errmsg = "The file \"%s\" appears to have been cut short"
1932 " in the middle of a packet or other data.";
1935 case WTAP_ERR_SHORT_WRITE:
1936 errmsg = "A full header couldn't be written to the file \"%s\".";
1941 errmsg = "The path to the file \"%s\" does not exist.";
1943 errmsg = "The file \"%s\" does not exist.";
1948 errmsg = "You do not have permission to create or write to the file \"%s\".";
1950 errmsg = "You do not have permission to read the file \"%s\".";
1954 errmsg = "\"%s\" is a directory (folder), not a file.";
1958 snprintf(errmsg_errno, sizeof(errmsg_errno),
1959 "The file \"%%s\" could not be opened: %s.",
1960 wtap_strerror(err));
1961 errmsg = errmsg_errno;
1968 file_rename_error_message(int err)
1971 static char errmsg_errno[1024+1];
1976 errmsg = "The path to the file \"%s\" does not exist.";
1980 errmsg = "You do not have permission to move the capture file to \"%s\".";
1984 snprintf(errmsg_errno, sizeof(errmsg_errno),
1985 "The file \"%%s\" could not be moved: %s.",
1986 wtap_strerror(err));
1987 errmsg = errmsg_errno;
1994 file_read_error_message(int err)
1996 static char errmsg_errno[1024+1];
1998 snprintf(errmsg_errno, sizeof(errmsg_errno),
1999 "An error occurred while reading from the file \"%%s\": %s.",
2000 wtap_strerror(err));
2001 return errmsg_errno;
2005 file_write_error_message(int err)
2008 static char errmsg_errno[1024+1];
2013 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
2018 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
2023 snprintf(errmsg_errno, sizeof(errmsg_errno),
2024 "An error occurred while writing to the file \"%%s\": %s.",
2025 wtap_strerror(err));
2026 errmsg = errmsg_errno;
2032 /* Check for write errors - if the file is being written to an NFS server,
2033 a write error may not show up until the file is closed, as NFS clients
2034 might not send writes to the server until the "write()" call finishes,
2035 so that the write may fail on the server but the "write()" may succeed. */
2037 file_close_error_message(int err)
2040 static char errmsg_errno[1024+1];
2044 case WTAP_ERR_CANT_CLOSE:
2045 errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
2048 case WTAP_ERR_SHORT_WRITE:
2049 errmsg = "Not all the packets could be written to the file \"%s\".";
2053 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
2058 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
2063 snprintf(errmsg_errno, sizeof(errmsg_errno),
2064 "An error occurred while closing the file \"%%s\": %s.",
2065 wtap_strerror(err));
2066 errmsg = errmsg_errno;
2073 /* Copies a file in binary mode, for those operating systems that care about
2075 * Returns TRUE on success, FALSE on failure. If a failure, it also
2076 * displays a simple dialog window with the error message.
2079 copy_binary_file(char *from_filename, char *to_filename)
2081 int from_fd, to_fd, nread, nwritten, err;
2082 guint8 pd[65536]; /* XXX - Hmm, 64K here, 64K in save_cap_file(),
2083 perhaps we should make just one 64K buffer. */
2085 /* Copy the raw bytes of the file. */
2086 from_fd = open(from_filename, O_RDONLY | O_BINARY);
2089 simple_dialog(ESD_TYPE_CRIT, NULL,
2090 file_open_error_message(err, TRUE), from_filename);
2094 /* Use open() instead of creat() so that we can pass the O_BINARY
2095 flag, which is relevant on Win32; it appears that "creat()"
2096 may open the file in text mode, not binary mode, but we want
2097 to copy the raw bytes of the file, so we need the output file
2098 to be open in binary mode. */
2099 to_fd = open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
2102 simple_dialog(ESD_TYPE_CRIT, NULL,
2103 file_open_error_message(err, TRUE), to_filename);
2108 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
2109 nwritten = write(to_fd, pd, nread);
2110 if (nwritten < nread) {
2114 err = WTAP_ERR_SHORT_WRITE;
2115 simple_dialog(ESD_TYPE_CRIT, NULL,
2116 file_write_error_message(err), to_filename);
2124 simple_dialog(ESD_TYPE_CRIT, NULL,
2125 file_read_error_message(err), from_filename);
2131 if (close(to_fd) < 0) {
2133 simple_dialog(ESD_TYPE_CRIT, NULL,
2134 file_close_error_message(err), to_filename);