4 * $Id: file.c,v 1.384 2004/05/27 21:48:10 ulfl 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.
25 /* With MSVC and a libethereal.dll this file needs to import some variables
26 in a special way. Therefore _NEED_VAR_IMPORT_ is defined. */
27 #define _NEED_VAR_IMPORT_
50 #ifdef HAVE_SYS_STAT_H
58 #ifdef NEED_SNPRINTF_H
59 # include "snprintf.h"
62 #ifdef NEED_STRERROR_H
66 #include <epan/epan.h>
67 #include <epan/filesystem.h>
71 #include <epan/packet.h>
77 #include "alert_box.h"
78 #include "simple_dialog.h"
79 #include "progress_dlg.h"
81 #include "statusbar.h"
83 #include <epan/dfilter/dfilter.h>
84 #include <epan/conversation.h>
86 #include <epan/epan_dissect.h>
88 #include "tap_dfilter_dlg.h"
89 #include "packet-data.h"
92 gboolean auto_scroll_live;
95 static guint32 firstsec, firstusec;
96 static guint32 prevsec, prevusec;
97 static guint32 cum_bytes = 0;
99 static void read_packet(capture_file *cf, long offset);
101 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
102 gboolean refilter, gboolean redissect);
104 static gboolean match_protocol_tree(capture_file *cf, frame_data *fdata,
106 static void match_subtree_text(proto_node *node, gpointer data);
107 static gboolean match_summary_line(capture_file *cf, frame_data *fdata,
109 static gboolean match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
111 static gboolean match_ascii(capture_file *cf, frame_data *fdata,
113 static gboolean match_unicode(capture_file *cf, frame_data *fdata,
115 static gboolean match_binary(capture_file *cf, frame_data *fdata,
117 static gboolean match_dfilter(capture_file *cf, frame_data *fdata,
119 static gboolean find_packet(capture_file *cf,
120 gboolean (*match_function)(capture_file *, frame_data *, void *),
123 static void cf_open_failure_alert_box(const char *filename, int err,
124 gchar *err_info, gboolean for_writing,
126 static char *file_rename_error_message(int err);
127 static void cf_write_failure_alert_box(const char *filename, int err);
128 static void cf_close_failure_alert_box(const char *filename, int err);
129 static gboolean copy_binary_file(char *from_filename, char *to_filename);
131 /* Update the progress bar this many times when reading a file. */
132 #define N_PROGBAR_UPDATES 100
134 /* Number of "frame_data" structures per memory chunk.
135 XXX - is this the right number? */
136 #define FRAME_DATA_CHUNK_SIZE 1024
140 cf_open(char *fname, gboolean is_tempfile, capture_file *cf)
148 wth = wtap_open_offline(fname, &err, &err_info, TRUE);
152 /* Find the size of the file. */
154 if (fstat(fd, &cf_stat) < 0) {
160 /* The open succeeded. Close whatever capture file we had open,
161 and fill in the information for this file. */
164 /* Initialize all data structures used for dissection. */
167 /* We're about to start reading the file. */
168 cf->state = FILE_READ_IN_PROGRESS;
172 cf->f_len = cf_stat.st_size;
174 /* Set the file name because we need it to set the follow stream filter.
175 XXX - is that still true? We need it for other reasons, though,
177 cf->filename = g_strdup(fname);
179 /* Indicate whether it's a permanent or temporary file. */
180 cf->is_tempfile = is_tempfile;
182 /* If it's a temporary capture buffer file, mark it as not saved. */
183 cf->user_saved = !is_tempfile;
185 cf->cd_t = wtap_file_type(cf->wth);
187 cf->displayed_count = 0;
188 cf->marked_count = 0;
189 cf->drops_known = FALSE;
193 cf->snap = wtap_snapshot_length(cf->wth);
195 /* Snapshot length not known. */
196 cf->has_snap = FALSE;
197 cf->snap = WTAP_MAX_PACKET_SIZE;
200 firstsec = 0, firstusec = 0;
201 prevsec = 0, prevusec = 0;
203 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
205 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
207 g_assert(cf->plist_chunk);
212 cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
216 /* Reset everything to a pristine state */
218 cf_close(capture_file *cf)
220 /* Die if we're in the middle of reading a file. */
221 g_assert(cf->state != FILE_READ_IN_PROGRESS);
223 /* Destroy all windows, which refer to the
224 capture file we're closing. */
225 destroy_cfile_wins();
231 /* We have no file open... */
232 if (cf->filename != NULL) {
233 /* If it's a temporary file, remove it. */
235 unlink(cf->filename);
236 g_free(cf->filename);
239 /* ...which means we have nothing to save. */
240 cf->user_saved = FALSE;
242 if (cf->plist_chunk != NULL) {
243 g_mem_chunk_destroy(cf->plist_chunk);
244 cf->plist_chunk = NULL;
246 if (cf->rfcode != NULL) {
247 dfilter_free(cf->rfcode);
251 cf->plist_end = NULL;
252 unselect_packet(cf); /* nothing to select */
253 cf->first_displayed = NULL;
254 cf->last_displayed = NULL;
256 /* No frame selected, no field in that frame selected. */
257 cf->current_frame = NULL;
258 cf->finfo_selected = NULL;
260 /* Clear the packet list. */
261 packet_list_freeze();
270 /* Clear any file-related status bar messages.
271 XXX - should be "clear *ALL* file-related status bar messages;
272 will there ever be more than one on the stack? */
273 statusbar_pop_file_msg();
275 /* Restore the standard title bar message. */
276 set_main_window_name("The Ethereal Network Analyzer");
278 /* Disable all menu items that make sense only if you have a capture. */
279 set_menus_for_capture_file(FALSE);
280 set_menus_for_unsaved_capture_file(FALSE);
281 set_menus_for_captured_packets(FALSE);
282 set_menus_for_selected_packet(cf);
283 set_menus_for_capture_in_progress(FALSE);
284 set_menus_for_selected_tree_row(cf);
286 reset_tap_listeners();
288 /* We have no file open. */
289 cf->state = FILE_CLOSED;
292 /* Set the file name in the status line, in the name for the main window,
293 and in the name for the main window's icon. */
295 set_display_filename(capture_file *cf)
299 static const gchar done_fmt_nodrops[] = " File: %s %s %02u:%02u:%02u";
300 static const gchar done_fmt_drops[] = " File: %s %s %02u:%02u:%02u Drops: %u";
302 gchar *win_name_fmt = "%s - Ethereal";
306 name_ptr = cf_get_display_name(cf);
308 if (!cf->is_tempfile) {
309 /* Add this filename to the list of recent files in the "Recent Files" submenu */
310 add_menu_recent_capture_file(cf->filename);
313 if (cf->f_len/1024/1024 > 10) {
314 size_str = g_strdup_printf("%ld MB", cf->f_len/1024/1024);
315 } else if (cf->f_len/1024 > 10) {
316 size_str = g_strdup_printf("%ld KB", cf->f_len/1024);
318 size_str = g_strdup_printf("%ld bytes", cf->f_len);
321 if (cf->drops_known) {
322 done_msg = g_strdup_printf(done_fmt_drops, name_ptr, size_str,
323 cf->esec/3600, cf->esec%3600/60, cf->esec%60, cf->drops);
325 done_msg = g_strdup_printf(done_fmt_nodrops, name_ptr, size_str,
326 cf->esec/3600, cf->esec%3600/60, cf->esec%60);
328 statusbar_push_file_msg(done_msg);
331 msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
332 win_name = g_malloc(msg_len);
333 snprintf(win_name, msg_len, win_name_fmt, name_ptr);
334 set_main_window_name(win_name);
339 cf_read(capture_file *cf)
343 gchar *name_ptr, *load_msg, *load_fmt = "%s";
345 char errmsg_errno[1024+1];
346 gchar err_str[2048+1];
348 progdlg_t *progbar = NULL;
351 * XXX - should be "off_t", but Wiretap would need more work to handle
352 * the full size of "off_t" on platforms where it's more than a "long"
360 gchar status_str[100];
361 int progbar_nextstep;
365 reset_tap_listeners();
366 tap_dfilter_dlg_update();
367 name_ptr = get_basename(cf->filename);
369 load_msg = g_strdup_printf(" Loading: %s", name_ptr);
370 statusbar_push_file_msg(load_msg);
373 load_msg = g_strdup_printf(load_fmt, name_ptr);
375 /* Update the progress bar when it gets to this value. */
376 progbar_nextstep = 0;
377 /* When we reach the value that triggers a progress bar update,
378 bump that value by this amount. */
379 progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
385 packet_list_freeze();
388 g_get_current_time(&start_time);
390 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
391 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
392 when we update it, we have to run the GTK+ main loop to get it
393 to repaint what's pending, and doing so may involve an "ioctl()"
394 to see if there's any pending input from an X server, and doing
395 that for every packet can be costly, especially on a big file. */
396 if (data_offset >= progbar_nextstep) {
397 file_pos = lseek(cf->filed, 0, SEEK_CUR);
398 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
399 if (prog_val > 1.0) {
400 /* The file probably grew while we were reading it.
401 Update "cf->f_len", and try again. */
402 fd = wtap_fd(cf->wth);
403 if (fstat(fd, &cf_stat) >= 0) {
404 cf->f_len = cf_stat.st_size;
405 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
407 /* If it's still > 1, either the "fstat()" failed (in which
408 case there's not much we can do about it), or the file
409 *shrank* (in which case there's not much we can do about
410 it); just clip the progress value at 1.0. */
414 if (progbar == NULL) {
415 /* Create the progress bar if necessary */
416 progbar = delayed_create_progress_dlg("Loading", load_msg,
417 &stop_flag, &start_time, prog_val);
421 if (progbar != NULL) {
422 g_snprintf(status_str, sizeof(status_str),
423 "%luKB of %luKB", file_pos / 1024, cf->f_len / 1024);
424 update_progress_dlg(progbar, prog_val, status_str);
426 progbar_nextstep += progbar_quantum;
430 /* Well, the user decided to abort the read. Destroy the progress
431 bar, close the capture file, and return READ_ABORTED so our caller
432 can do whatever is appropriate when that happens. */
433 destroy_progress_dlg(progbar);
434 cf->state = FILE_READ_ABORTED; /* so that we're allowed to close it */
435 packet_list_thaw(); /* undo our freeze */
437 return (READ_ABORTED);
439 read_packet(cf, data_offset);
442 /* We're done reading the file; destroy the progress bar if it was created. */
446 destroy_progress_dlg(progbar);
448 /* We're done reading sequentially through the file. */
449 cf->state = FILE_READ_DONE;
451 /* Close the sequential I/O side, to free up memory it requires. */
452 wtap_sequential_close(cf->wth);
454 /* Allow the protocol dissectors to free up memory that they
455 * don't need after the sequential run-through of the packets. */
456 postseq_cleanup_all_protocols();
458 /* Set the file encapsulation type now; we don't know what it is until
459 we've looked at all the packets, as we don't know until then whether
460 there's more than one type (and thus whether it's
461 WTAP_ENCAP_PER_PACKET). */
462 cf->lnk_t = wtap_file_encap(cf->wth);
464 cf->current_frame = cf->first_displayed;
467 statusbar_pop_file_msg();
468 set_display_filename(cf);
470 /* Enable menu items that make sense if you have a capture file you've
472 set_menus_for_capture_file(TRUE);
473 set_menus_for_unsaved_capture_file(!cf->user_saved);
475 /* Enable menu items that make sense if you have some captured packets. */
476 set_menus_for_captured_packets(TRUE);
478 /* If we have any displayed packets to select, select the first of those
479 packets by making the first row the selected row. */
480 if (cf->first_displayed != NULL)
481 packet_list_select_row(0);
484 /* Put up a message box noting that the read failed somewhere along
485 the line. Don't throw out the stuff we managed to read, though,
489 case WTAP_ERR_UNSUPPORTED_ENCAP:
490 errmsg = "The capture file is for a network type that Ethereal doesn't support.";
493 case WTAP_ERR_CANT_READ:
494 errmsg = "An attempt to read from the file failed for"
495 " some unknown reason.";
498 case WTAP_ERR_SHORT_READ:
499 errmsg = "The capture file appears to have been cut short"
500 " in the middle of a packet.";
503 case WTAP_ERR_BAD_RECORD:
504 snprintf(errmsg_errno, sizeof(errmsg_errno),
505 "The capture file appears to be damaged or corrupt.\n(%s)",
507 errmsg = errmsg_errno;
511 snprintf(errmsg_errno, sizeof(errmsg_errno),
512 "An error occurred while reading the"
513 " capture file: %s.", wtap_strerror(err));
514 errmsg = errmsg_errno;
517 snprintf(err_str, sizeof err_str, errmsg);
518 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
521 return (READ_SUCCESS);
526 cf_start_tail(char *fname, gboolean is_tempfile, capture_file *cf)
531 err = cf_open(fname, is_tempfile, cf);
533 /* Disable menu items that make no sense if you're currently running
535 set_menus_for_capture_in_progress(TRUE);
537 /* Enable menu items that make sense if you have some captured
538 packets (yes, I know, we don't have any *yet*). */
539 set_menus_for_captured_packets(TRUE);
541 capture_msg = g_strdup_printf(" %s: <live capture in progress>", cf->iface);
543 statusbar_push_file_msg(capture_msg);
551 cf_continue_tail(capture_file *cf, int to_read, int *err)
553 long data_offset = 0;
558 packet_list_freeze();
560 while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
561 if (cf->state == FILE_READ_ABORTED) {
562 /* Well, the user decided to exit Ethereal. Break out of the
563 loop, and let the code below (which is called even if there
564 aren't any packets left to read) exit. */
567 read_packet(cf, data_offset);
573 /* XXX - this cheats and looks inside the packet list to find the final
575 if (auto_scroll_live && cf->plist_end != NULL)
576 packet_list_moveto_end();
578 if (cf->state == FILE_READ_ABORTED) {
579 /* Well, the user decided to exit Ethereal. Return READ_ABORTED
580 so that our caller can kill off the capture child process;
581 this will cause an EOF on the pipe from the child, so
582 "cf_finish_tail()" will be called, and it will clean up
585 } else if (*err != 0) {
586 /* We got an error reading the capture file.
587 XXX - pop up a dialog box? */
590 return (READ_SUCCESS);
594 cf_finish_tail(capture_file *cf, int *err)
601 packet_list_freeze();
603 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
604 if (cf->state == FILE_READ_ABORTED) {
605 /* Well, the user decided to abort the read. Break out of the
606 loop, and let the code below (which is called even if there
607 aren't any packets left to read) exit. */
610 read_packet(cf, data_offset);
613 if (cf->state == FILE_READ_ABORTED) {
614 /* Well, the user decided to abort the read. We're only called
615 when the child capture process closes the pipe to us (meaning
616 it's probably exited), so we can just close the capture
617 file; we return READ_ABORTED so our caller can do whatever
618 is appropriate when that happens. */
624 if (auto_scroll_live && cf->plist_end != NULL)
625 /* XXX - this cheats and looks inside the packet list to find the final
627 packet_list_moveto_end();
629 /* We're done reading sequentially through the file. */
630 cf->state = FILE_READ_DONE;
632 /* we have to update the f_len field */
633 /* Find the size of the file. */
634 fd = wtap_fd(cf->wth);
635 if (fstat(fd, &cf_stat) >= 0) {
636 cf->f_len = cf_stat.st_size;
639 /* We're done reading sequentially through the file; close the
640 sequential I/O side, to free up memory it requires. */
641 wtap_sequential_close(cf->wth);
643 /* Allow the protocol dissectors to free up memory that they
644 * don't need after the sequential run-through of the packets. */
645 postseq_cleanup_all_protocols();
647 /* Set the file encapsulation type now; we don't know what it is until
648 we've looked at all the packets, as we don't know until then whether
649 there's more than one type (and thus whether it's
650 WTAP_ENCAP_PER_PACKET). */
651 cf->lnk_t = wtap_file_encap(cf->wth);
653 /* Pop the "<live capture in progress>" message off the status bar. */
654 statusbar_pop_file_msg();
656 set_display_filename(cf);
658 /* Enable menu items that make sense if you're not currently running
660 set_menus_for_capture_in_progress(FALSE);
662 /* Enable menu items that make sense if you have a capture file
663 you've finished reading. */
664 set_menus_for_capture_file(TRUE);
665 set_menus_for_unsaved_capture_file(!cf->user_saved);
668 /* We got an error reading the capture file.
669 XXX - pop up a dialog box? */
672 return (READ_SUCCESS);
675 #endif /* HAVE_LIBPCAP */
678 cf_get_display_name(capture_file *cf)
682 /* Return a name to use in displays */
683 if (!cf->is_tempfile) {
684 /* Get the last component of the file name, and use that. */
686 displayname = get_basename(cf->filename);
688 /* Add this filename to the list of recent files in the "Recent Files" submenu */
689 add_menu_recent_capture_file(cf->filename);
691 displayname="(No file)";
694 /* The file we read is a temporary file from a live capture;
695 we don't mention its name. */
696 displayname = "(Untitled)";
702 color_filter_t *colorf;
704 } apply_color_filter_args;
707 * If no color filter has been applied, apply this one.
708 * (The "if no color filter has been applied" is to handle the case where
709 * more than one color filter matches the packet.)
712 apply_color_filter(gpointer filter_arg, gpointer argp)
714 color_filter_t *colorf = filter_arg;
715 apply_color_filter_args *args = argp;
717 if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
718 if (dfilter_apply_edt(colorf->c_colorfilter, args->edt))
719 args->colorf = colorf;
724 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
725 union wtap_pseudo_header *pseudo_header, const guchar *buf,
728 apply_color_filter_args args;
730 gboolean create_proto_tree = FALSE;
733 /* just add some value here until we know if it is being displayed or not */
734 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
736 /* We don't yet have a color filter to apply. */
739 /* If we don't have the time stamp of the first packet in the
740 capture, it's because this is the first packet. Save the time
741 stamp of this packet as the time stamp of the first packet. */
742 if (!firstsec && !firstusec) {
743 firstsec = fdata->abs_secs;
744 firstusec = fdata->abs_usecs;
746 /* if this frames is marked as a reference time frame, reset
747 firstsec and firstusec to this frame */
748 if(fdata->flags.ref_time){
749 firstsec = fdata->abs_secs;
750 firstusec = fdata->abs_usecs;
753 /* If we don't have the time stamp of the previous displayed packet,
754 it's because this is the first displayed packet. Save the time
755 stamp of this packet as the time stamp of the previous displayed
757 if (!prevsec && !prevusec) {
758 prevsec = fdata->abs_secs;
759 prevusec = fdata->abs_usecs;
762 /* Get the time elapsed between the first packet and this packet. */
763 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
764 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
766 /* If it's greater than the current elapsed time, set the elapsed time
767 to it (we check for "greater than" so as not to be confused by
768 time moving backwards). */
769 if ((gint32)cf->esec < fdata->rel_secs
770 || ((gint32)cf->esec == fdata->rel_secs && (gint32)cf->eusec < fdata->rel_usecs)) {
771 cf->esec = fdata->rel_secs;
772 cf->eusec = fdata->rel_usecs;
775 /* Get the time elapsed between the previous displayed packet and
777 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
778 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
782 we have a display filter and are re-applying it;
784 we have a list of color filters;
786 we have tap listeners;
788 allocate a protocol tree root node, so that we'll construct
789 a protocol tree against which a filter expression can be
791 if ((cf->dfcode != NULL && refilter) || filter_list != NULL
792 || num_tap_filters != 0)
793 create_proto_tree = TRUE;
795 /* Dissect the frame. */
796 edt = epan_dissect_new(create_proto_tree, FALSE);
798 if (cf->dfcode != NULL && refilter) {
799 epan_dissect_prime_dfilter(edt, cf->dfcode);
802 filter_list_prime_edt(edt);
805 epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
806 tap_push_tapped_queue(edt);
808 /* If we have a display filter, apply it if we're refiltering, otherwise
809 leave the "passed_dfilter" flag alone.
811 If we don't have a display filter, set "passed_dfilter" to 1. */
812 if (cf->dfcode != NULL) {
814 if (cf->dfcode != NULL)
815 fdata->flags.passed_dfilter = dfilter_apply_edt(cf->dfcode, edt) ? 1 : 0;
817 fdata->flags.passed_dfilter = 1;
820 fdata->flags.passed_dfilter = 1;
822 /* If we have color filters, and the frame is to be displayed, apply
823 the color filters. */
824 if (fdata->flags.passed_dfilter) {
825 if (filter_list != NULL) {
827 g_slist_foreach(filter_list, apply_color_filter, &args);
832 if( (fdata->flags.passed_dfilter)
833 || (edt->pi.fd->flags.ref_time) ){
834 /* This frame either passed the display filter list or is marked as
835 a time reference frame. All time reference frames are displayed
836 even if they dont pass the display filter */
837 /* if this was a TIME REF frame we should reset the cul bytes field */
838 if(edt->pi.fd->flags.ref_time){
839 cum_bytes = fdata->pkt_len;
840 fdata->cum_bytes = cum_bytes;
843 /* increase cum_bytes with this packets length */
844 cum_bytes += fdata->pkt_len;
846 epan_dissect_fill_in_columns(edt);
848 /* If we haven't yet seen the first frame, this is it.
850 XXX - we must do this before we add the row to the display,
851 as, if the display's GtkCList's selection mode is
852 GTK_SELECTION_BROWSE, when the first entry is added to it,
853 "select_packet()" will be called, and it will fetch the row
854 data for the 0th row, and will get a null pointer rather than
855 "fdata", as "gtk_clist_append()" won't yet have returned and
856 thus "gtk_clist_set_row_data()" won't yet have been called.
858 We thus need to leave behind bread crumbs so that
859 "select_packet()" can find this frame. See the comment
860 in "select_packet()". */
861 if (cf->first_displayed == NULL)
862 cf->first_displayed = fdata;
864 /* This is the last frame we've seen so far. */
865 cf->last_displayed = fdata;
867 row = packet_list_append(cf->cinfo.col_data, fdata);
869 /* If the packet matches a color filter,
870 * store matching color_filter_t object in frame data. */
871 if (filter_list != NULL && (args.colorf != NULL)) {
872 /* add the matching colorfilter to the frame data */
873 fdata->color_filter = args.colorf;
874 /* If packet is marked, use colors from preferences */
875 if (fdata->flags.marked) {
876 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
877 } else /* if (filter_list != NULL && (args.colorf != NULL)) */ {
878 packet_list_set_colors(row, &(args.colorf->fg_color),
879 &(args.colorf->bg_color));
882 /* No color filter match */
883 fdata->color_filter = NULL;
884 if (fdata->flags.marked) {
885 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
889 /* Set the time of the previous displayed frame to the time of this
891 prevsec = fdata->abs_secs;
892 prevusec = fdata->abs_usecs;
894 cf->displayed_count++;
896 /* This frame didn't pass the display filter, so it's not being added
897 to the clist, and thus has no row. */
900 epan_dissect_free(edt);
905 read_packet(capture_file *cf, long offset)
907 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
908 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
909 const guchar *buf = wtap_buf_ptr(cf->wth);
912 frame_data *plist_end;
915 /* Allocate the next list entry, and add it to the list. */
916 fdata = g_mem_chunk_alloc(cf->plist_chunk);
921 fdata->pkt_len = phdr->len;
922 fdata->cap_len = phdr->caplen;
923 fdata->file_off = offset;
924 fdata->lnk_t = phdr->pkt_encap;
925 fdata->abs_secs = phdr->ts.tv_sec;
926 fdata->abs_usecs = phdr->ts.tv_usec;
927 fdata->flags.encoding = CHAR_ASCII;
928 fdata->flags.visited = 0;
929 fdata->flags.marked = 0;
930 fdata->flags.ref_time = 0;
934 edt = epan_dissect_new(TRUE, FALSE);
935 epan_dissect_prime_dfilter(edt, cf->rfcode);
936 epan_dissect_run(edt, pseudo_header, buf, fdata, NULL);
937 passed = dfilter_apply_edt(cf->rfcode, edt);
938 epan_dissect_free(edt);
941 plist_end = cf->plist_end;
942 fdata->prev = plist_end;
943 if (plist_end != NULL)
944 plist_end->next = fdata;
947 cf->plist_end = fdata;
950 fdata->num = cf->count;
951 add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE);
953 /* XXX - if we didn't have read filters, or if we could avoid
954 allocating the "frame_data" structure until we knew whether
955 the frame passed the read filter, we could use a G_ALLOC_ONLY
958 ...but, at least in one test I did, where I just made the chunk
959 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
960 seem to save a noticeable amount of time or space. */
961 g_mem_chunk_free(cf->plist_chunk, fdata);
966 filter_packets(capture_file *cf, gchar *dftext, gboolean force)
969 char *filter_new = dftext ? dftext : "";
970 char *filter_old = cf->dfilter ? cf->dfilter : "";
972 /* if new filter equals old one, do nothing unless told to do so */
973 if (!force && strcmp(filter_new, filter_old) == 0) {
977 if (dftext == NULL) {
978 /* The new filter is an empty filter (i.e., display all packets). */
982 * We have a filter; make a copy of it (as we'll be saving it),
983 * and try to compile it.
985 dftext = g_strdup(dftext);
986 if (!dfilter_compile(dftext, &dfcode)) {
987 /* The attempt failed; report an error. */
988 gchar *safe_dftext = simple_dialog_format_message(dftext);
989 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
991 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
994 "The following display filter is not a valid display filter:\n%s\n"
995 "See the help for a description of the display filter syntax.",
996 simple_dialog_primary_start(), safe_dfilter_error_msg,
997 simple_dialog_primary_end(), safe_dftext);
998 g_free(safe_dfilter_error_msg);
1005 if (dfcode == NULL) {
1006 /* Yes - free the filter text, and set it to null. */
1012 /* We have a valid filter. Replace the current filter. */
1013 if (cf->dfilter != NULL)
1014 g_free(cf->dfilter);
1015 cf->dfilter = dftext;
1016 if (cf->dfcode != NULL)
1017 dfilter_free(cf->dfcode);
1018 cf->dfcode = dfcode;
1020 /* Now rescan the packet list, applying the new filter, but not
1021 throwing away information constructed on a previous pass. */
1022 if (dftext == NULL) {
1023 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1025 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1031 colorize_packets(capture_file *cf)
1033 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1037 reftime_packets(capture_file *cf)
1039 rescan_packets(cf, "Updating Reftime", "all packets", FALSE, FALSE);
1043 redissect_packets(capture_file *cf)
1045 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1048 /* Rescan the list of packets, reconstructing the CList.
1050 "action" describes why we're doing this; it's used in the progress
1053 "action_item" describes what we're doing; it's used in the progress
1056 "refilter" is TRUE if we need to re-evaluate the filter expression.
1058 "redissect" is TRUE if we need to make the dissectors reconstruct
1059 any state information they have (because a preference that affects
1060 some dissector has changed, meaning some dissector might construct
1061 its state differently from the way it was constructed the last time). */
1063 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1064 gboolean refilter, gboolean redissect)
1067 progdlg_t *progbar = NULL;
1072 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1073 int selected_row, prev_row, preceding_row, following_row;
1074 gboolean selected_frame_seen;
1077 GTimeVal start_time;
1078 gchar status_str[100];
1079 int progbar_nextstep;
1080 int progbar_quantum;
1083 reset_tap_listeners();
1084 /* Which frame, if any, is the currently selected frame?
1085 XXX - should the selected frame or the focus frame be the "current"
1086 frame, that frame being the one from which "Find Frame" searches
1088 selected_frame = cf->current_frame;
1090 /* We don't yet know what row that frame will be on, if any, after we
1091 rebuild the clist, however. */
1095 /* We need to re-initialize all the state information that protocols
1096 keep, because some preference that controls a dissector has changed,
1097 which might cause the state information to be constructed differently
1098 by that dissector. */
1100 /* Initialize all data structures used for dissection. */
1104 /* Freeze the packet list while we redo it, so we don't get any
1105 screen updates while it happens. */
1106 packet_list_freeze();
1109 packet_list_clear();
1111 /* We don't yet know which will be the first and last frames displayed. */
1112 cf->first_displayed = NULL;
1113 cf->last_displayed = NULL;
1115 /* We currently don't display any packets */
1116 cf->displayed_count = 0;
1118 /* Iterate through the list of frames. Call a routine for each frame
1119 to check whether it should be displayed and, if so, add it to
1120 the display list. */
1126 /* Update the progress bar when it gets to this value. */
1127 progbar_nextstep = 0;
1128 /* When we reach the value that triggers a progress bar update,
1129 bump that value by this amount. */
1130 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1131 /* Count of packets at which we've looked. */
1135 g_get_current_time(&start_time);
1137 row = -1; /* no previous row yet */
1142 preceding_frame = NULL;
1144 following_frame = NULL;
1146 selected_frame_seen = FALSE;
1148 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1149 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1150 when we update it, we have to run the GTK+ main loop to get it
1151 to repaint what's pending, and doing so may involve an "ioctl()"
1152 to see if there's any pending input from an X server, and doing
1153 that for every packet can be costly, especially on a big file. */
1154 if (count >= progbar_nextstep) {
1155 /* let's not divide by zero. I should never be started
1156 * with count == 0, so let's assert that
1158 g_assert(cf->count > 0);
1159 prog_val = (gfloat) count / cf->count;
1161 if (progbar == NULL)
1162 /* Create the progress bar if necessary */
1163 progbar = delayed_create_progress_dlg(action, action_item, &stop_flag,
1164 &start_time, prog_val);
1166 if (progbar != NULL) {
1167 g_snprintf(status_str, sizeof(status_str),
1168 "%4u of %u frames", count, cf->count);
1169 update_progress_dlg(progbar, prog_val, status_str);
1172 progbar_nextstep += progbar_quantum;
1176 /* Well, the user decided to abort the filtering. Just stop.
1178 XXX - go back to the previous filter? Users probably just
1179 want not to wait for a filtering operation to finish;
1180 unless we cancel by having no filter, reverting to the
1181 previous filter will probably be even more expensive than
1182 continuing the filtering, as it involves going back to the
1183 beginning and filtering, and even with no filter we currently
1184 have to re-generate the entire clist, which is also expensive.
1186 I'm not sure what Network Monitor does, but it doesn't appear
1187 to give you an unfiltered display if you cancel. */
1194 /* Since all state for the frame was destroyed, mark the frame
1195 * as not visited, free the GSList referring to the state
1196 * data (the per-frame data itself was freed by
1197 * "init_dissection()"), and null out the GSList pointer. */
1198 fdata->flags.visited = 0;
1200 g_slist_free(fdata->pfd);
1205 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1206 cf->pd, fdata->cap_len, &err, &err_info)) {
1207 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1208 cf_read_error_message(err, err_info), cf->filename);
1212 /* If the previous frame is displayed, and we haven't yet seen the
1213 selected frame, remember that frame - it's the closest one we've
1214 yet seen before the selected frame. */
1215 if (prev_row != -1 && !selected_frame_seen) {
1216 preceding_row = prev_row;
1217 preceding_frame = prev_frame;
1219 row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
1222 /* If this frame is displayed, and this is the first frame we've
1223 seen displayed after the selected frame, remember this frame -
1224 it's the closest one we've yet seen at or after the selected
1226 if (row != -1 && selected_frame_seen && following_row == -1) {
1227 following_row = row;
1228 following_frame = fdata;
1230 if (fdata == selected_frame) {
1232 selected_frame_seen = TRUE;
1235 /* Remember this row/frame - it'll be the previous row/frame
1236 on the next pass through the loop. */
1242 /* Clear out what remains of the visited flags and per-frame data
1245 XXX - that may cause various forms of bogosity when dissecting
1246 these frames, as they won't have been seen by this sequential
1247 pass, but the only alternative I see is to keep scanning them
1248 even though the user requested that the scan stop, and that
1249 would leave the user stuck with an Ethereal grinding on
1250 until it finishes. Should we just stick them with that? */
1251 for (; fdata != NULL; fdata = fdata->next) {
1252 fdata->flags.visited = 0;
1254 g_slist_free(fdata->pfd);
1260 /* We're done filtering the packets; destroy the progress bar if it
1262 if (progbar != NULL)
1263 destroy_progress_dlg(progbar);
1265 /* Unfreeze the packet list. */
1268 if (selected_row == -1) {
1269 /* The selected frame didn't pass the filter. */
1270 if (selected_frame == NULL) {
1271 /* That's because there *was* no selected frame. Make the first
1272 displayed frame the current frame. */
1275 /* Find the nearest displayed frame to the selected frame (whether
1276 it's before or after that frame) and make that the current frame.
1277 If the next and previous displayed frames are equidistant from the
1278 selected frame, choose the next one. */
1279 g_assert(following_frame == NULL ||
1280 following_frame->num >= selected_frame->num);
1281 g_assert(preceding_frame == NULL ||
1282 preceding_frame->num <= selected_frame->num);
1283 if (following_frame == NULL) {
1284 /* No frame after the selected frame passed the filter, so we
1285 have to select the last displayed frame before the selected
1287 selected_row = preceding_row;
1288 } else if (preceding_frame == NULL) {
1289 /* No frame before the selected frame passed the filter, so we
1290 have to select the first displayed frame after the selected
1292 selected_row = following_row;
1294 /* Choose the closer of the last displayed frame before the
1295 selected frame and the first displayed frame after the
1296 selected frame; in case of a tie, choose the first displayed
1297 frame after the selected frame. */
1298 if (following_frame->num - selected_frame->num <=
1299 selected_frame->num - preceding_frame->num) {
1300 selected_row = following_row;
1302 /* The previous frame is closer to the selected frame than the
1304 selected_row = preceding_row;
1310 if (selected_row == -1) {
1311 /* There are no frames displayed at all. */
1312 unselect_packet(cf);
1314 /* Either the frame that was selected passed the filter, or we've
1315 found the nearest displayed frame to that frame. Select it, make
1316 it the focus row, and make it visible. */
1317 packet_list_set_selected_row(selected_row);
1328 process_specified_packets(capture_file *cf, packet_range_t *range,
1329 const char *string1, const char *string2,
1330 gboolean (*callback)(capture_file *, frame_data *,
1331 union wtap_pseudo_header *, const guint8 *, void *),
1332 void *callback_args)
1337 union wtap_pseudo_header pseudo_header;
1338 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
1339 psp_return_t ret = PSP_FINISHED;
1341 progdlg_t *progbar = NULL;
1344 gboolean progbar_stop_flag;
1345 GTimeVal progbar_start_time;
1346 gchar progbar_status_str[100];
1347 int progbar_nextstep;
1348 int progbar_quantum;
1349 range_process_e process_this;
1351 /* Update the progress bar when it gets to this value. */
1352 progbar_nextstep = 0;
1353 /* When we reach the value that triggers a progress bar update,
1354 bump that value by this amount. */
1355 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1356 /* Count of packets at which we've looked. */
1359 progbar_stop_flag = FALSE;
1360 g_get_current_time(&progbar_start_time);
1362 packet_range_process_init(range);
1364 /* Iterate through the list of packets, printing the packets that
1365 were selected by the current display filter. */
1366 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1367 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1368 when we update it, we have to run the GTK+ main loop to get it
1369 to repaint what's pending, and doing so may involve an "ioctl()"
1370 to see if there's any pending input from an X server, and doing
1371 that for every packet can be costly, especially on a big file. */
1372 if (progbar_count >= progbar_nextstep) {
1373 /* let's not divide by zero. I should never be started
1374 * with count == 0, so let's assert that
1376 g_assert(cf->count > 0);
1377 progbar_val = (gfloat) progbar_count / cf->count;
1379 if (progbar == NULL)
1380 /* Create the progress bar if necessary */
1381 progbar = delayed_create_progress_dlg(string1, string2,
1383 &progbar_start_time,
1386 if (progbar != NULL) {
1387 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
1388 "%4u of %u packets", progbar_count, cf->count);
1389 update_progress_dlg(progbar, progbar_val, progbar_status_str);
1392 progbar_nextstep += progbar_quantum;
1395 if (progbar_stop_flag) {
1396 /* Well, the user decided to abort the operation. Just stop,
1397 and arrange to return TRUE to our caller, so they know it
1398 was stopped explicitly. */
1405 /* do we have to process this packet? */
1406 process_this = packet_range_process_packet(range, fdata);
1407 if (process_this == range_process_next) {
1408 /* this packet uninteresting, continue with next one */
1410 } else if (process_this == range_processing_finished) {
1411 /* all interesting packets processed, stop the loop */
1415 /* Get the packet */
1416 if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1417 pd, fdata->cap_len, &err, &err_info)) {
1418 /* Attempt to get the packet failed. */
1419 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1420 cf_read_error_message(err, err_info), cf->filename);
1424 /* Process the packet */
1425 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
1426 /* Callback failed. We assume it reported the error appropriately. */
1432 /* We're done printing the packets; destroy the progress bar if
1434 if (progbar != NULL)
1435 destroy_progress_dlg(progbar);
1441 retap_packet(capture_file *cf _U_, frame_data *fdata,
1442 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1445 epan_dissect_t *edt;
1447 /* If we have tap listeners, allocate a protocol tree root node, so that
1448 we'll construct a protocol tree against which a filter expression can
1450 edt = epan_dissect_new(num_tap_filters != 0, FALSE);
1451 tap_queue_init(edt);
1452 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1453 tap_push_tapped_queue(edt);
1454 epan_dissect_free(edt);
1460 retap_packets(capture_file *cf)
1462 packet_range_t range;
1464 /* Reset the tap listeners. */
1465 reset_tap_listeners();
1467 /* Iterate through the list of packets, dissecting all packets and
1468 re-running the taps. */
1469 packet_range_init(&range);
1470 packet_range_process_init(&range);
1471 switch (process_specified_packets(cf, &range, "Refiltering statistics on",
1472 "all packets", retap_packet,
1475 /* Completed successfully. */
1479 /* Well, the user decided to abort the refiltering.
1480 Return FALSE so our caller knows they did that. */
1484 /* Error while retapping. */
1492 print_args_t *print_args;
1494 gboolean print_header_line;
1495 char *header_line_buf;
1496 int header_line_buf_len;
1497 gboolean print_formfeed;
1498 gboolean print_separator;
1502 } print_callback_args_t;
1505 print_packet(capture_file *cf, frame_data *fdata,
1506 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1509 print_callback_args_t *args = argsp;
1510 epan_dissect_t *edt;
1516 gboolean proto_tree_needed;
1519 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex;
1521 /* Fill in the column information, but don't bother creating
1522 the logical protocol tree. */
1523 edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
1524 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
1525 epan_dissect_fill_in_columns(edt);
1527 if (args->print_formfeed) {
1528 print_formfeed(args->print_fh, args->print_args->format);
1530 if (args->print_separator)
1531 print_line(args->print_fh, 0, args->print_args->format, "");
1534 if (args->print_args->print_summary || args->print_args->format == PR_FMT_PS) {
1535 if (args->print_header_line) {
1536 print_line(args->print_fh, 0, args->print_args->format,
1537 args->header_line_buf);
1538 args->print_header_line = FALSE; /* we might not need to print any more */
1540 cp = &args->line_buf[0];
1542 for (i = 0; i < cf->cinfo.num_cols; i++) {
1543 /* Find the length of the string for this column. */
1544 column_len = strlen(cf->cinfo.col_data[i]);
1545 if (args->col_widths[i] > column_len)
1546 column_len = args->col_widths[i];
1548 /* Make sure there's room in the line buffer for the column; if not,
1549 double its length. */
1550 line_len += column_len + 1; /* "+1" for space */
1551 if (line_len > args->line_buf_len) {
1552 cp_off = cp - args->line_buf;
1553 args->line_buf_len = 2 * line_len;
1554 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
1555 cp = args->line_buf + cp_off;
1558 /* Right-justify the packet number column. */
1559 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1560 sprintf(cp, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
1562 sprintf(cp, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
1564 if (i != cf->cinfo.num_cols - 1)
1569 print_packet_header(args->print_fh, args->print_args->format, fdata->num, args->line_buf);
1571 if (args->print_args->print_summary) {
1572 print_line(args->print_fh, 0, args->print_args->format, args->line_buf);
1574 } /* if (print_summary) */
1576 if (args->print_args->print_dissections != print_dissections_none) {
1577 if (args->print_args->print_summary) {
1578 /* Separate the summary line from the tree with a blank line. */
1579 print_line(args->print_fh, 0, args->print_args->format, "");
1582 /* Print the information in that tree. */
1583 proto_tree_print(args->print_args, edt, args->print_fh);
1585 /* Print a blank line if we print anything after this (aka more than one packet). */
1586 args->print_separator = TRUE;
1588 /* Print a header line if we print any more packet summaries */
1589 args->print_header_line = TRUE;
1592 if (args->print_args->print_hex) {
1593 /* Print the full packet data as hex. */
1594 print_hex_data(args->print_fh, args->print_args->format, edt);
1596 /* Print a blank line if we print anything after this (aka more than one packet). */
1597 args->print_separator = TRUE;
1599 /* Print a header line if we print any more packet summaries */
1600 args->print_header_line = TRUE;
1601 } /* if (print_summary) */
1603 epan_dissect_free(edt);
1605 /* do we want to have a formfeed between each packet from now on? */
1606 if(args->print_args->print_formfeed) {
1607 args->print_formfeed = TRUE;
1610 return !ferror(args->print_fh);
1614 print_packets(capture_file *cf, print_args_t *print_args)
1617 print_callback_args_t callback_args;
1625 if(print_args->to_file) {
1626 callback_args.print_fh = open_print_dest(print_args->to_file,
1629 callback_args.print_fh = open_print_dest(print_args->to_file,
1632 if (callback_args.print_fh == NULL)
1633 return PP_OPEN_ERROR; /* attempt to open destination failed */
1635 print_preamble(callback_args.print_fh, print_args->format, cf->filename);
1636 if (ferror(callback_args.print_fh)) {
1637 close_print_dest(print_args->to_file, callback_args.print_fh);
1638 return PP_WRITE_ERROR;
1641 callback_args.print_args = print_args;
1642 callback_args.print_header_line = TRUE;
1643 callback_args.header_line_buf = NULL;
1644 callback_args.header_line_buf_len = 256;
1645 callback_args.print_formfeed = FALSE;
1646 callback_args.print_separator = FALSE;
1647 callback_args.line_buf = NULL;
1648 callback_args.line_buf_len = 256;
1649 callback_args.col_widths = NULL;
1650 if (print_args->print_summary || print_args->format == PR_FMT_PS) {
1651 /* We're printing packet summaries. Allocate the header line buffer
1652 and get the column widths. */
1653 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
1655 /* Find the widths for each of the columns - maximum of the
1656 width of the title and the width of the data - and construct
1657 a buffer with a line containing the column titles. */
1658 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1659 cp = &callback_args.header_line_buf[0];
1661 for (i = 0; i < cf->cinfo.num_cols; i++) {
1662 /* Don't pad the last column. */
1663 if (i == cf->cinfo.num_cols - 1)
1664 callback_args.col_widths[i] = 0;
1666 callback_args.col_widths[i] = strlen(cf->cinfo.col_title[i]);
1667 data_width = get_column_char_width(get_column_format(i));
1668 if (data_width > callback_args.col_widths[i])
1669 callback_args.col_widths[i] = data_width;
1672 /* Find the length of the string for this column. */
1673 column_len = strlen(cf->cinfo.col_title[i]);
1674 if (callback_args.col_widths[i] > column_len)
1675 column_len = callback_args.col_widths[i];
1677 /* Make sure there's room in the line buffer for the column; if not,
1678 double its length. */
1679 line_len += column_len + 1; /* "+1" for space */
1680 if (line_len > callback_args.header_line_buf_len) {
1681 cp_off = cp - callback_args.header_line_buf;
1682 callback_args.header_line_buf_len = 2 * line_len;
1683 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
1684 callback_args.header_line_buf_len + 1);
1685 cp = callback_args.header_line_buf + cp_off;
1688 /* Right-justify the packet number column. */
1689 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1690 sprintf(cp, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1692 sprintf(cp, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1694 if (i != cf->cinfo.num_cols - 1)
1699 /* Now start out the main line buffer with the same length as the
1700 header line buffer. */
1701 callback_args.line_buf_len = callback_args.header_line_buf_len;
1702 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
1703 } /* if (print_summary) */
1705 /* Iterate through the list of packets, printing the packets we were
1707 ret = process_specified_packets(cf, &print_args->range, "Printing",
1708 "selected packets", print_packet,
1711 if (callback_args.header_line_buf != NULL)
1712 g_free(callback_args.header_line_buf);
1713 if (callback_args.line_buf != NULL)
1714 g_free(callback_args.line_buf);
1715 if (callback_args.col_widths != NULL)
1716 g_free(callback_args.col_widths);
1721 /* Completed successfully. */
1725 /* Well, the user decided to abort the printing.
1727 XXX - note that what got generated before they did that
1728 will get printed if we're piping to a print program; we'd
1729 have to write to a file and then hand that to the print
1730 program to make it actually not print anything. */
1734 /* Error while printing.
1736 XXX - note that what got generated before they did that
1737 will get printed if we're piping to a print program; we'd
1738 have to write to a file and then hand that to the print
1739 program to make it actually not print anything. */
1740 close_print_dest(print_args->to_file, callback_args.print_fh);
1741 return PP_WRITE_ERROR;
1744 print_finale(callback_args.print_fh, print_args->format);
1745 if (ferror(callback_args.print_fh)) {
1746 close_print_dest(print_args->to_file, callback_args.print_fh);
1747 return PP_WRITE_ERROR;
1750 close_print_dest(print_args->to_file, callback_args.print_fh);
1755 /* Scan through the packet list and change all columns that use the
1756 "command-line-specified" time stamp format to use the current
1757 value of that format. */
1759 change_time_formats(capture_file *cf)
1762 progdlg_t *progbar = NULL;
1768 GTimeVal start_time;
1769 gchar status_str[100];
1770 int progbar_nextstep;
1771 int progbar_quantum;
1773 gboolean sorted_by_frame_column;
1775 /* Are there any columns with time stamps in the "command-line-specified"
1778 XXX - we have to force the "column is writable" flag on, as it
1779 might be off from the last frame that was dissected. */
1780 col_set_writable(&cf->cinfo, TRUE);
1781 if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
1782 /* No, there aren't any columns in that format, so we have no work
1786 first = cf->cinfo.col_first[COL_CLS_TIME];
1787 g_assert(first >= 0);
1788 last = cf->cinfo.col_last[COL_CLS_TIME];
1790 /* Freeze the packet list while we redo it, so we don't get any
1791 screen updates while it happens. */
1792 packet_list_freeze();
1794 /* Update the progress bar when it gets to this value. */
1795 progbar_nextstep = 0;
1796 /* When we reach the value that triggers a progress bar update,
1797 bump that value by this amount. */
1798 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1799 /* Count of packets at which we've looked. */
1802 /* If the rows are currently sorted by the frame column then we know
1803 * the row number of each packet: it's the row number of the previously
1804 * displayed packet + 1.
1806 * Otherwise, if the display is sorted by a different column then we have
1807 * to use the O(N) packet_list_find_row_from_data() (thus making the job
1808 * of changing the time display format O(N**2)).
1810 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
1811 * the row number and walks that many elements down the clist to find
1812 * the appropriate element.)
1814 sorted_by_frame_column = FALSE;
1815 for (i = 0; i < cf->cinfo.num_cols; i++) {
1816 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1818 sorted_by_frame_column = (i == packet_list_get_sort_column());
1824 g_get_current_time(&start_time);
1826 /* Iterate through the list of packets, checking whether the packet
1827 is in a row of the summary list and, if so, whether there are
1828 any columns that show the time in the "command-line-specified"
1829 format and, if so, update that row. */
1830 for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
1831 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1832 when we update it, we have to run the GTK+ main loop to get it
1833 to repaint what's pending, and doing so may involve an "ioctl()"
1834 to see if there's any pending input from an X server, and doing
1835 that for every packet can be costly, especially on a big file. */
1836 if (count >= progbar_nextstep) {
1837 /* let's not divide by zero. I should never be started
1838 * with count == 0, so let's assert that
1840 g_assert(cf->count > 0);
1842 prog_val = (gfloat) count / cf->count;
1844 if (progbar == NULL)
1845 /* Create the progress bar if necessary */
1846 progbar = delayed_create_progress_dlg("Changing", "time display",
1847 &stop_flag, &start_time, prog_val);
1849 if (progbar != NULL) {
1850 g_snprintf(status_str, sizeof(status_str),
1851 "%4u of %u packets", count, cf->count);
1852 update_progress_dlg(progbar, prog_val, status_str);
1855 progbar_nextstep += progbar_quantum;
1859 /* Well, the user decided to abort the redisplay. Just stop.
1861 XXX - this leaves the time field in the old format in
1862 frames we haven't yet processed. So it goes; should we
1863 simply not offer them the option of stopping? */
1869 /* Find what row this packet is in. */
1870 if (!sorted_by_frame_column) {
1871 /* This function is O(N), so we try to avoid using it... */
1872 row = packet_list_find_row_from_data(fdata);
1874 /* ...which we do by maintaining a count of packets that are
1875 being displayed (i.e., that have passed the display filter),
1876 and using the current value of that count as the row number
1877 (which is why we can only do it when the display is sorted
1878 by the frame number). */
1879 if (fdata->flags.passed_dfilter)
1886 /* This packet is in the summary list, on row "row". */
1888 for (i = first; i <= last; i++) {
1889 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1890 /* This is one of the columns that shows the time in
1891 "command-line-specified" format; update it. */
1892 cf->cinfo.col_buf[i][0] = '\0';
1893 col_set_cls_time(fdata, &cf->cinfo, i);
1894 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
1900 /* We're done redisplaying the packets; destroy the progress bar if it
1902 if (progbar != NULL)
1903 destroy_progress_dlg(progbar);
1905 /* Set the column widths of those columns that show the time in
1906 "command-line-specified" format. */
1907 for (i = first; i <= last; i++) {
1908 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1909 packet_list_set_cls_time_width(i);
1913 /* Unfreeze the packet list. */
1921 gboolean frame_matched;
1925 find_packet_protocol_tree(capture_file *cf, const char *string)
1929 mdata.string = string;
1930 mdata.string_len = strlen(string);
1931 return find_packet(cf, match_protocol_tree, &mdata);
1935 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
1937 match_data *mdata = criterion;
1938 epan_dissect_t *edt;
1940 /* Construct the protocol tree, including the displayed text */
1941 edt = epan_dissect_new(TRUE, TRUE);
1942 /* We don't need the column information */
1943 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
1945 /* Iterate through all the nodes, seeing if they have text that matches. */
1947 mdata->frame_matched = FALSE;
1948 proto_tree_children_foreach(edt->tree, match_subtree_text, mdata);
1949 epan_dissect_free(edt);
1950 return mdata->frame_matched;
1954 match_subtree_text(proto_node *node, gpointer data)
1956 match_data *mdata = (match_data*) data;
1957 const gchar *string = mdata->string;
1958 size_t string_len = mdata->string_len;
1959 capture_file *cf = mdata->cf;
1960 field_info *fi = PITEM_FINFO(node);
1961 gchar label_str[ITEM_LABEL_LENGTH];
1968 if (mdata->frame_matched) {
1969 /* We already had a match; don't bother doing any more work. */
1973 /* Don't match invisible entries. */
1974 if (PROTO_ITEM_IS_HIDDEN(node))
1977 /* was a free format label produced? */
1979 label_ptr = fi->rep->representation;
1981 /* no, make a generic label */
1982 label_ptr = label_str;
1983 proto_item_fill_label(fi, label_str);
1986 /* Does that label match? */
1987 label_len = strlen(label_ptr);
1988 for (i = 0; i < label_len; i++) {
1989 c_char = label_ptr[i];
1991 c_char = toupper(c_char);
1992 if (c_char == string[c_match]) {
1994 if (c_match == string_len) {
1995 /* No need to look further; we have a match */
1996 mdata->frame_matched = TRUE;
2003 /* Recurse into the subtree, if it exists */
2004 if (node->first_child != NULL)
2005 proto_tree_children_foreach(node, match_subtree_text, mdata);
2009 find_packet_summary_line(capture_file *cf, const char *string)
2013 mdata.string = string;
2014 mdata.string_len = strlen(string);
2015 return find_packet(cf, match_summary_line, &mdata);
2019 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2021 match_data *mdata = criterion;
2022 const gchar *string = mdata->string;
2023 size_t string_len = mdata->string_len;
2024 epan_dissect_t *edt;
2025 const char *info_column;
2026 size_t info_column_len;
2027 gboolean frame_matched = FALSE;
2033 /* Don't bother constructing the protocol tree */
2034 edt = epan_dissect_new(FALSE, FALSE);
2035 /* Get the column information */
2036 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2038 /* Find the Info column */
2039 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2040 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2041 /* Found it. See if we match. */
2042 info_column = edt->pi.cinfo->col_data[colx];
2043 info_column_len = strlen(info_column);
2044 for (i = 0; i < info_column_len; i++) {
2045 c_char = info_column[i];
2047 c_char = toupper(c_char);
2048 if (c_char == string[c_match]) {
2050 if (c_match == string_len) {
2051 frame_matched = TRUE;
2060 epan_dissect_free(edt);
2061 return frame_matched;
2067 } cbs_t; /* "Counted byte string" */
2070 find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
2075 info.data_len = string_size;
2077 /* String or hex search? */
2079 /* String search - what type of string? */
2080 switch (cf->scs_type) {
2082 case SCS_ASCII_AND_UNICODE:
2083 return find_packet(cf, match_ascii_and_unicode, &info);
2086 return find_packet(cf, match_ascii, &info);
2089 return find_packet(cf, match_unicode, &info);
2092 g_assert_not_reached();
2096 return find_packet(cf, match_binary, &info);
2100 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2102 cbs_t *info = criterion;
2103 const char *ascii_text = info->data;
2104 size_t textlen = info->data_len;
2105 gboolean frame_matched;
2111 frame_matched = FALSE;
2112 buf_len = fdata->pkt_len;
2113 for (i = 0; i < buf_len; i++) {
2116 c_char = toupper(c_char);
2118 if (c_char == ascii_text[c_match]) {
2120 if (c_match == textlen) {
2121 frame_matched = TRUE;
2128 return frame_matched;
2132 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2134 cbs_t *info = criterion;
2135 const char *ascii_text = info->data;
2136 size_t textlen = info->data_len;
2137 gboolean frame_matched;
2143 frame_matched = FALSE;
2144 buf_len = fdata->pkt_len;
2145 for (i = 0; i < buf_len; i++) {
2148 c_char = toupper(c_char);
2149 if (c_char == ascii_text[c_match]) {
2151 if (c_match == textlen) {
2152 frame_matched = TRUE;
2158 return frame_matched;
2162 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2164 cbs_t *info = criterion;
2165 const char *ascii_text = info->data;
2166 size_t textlen = info->data_len;
2167 gboolean frame_matched;
2173 frame_matched = FALSE;
2174 buf_len = fdata->pkt_len;
2175 for (i = 0; i < buf_len; i++) {
2178 c_char = toupper(c_char);
2179 if (c_char == ascii_text[c_match]) {
2182 if (c_match == textlen) {
2183 frame_matched = TRUE;
2189 return frame_matched;
2193 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
2195 cbs_t *info = criterion;
2196 const guint8 *binary_data = info->data;
2197 size_t datalen = info->data_len;
2198 gboolean frame_matched;
2203 frame_matched = FALSE;
2204 buf_len = fdata->pkt_len;
2205 for (i = 0; i < buf_len; i++) {
2206 if (cf->pd[i] == binary_data[c_match]) {
2208 if (c_match == datalen) {
2209 frame_matched = TRUE;
2215 return frame_matched;
2219 find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
2221 return find_packet(cf, match_dfilter, sfcode);
2225 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
2227 dfilter_t *sfcode = criterion;
2228 epan_dissect_t *edt;
2229 gboolean frame_matched;
2231 edt = epan_dissect_new(TRUE, FALSE);
2232 epan_dissect_prime_dfilter(edt, sfcode);
2233 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2234 frame_matched = dfilter_apply_edt(sfcode, edt);
2235 epan_dissect_free(edt);
2236 return frame_matched;
2240 find_packet(capture_file *cf,
2241 gboolean (*match_function)(capture_file *, frame_data *, void *),
2244 frame_data *start_fd;
2246 frame_data *new_fd = NULL;
2247 progdlg_t *progbar = NULL;
2254 GTimeVal start_time;
2255 gchar status_str[100];
2256 int progbar_nextstep;
2257 int progbar_quantum;
2259 start_fd = cf->current_frame;
2260 if (start_fd != NULL) {
2261 /* Iterate through the list of packets, starting at the packet we've
2262 picked, calling a routine to run the filter on the packet, see if
2263 it matches, and stop if so. */
2267 progbar_nextstep = 0;
2268 /* When we reach the value that triggers a progress bar update,
2269 bump that value by this amount. */
2270 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2273 g_get_current_time(&start_time);
2277 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2278 when we update it, we have to run the GTK+ main loop to get it
2279 to repaint what's pending, and doing so may involve an "ioctl()"
2280 to see if there's any pending input from an X server, and doing
2281 that for every packet can be costly, especially on a big file. */
2282 if (count >= progbar_nextstep) {
2283 /* let's not divide by zero. I should never be started
2284 * with count == 0, so let's assert that
2286 g_assert(cf->count > 0);
2288 prog_val = (gfloat) count / cf->count;
2290 /* Create the progress bar if necessary */
2291 if (progbar == NULL)
2292 progbar = delayed_create_progress_dlg("Searching", cf->sfilter,
2293 &stop_flag, &start_time, prog_val);
2295 if (progbar != NULL) {
2296 g_snprintf(status_str, sizeof(status_str),
2297 "%4u of %u packets", count, cf->count);
2298 update_progress_dlg(progbar, prog_val, status_str);
2301 progbar_nextstep += progbar_quantum;
2305 /* Well, the user decided to abort the search. Go back to the
2306 frame where we started. */
2311 /* Go past the current frame. */
2312 if (cf->sbackward) {
2313 /* Go on to the previous frame. */
2314 fdata = fdata->prev;
2315 if (fdata == NULL) {
2317 * XXX - other apps have a bit more of a detailed message
2318 * for this, and instead of offering "OK" and "Cancel",
2319 * they offer things such as "Continue" and "Cancel";
2320 * we need an API for popping up alert boxes with
2321 * {Verb} and "Cancel".
2323 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2324 "%sBeginning of capture exceeded!%s\n\n"
2325 "Search is continued from the end of the capture.",
2326 simple_dialog_primary_start(), simple_dialog_primary_end());
2327 fdata = cf->plist_end; /* wrap around */
2330 /* Go on to the next frame. */
2331 fdata = fdata->next;
2332 if (fdata == NULL) {
2333 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2334 "%sEnd of capture exceeded!%s\n\n"
2335 "Search is continued from the start of the capture.",
2336 simple_dialog_primary_start(), simple_dialog_primary_end());
2337 fdata = cf->plist; /* wrap around */
2343 /* Is this packet in the display? */
2344 if (fdata->flags.passed_dfilter) {
2345 /* Yes. Load its data. */
2346 if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
2347 cf->pd, fdata->cap_len, &err, &err_info)) {
2348 /* Read error. Report the error, and go back to the frame
2349 where we started. */
2350 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2351 cf_read_error_message(err, err_info), cf->filename);
2356 /* Does it match the search criterion? */
2357 if ((*match_function)(cf, fdata, criterion)) {
2359 break; /* found it! */
2363 if (fdata == start_fd) {
2364 /* We're back to the frame we were on originally, and that frame
2365 doesn't match the search filter. The search failed. */
2370 /* We're done scanning the packets; destroy the progress bar if it
2372 if (progbar != NULL)
2373 destroy_progress_dlg(progbar);
2376 if (new_fd != NULL) {
2377 /* We found a frame. Find what row it's in. */
2378 row = packet_list_find_row_from_data(new_fd);
2379 g_assert(row != -1);
2381 /* Select that row, make it the focus row, and make it visible. */
2382 packet_list_set_selected_row(row);
2383 return TRUE; /* success */
2385 return FALSE; /* failure */
2389 goto_frame(capture_file *cf, guint fnumber)
2394 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
2397 if (fdata == NULL) {
2398 /* we didn't find a packet with that packet number */
2399 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2400 "There is no packet with that packet number.");
2401 return FALSE; /* we failed to go to that packet */
2403 if (!fdata->flags.passed_dfilter) {
2404 /* that packet currently isn't displayed */
2405 /* XXX - add it to the set of displayed packets? */
2406 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2407 "That packet is not currently being displayed.");
2408 return FALSE; /* we failed to go to that packet */
2411 /* We found that packet, and it's currently being displayed.
2412 Find what row it's in. */
2413 row = packet_list_find_row_from_data(fdata);
2414 g_assert(row != -1);
2416 /* Select that row, make it the focus row, and make it visible. */
2417 packet_list_set_selected_row(row);
2418 return TRUE; /* we got to that packet */
2422 goto_top_frame(capture_file *cf)
2426 frame_data *lowest_fdata = NULL;
2428 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2429 if (fdata->flags.passed_dfilter) {
2430 lowest_fdata = fdata;
2435 if (lowest_fdata == NULL) {
2439 /* We found that packet, and it's currently being displayed.
2440 Find what row it's in. */
2441 row = packet_list_find_row_from_data(lowest_fdata);
2442 g_assert(row != -1);
2444 /* Select that row, make it the focus row, and make it visible. */
2445 packet_list_set_selected_row(row);
2446 return TRUE; /* we got to that packet */
2450 goto_bottom_frame(capture_file *cf)
2454 frame_data *highest_fdata = NULL;
2456 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2457 if (fdata->flags.passed_dfilter) {
2458 highest_fdata = fdata;
2462 if (highest_fdata == NULL) {
2466 /* We found that packet, and it's currently being displayed.
2467 Find what row it's in. */
2468 row = packet_list_find_row_from_data(highest_fdata);
2469 g_assert(row != -1);
2471 /* Select that row, make it the focus row, and make it visible. */
2472 packet_list_set_selected_row(row);
2473 return TRUE; /* we got to that packet */
2476 /* Select the packet on a given row. */
2478 select_packet(capture_file *cf, int row)
2484 /* Get the frame data struct pointer for this frame */
2485 fdata = (frame_data *)packet_list_get_row_data(row);
2487 if (fdata == NULL) {
2488 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
2489 the first entry is added to it by "real_insert_row()", that row
2490 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
2491 our version and the vanilla GTK+ version).
2493 This means that a "select-row" signal is emitted; this causes
2494 "packet_list_select_cb()" to be called, which causes "select_packet()"
2497 "select_packet()" fetches, above, the data associated with the
2498 row that was selected; however, as "gtk_clist_append()", which
2499 called "real_insert_row()", hasn't yet returned, we haven't yet
2500 associated any data with that row, so we get back a null pointer.
2502 We can't assume that there's only one frame in the frame list,
2503 either, as we may be filtering the display.
2505 We therefore assume that, if "row" is 0, i.e. the first row
2506 is being selected, and "cf->first_displayed" equals
2507 "cf->last_displayed", i.e. there's only one frame being
2508 displayed, that frame is the frame we want.
2510 This means we have to set "cf->first_displayed" and
2511 "cf->last_displayed" before adding the row to the
2512 GtkCList; see the comment in "add_packet_to_packet_list()". */
2514 if (row == 0 && cf->first_displayed == cf->last_displayed)
2515 fdata = cf->first_displayed;
2518 /* Get the data in that frame. */
2519 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
2520 cf->pd, fdata->cap_len, &err, &err_info)) {
2521 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2522 cf_read_error_message(err, err_info), cf->filename);
2526 /* Record that this frame is the current frame. */
2527 cf->current_frame = fdata;
2529 /* Create the logical protocol tree. */
2530 if (cf->edt != NULL) {
2531 epan_dissect_free(cf->edt);
2534 /* We don't need the columns here. */
2535 cf->edt = epan_dissect_new(TRUE, TRUE);
2536 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
2539 /* Display the GUI protocol tree and hex dump.
2540 XXX - why do we dump core if we call "proto_tree_draw()"
2541 before calling "add_byte_views()"? */
2542 add_main_byte_views(cf->edt);
2543 main_proto_tree_draw(cf->edt->tree);
2545 /* A packet is selected. */
2546 set_menus_for_selected_packet(cf);
2549 /* Unselect the selected packet, if any. */
2551 unselect_packet(capture_file *cf)
2553 /* Destroy the epan_dissect_t for the unselected packet. */
2554 if (cf->edt != NULL) {
2555 epan_dissect_free(cf->edt);
2559 /* Clear out the display of that packet. */
2560 clear_tree_and_hex_views();
2562 /* No packet is selected. */
2563 cf->current_frame = NULL;
2564 set_menus_for_selected_packet(cf);
2566 /* No protocol tree means no selected field. */
2570 /* Unset the selected protocol tree field, if any. */
2572 unselect_field(capture_file *cf)
2574 statusbar_pop_field_msg();
2575 cf->finfo_selected = NULL;
2576 set_menus_for_selected_tree_row(cf);
2580 * Mark a particular frame.
2583 mark_frame(capture_file *cf, frame_data *frame)
2585 frame->flags.marked = TRUE;
2590 * Unmark a particular frame.
2593 unmark_frame(capture_file *cf, frame_data *frame)
2595 frame->flags.marked = FALSE;
2602 } save_callback_args_t;
2605 * Save a capture to a file, in a particular format, saving either
2606 * all packets, all currently-displayed packets, or all marked packets.
2608 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
2609 * up a message box for the failure.
2612 save_packet(capture_file *cf _U_, frame_data *fdata,
2613 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2616 save_callback_args_t *args = argsp;
2617 struct wtap_pkthdr hdr;
2620 /* init the wtap header for saving */
2621 hdr.ts.tv_sec = fdata->abs_secs;
2622 hdr.ts.tv_usec = fdata->abs_usecs;
2623 hdr.caplen = fdata->cap_len;
2624 hdr.len = fdata->pkt_len;
2625 hdr.pkt_encap = fdata->lnk_t;
2627 /* and save the packet */
2628 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
2629 cf_write_failure_alert_box(args->fname, err);
2636 cf_save(char *fname, capture_file *cf, packet_range_t *range, guint save_format)
2638 gchar *from_filename;
2639 gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
2644 struct stat infile, outfile;
2645 save_callback_args_t callback_args;
2647 name_ptr = get_basename(fname);
2648 msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
2649 save_msg = g_malloc(msg_len);
2650 snprintf(save_msg, msg_len, save_fmt, name_ptr);
2651 statusbar_push_file_msg(save_msg);
2655 * Check that the from file is not the same as to file
2656 * We do it here so we catch all cases ...
2657 * Unfortunately, the file requester gives us an absolute file
2658 * name and the read file name may be relative (if supplied on
2659 * the command line). From Joerg Mayer.
2661 * This is a bit tricky on win32. The st_ino field is documented as:
2662 * "The inode, and therefore st_ino, has no meaning in the FAT, ..."
2663 * but it *is* set to zero if stat() returns without an error,
2664 * so this is working, but maybe not quite the way expected. ULFL
2666 infile.st_ino = 1; /* These prevent us from getting equality */
2667 outfile.st_ino = 2; /* If one or other of the files is not accessible */
2668 stat(cf->filename, &infile);
2669 stat(fname, &outfile);
2670 if (infile.st_ino == outfile.st_ino) {
2671 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2672 "%sCapture file: \"%s\" already exists!%s\n\n"
2673 "Please choose a different filename.",
2674 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
2678 packet_range_process_init(range);
2681 * if (!save_filtered && !save_marked && !save_manual_range &&
2682 * !save_marked_range && !save_curr && save_format == cf->cd_t) {
2685 if (packet_range_process_all(range) && save_format == cf->cd_t) {
2686 /* We're not filtering packets, and we're saving it in the format
2687 it's already in, so we can just move or copy the raw data. */
2689 if (cf->is_tempfile) {
2690 /* The file being saved is a temporary file from a live
2691 capture, so it doesn't need to stay around under that name;
2692 first, try renaming the capture buffer file to the new name. */
2694 if (rename(cf->filename, fname) == 0) {
2695 /* That succeeded - there's no need to copy the source file. */
2696 from_filename = NULL;
2699 if (errno == EXDEV) {
2700 /* They're on different file systems, so we have to copy the
2703 from_filename = cf->filename;
2705 /* The rename failed, but not because they're on different
2706 file systems - put up an error message. (Or should we
2707 just punt and try to copy? The only reason why I'd
2708 expect the rename to fail and the copy to succeed would
2709 be if we didn't have permission to remove the file from
2710 the temporary directory, and that might be fixable - but
2711 is it worth requiring the user to go off and fix it?) */
2712 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2713 file_rename_error_message(errno), fname);
2719 from_filename = cf->filename;
2722 /* It's a permanent file, so we should copy it, and not remove the
2725 from_filename = cf->filename;
2729 /* Copy the file, if we haven't moved it. */
2730 if (!copy_binary_file(from_filename, fname))
2734 /* Either we're filtering packets, or we're saving in a different
2735 format; we can't do that by copying or moving the capture file,
2736 we have to do it by writing the packets out in Wiretap. */
2737 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
2739 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
2743 /* XXX - we let the user save a subset of the packets.
2745 If we do that, should we make that file the current file? If so,
2746 it means we can no longer get at the other packets. What does
2749 /* Iterate through the list of packets, processing the packets we were
2752 XXX - we've already called "packet_range_process_init(range)", but
2753 "process_specified_packets()" will do it again. Fortunately,
2754 that's harmless in this case, as we haven't done anything to
2755 "range" since we initialized it. */
2756 callback_args.pdh = pdh;
2757 callback_args.fname = fname;
2758 switch (process_specified_packets(cf, range, "Saving",
2759 "selected packets", save_packet,
2763 /* Completed successfully. */
2767 /* The user decided to abort the saving.
2768 XXX - remove the output file? */
2772 /* Error while saving. */
2773 wtap_dump_close(pdh, &err);
2777 if (!wtap_dump_close(pdh, &err)) {
2778 cf_close_failure_alert_box(fname, err);
2783 /* Pop the "Saving:" message off the status bar. */
2784 statusbar_pop_file_msg();
2786 if (packet_range_process_all(range)) {
2787 /* We saved the entire capture, not just some packets from it.
2788 Open and read the file we saved it to.
2790 XXX - this is somewhat of a waste; we already have the
2791 packets, all this gets us is updated file type information
2792 (which we could just stuff into "cf"), and having the new
2793 file be the one we have opened and from which we're reading
2794 the data, and it means we have to spend time opening and
2795 reading the file, which could be a significant amount of
2796 time if the file is large. */
2797 cf->user_saved = TRUE;
2799 if ((err = cf_open(fname, FALSE, cf)) == 0) {
2800 /* XXX - report errors if this fails?
2801 What should we return if it fails or is aborted? */
2802 switch (cf_read(cf)) {
2806 /* Just because we got an error, that doesn't mean we were unable
2807 to read any of the file; we handle what we could get from the
2812 /* The user bailed out of re-reading the capture file; the
2813 capture file has been closed - just return (without
2814 changing any menu settings; "cf_close()" set them
2815 correctly for the "no capture file open" state). */
2818 set_menus_for_unsaved_capture_file(FALSE);
2824 /* Pop the "Saving:" message off the status bar. */
2825 statusbar_pop_file_msg();
2830 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
2831 gboolean for_writing, int file_type)
2834 /* Wiretap error. */
2837 case WTAP_ERR_NOT_REGULAR_FILE:
2838 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2839 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
2843 case WTAP_ERR_RANDOM_OPEN_PIPE:
2844 /* Seen only when opening a capture file for reading. */
2845 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2846 "The file \"%s\" is a pipe or FIFO; Ethereal cannot read pipe or FIFO files.",
2850 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
2851 /* Seen only when opening a capture file for reading. */
2852 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2853 "The file \"%s\" is not a capture file in a format Ethereal understands.",
2857 case WTAP_ERR_UNSUPPORTED:
2858 /* Seen only when opening a capture file for reading. */
2859 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2860 "The file \"%s\" is not a capture file in a format Ethereal understands.\n"
2862 filename, err_info);
2866 case WTAP_ERR_CANT_WRITE_TO_PIPE:
2867 /* Seen only when opening a capture file for writing. */
2868 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2869 "The file \"%s\" is a pipe, and %s capture files cannot be "
2870 "written to a pipe.",
2871 filename, wtap_file_type_string(file_type));
2874 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
2875 /* Seen only when opening a capture file for writing. */
2876 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2877 "Ethereal does not support writing capture files in that format.");
2880 case WTAP_ERR_UNSUPPORTED_ENCAP:
2882 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2883 "Ethereal cannot save this capture in that format.");
2885 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2886 "The file \"%s\" is a capture for a network type that Ethereal doesn't support.\n"
2888 filename, err_info);
2893 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
2895 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2896 "Ethereal cannot save this capture in that format.");
2898 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2899 "The file \"%s\" is a capture for a network type that Ethereal doesn't support.",
2904 case WTAP_ERR_BAD_RECORD:
2905 /* Seen only when opening a capture file for reading. */
2906 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2907 "The file \"%s\" appears to be damaged or corrupt.\n"
2909 filename, err_info);
2913 case WTAP_ERR_CANT_OPEN:
2915 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2916 "The file \"%s\" could not be created for some unknown reason.",
2919 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2920 "The file \"%s\" could not be opened for some unknown reason.",
2925 case WTAP_ERR_SHORT_READ:
2926 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2927 "The file \"%s\" appears to have been cut short"
2928 " in the middle of a packet or other data.",
2932 case WTAP_ERR_SHORT_WRITE:
2933 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2934 "A full header couldn't be written to the file \"%s\".",
2939 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2940 "The file \"%s\" could not be %s: %s.",
2942 for_writing ? "created" : "opened",
2943 wtap_strerror(err));
2948 open_failure_alert_box(filename, err, for_writing);
2953 file_rename_error_message(int err)
2956 static char errmsg_errno[1024+1];
2961 errmsg = "The path to the file \"%s\" does not exist.";
2965 errmsg = "You do not have permission to move the capture file to \"%s\".";
2969 snprintf(errmsg_errno, sizeof(errmsg_errno),
2970 "The file \"%%s\" could not be moved: %s.",
2971 wtap_strerror(err));
2972 errmsg = errmsg_errno;
2979 cf_read_error_message(int err, gchar *err_info)
2981 static char errmsg_errno[1024+1];
2985 case WTAP_ERR_UNSUPPORTED:
2986 case WTAP_ERR_UNSUPPORTED_ENCAP:
2987 case WTAP_ERR_BAD_RECORD:
2988 snprintf(errmsg_errno, sizeof(errmsg_errno),
2989 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
2990 wtap_strerror(err), err_info);
2994 snprintf(errmsg_errno, sizeof(errmsg_errno),
2995 "An error occurred while reading from the file \"%%s\": %s.",
2996 wtap_strerror(err));
2999 return errmsg_errno;
3003 cf_write_failure_alert_box(const char *filename, int err)
3006 /* Wiretap error. */
3007 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3008 "An error occurred while writing to the file \"%s\": %s.",
3009 filename, wtap_strerror(err));
3012 write_failure_alert_box(filename, err);
3016 /* Check for write errors - if the file is being written to an NFS server,
3017 a write error may not show up until the file is closed, as NFS clients
3018 might not send writes to the server until the "write()" call finishes,
3019 so that the write may fail on the server but the "write()" may succeed. */
3021 cf_close_failure_alert_box(const char *filename, int err)
3024 /* Wiretap error. */
3027 case WTAP_ERR_CANT_CLOSE:
3028 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3029 "The file \"%s\" couldn't be closed for some unknown reason.",
3033 case WTAP_ERR_SHORT_WRITE:
3034 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3035 "Not all the packets could be written to the file \"%s\".",
3040 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3041 "An error occurred while closing the file \"%s\": %s.",
3042 filename, wtap_strerror(err));
3047 We assume that a close error from the OS is really a write error. */
3048 write_failure_alert_box(filename, err);
3053 /* Copies a file in binary mode, for those operating systems that care about
3055 * Returns TRUE on success, FALSE on failure. If a failure, it also
3056 * displays a simple dialog window with the error message.
3059 copy_binary_file(char *from_filename, char *to_filename)
3061 int from_fd, to_fd, nread, nwritten, err;
3064 /* Copy the raw bytes of the file. */
3065 from_fd = open(from_filename, O_RDONLY | O_BINARY);
3067 open_failure_alert_box(from_filename, errno, FALSE);
3071 /* Use open() instead of creat() so that we can pass the O_BINARY
3072 flag, which is relevant on Win32; it appears that "creat()"
3073 may open the file in text mode, not binary mode, but we want
3074 to copy the raw bytes of the file, so we need the output file
3075 to be open in binary mode. */
3076 to_fd = open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
3078 open_failure_alert_box(to_filename, errno, TRUE);
3083 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
3084 nwritten = write(to_fd, pd, nread);
3085 if (nwritten < nread) {
3089 err = WTAP_ERR_SHORT_WRITE;
3090 write_failure_alert_box(to_filename, err);
3098 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3099 "An error occurred while reading from the file \"%s\": %s.",
3100 from_filename, strerror(err));
3106 if (close(to_fd) < 0) {
3107 write_failure_alert_box(to_filename, errno);