4 * $Id: file.c,v 1.357 2004/02/03 17:59:00 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.
46 #ifdef HAVE_SYS_STAT_H
54 #ifdef NEED_SNPRINTF_H
55 # include "snprintf.h"
58 #ifdef NEED_STRERROR_H
62 #include <epan/epan.h>
63 #include <epan/filesystem.h>
67 #include <epan/packet.h>
73 #include "simple_dialog.h"
74 #include "progress_dlg.h"
76 #include "statusbar.h"
78 #include <epan/dfilter/dfilter.h>
79 #include <epan/conversation.h>
81 #include <epan/epan_dissect.h>
83 #include "tap_dfilter_dlg.h"
84 #include "packet-data.h"
87 gboolean auto_scroll_live;
90 static guint32 firstsec, firstusec;
91 static guint32 prevsec, prevusec;
92 static guint32 cum_bytes = 0;
94 static void read_packet(capture_file *cf, long offset);
96 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
97 gboolean refilter, gboolean redissect);
99 static gboolean match_protocol_tree(capture_file *cf, frame_data *fdata,
101 static void match_subtree_text(proto_node *node, gpointer data);
102 static gboolean match_summary_line(capture_file *cf, frame_data *fdata,
104 static gboolean match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
106 static gboolean match_ascii(capture_file *cf, frame_data *fdata,
108 static gboolean match_unicode(capture_file *cf, frame_data *fdata,
110 static gboolean match_binary(capture_file *cf, frame_data *fdata,
112 static gboolean match_dfilter(capture_file *cf, frame_data *fdata,
114 static gboolean find_packet(capture_file *cf,
115 gboolean (*match_function)(capture_file *, frame_data *, void *),
118 static char *cf_open_error_message(int err, gchar *err_info,
119 gboolean for_writing, int file_type);
120 static char *file_rename_error_message(int err);
121 static char *cf_write_error_message(int);
122 static char *cf_close_error_message(int err);
123 static gboolean copy_binary_file(char *from_filename, char *to_filename);
125 /* Update the progress bar this many times when reading a file. */
126 #define N_PROGBAR_UPDATES 100
128 /* Number of "frame_data" structures per memory chunk.
129 XXX - is this the right number? */
130 #define FRAME_DATA_CHUNK_SIZE 1024
137 gboolean print_all_levels;
138 gboolean print_hex_for_data;
140 gint format; /* text or PostScript */
145 cf_open(char *fname, gboolean is_tempfile, capture_file *cf)
153 wth = wtap_open_offline(fname, &err, &err_info, TRUE);
157 /* Find the size of the file. */
159 if (fstat(fd, &cf_stat) < 0) {
165 /* The open succeeded. Close whatever capture file we had open,
166 and fill in the information for this file. */
169 /* Initialize all data structures used for dissection. */
172 /* We're about to start reading the file. */
173 cf->state = FILE_READ_IN_PROGRESS;
177 cf->f_len = cf_stat.st_size;
179 /* Set the file name because we need it to set the follow stream filter.
180 XXX - is that still true? We need it for other reasons, though,
182 cf->filename = g_strdup(fname);
184 /* Indicate whether it's a permanent or temporary file. */
185 cf->is_tempfile = is_tempfile;
187 /* If it's a temporary capture buffer file, mark it as not saved. */
188 cf->user_saved = !is_tempfile;
190 cf->cd_t = wtap_file_type(cf->wth);
192 cf->displayed_count = 0;
193 cf->marked_count = 0;
194 cf->drops_known = FALSE;
198 cf->snap = wtap_snapshot_length(cf->wth);
200 /* Snapshot length not known. */
201 cf->has_snap = FALSE;
202 cf->snap = WTAP_MAX_PACKET_SIZE;
205 firstsec = 0, firstusec = 0;
206 prevsec = 0, prevusec = 0;
208 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
210 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
212 g_assert(cf->plist_chunk);
217 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
218 cf_open_error_message(err, err_info, FALSE, 0), fname);
222 /* Reset everything to a pristine state */
224 cf_close(capture_file *cf)
226 /* Die if we're in the middle of reading a file. */
227 g_assert(cf->state != FILE_READ_IN_PROGRESS);
229 /* Destroy all windows, which refer to the
230 capture file we're closing. */
231 destroy_cfile_wins();
237 /* We have no file open... */
238 if (cf->filename != NULL) {
239 /* If it's a temporary file, remove it. */
241 unlink(cf->filename);
242 g_free(cf->filename);
245 /* ...which means we have nothing to save. */
246 cf->user_saved = FALSE;
248 if (cf->plist_chunk != NULL) {
249 g_mem_chunk_destroy(cf->plist_chunk);
250 cf->plist_chunk = NULL;
252 if (cf->rfcode != NULL) {
253 dfilter_free(cf->rfcode);
257 cf->plist_end = NULL;
258 unselect_packet(cf); /* nothing to select */
259 cf->first_displayed = NULL;
260 cf->last_displayed = NULL;
262 /* No frame selected, no field in that frame selected. */
263 cf->current_frame = NULL;
264 cf->finfo_selected = NULL;
266 /* Clear the packet list. */
267 packet_list_freeze();
276 /* Clear any file-related status bar messages.
277 XXX - should be "clear *ALL* file-related status bar messages;
278 will there ever be more than one on the stack? */
279 statusbar_pop_file_msg();
281 /* Restore the standard title bar message. */
282 set_main_window_name("The Ethereal Network Analyzer");
284 /* Disable all menu items that make sense only if you have a capture. */
285 set_menus_for_capture_file(FALSE);
286 set_menus_for_unsaved_capture_file(FALSE);
287 set_menus_for_captured_packets(FALSE);
288 set_menus_for_selected_packet(cf);
289 set_menus_for_capture_in_progress(FALSE);
290 set_menus_for_selected_tree_row(cf);
292 /* We have no file open. */
293 cf->state = FILE_CLOSED;
296 /* Set the file name in the status line, in the name for the main window,
297 and in the name for the main window's icon. */
299 set_display_filename(capture_file *cf)
303 static const gchar done_fmt_nodrops[] = " File: %s %s %02u:%02u:%02u";
304 static const gchar done_fmt_drops[] = " File: %s %s %02u:%02u:%02u Drops: %u";
306 gchar *win_name_fmt = "%s - Ethereal";
310 name_ptr = cf_get_display_name(cf);
312 if (!cf->is_tempfile) {
313 /* Add this filename to the list of recent files in the "Recent Files" submenu */
314 add_menu_recent_capture_file(cf->filename);
317 if (cf->f_len/1024/1024 > 10) {
318 size_str = g_strdup_printf("%ld MB", cf->f_len/1024/1024);
319 } else if (cf->f_len/1024 > 10) {
320 size_str = g_strdup_printf("%ld KB", cf->f_len/1024);
322 size_str = g_strdup_printf("%ld bytes", cf->f_len);
325 if (cf->drops_known) {
326 done_msg = g_strdup_printf(done_fmt_drops, name_ptr, size_str,
327 cf->esec/3600, cf->esec%3600/60, cf->esec%60, cf->drops);
329 done_msg = g_strdup_printf(done_fmt_nodrops, name_ptr, size_str,
330 cf->esec/3600, cf->esec%3600/60, cf->esec%60);
332 statusbar_push_file_msg(done_msg);
335 msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
336 win_name = g_malloc(msg_len);
337 snprintf(win_name, msg_len, win_name_fmt, name_ptr);
338 set_main_window_name(win_name);
343 cf_read(capture_file *cf)
347 gchar *name_ptr, *load_msg, *load_fmt = "%s";
349 char errmsg_errno[1024+1];
350 gchar err_str[2048+1];
352 progdlg_t *progbar = NULL;
355 * XXX - should be "off_t", but Wiretap would need more work to handle
356 * the full size of "off_t" on platforms where it's more than a "long"
364 gchar status_str[100];
365 int progbar_nextstep;
369 reset_tap_listeners();
370 tap_dfilter_dlg_update();
371 name_ptr = get_basename(cf->filename);
373 load_msg = g_strdup_printf(" Loading: %s", name_ptr);
374 statusbar_push_file_msg(load_msg);
377 load_msg = g_strdup_printf(load_fmt, name_ptr);
379 /* Update the progress bar when it gets to this value. */
380 progbar_nextstep = 0;
381 /* When we reach the value that triggers a progress bar update,
382 bump that value by this amount. */
383 progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
389 packet_list_freeze();
392 g_get_current_time(&start_time);
394 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
395 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
396 when we update it, we have to run the GTK+ main loop to get it
397 to repaint what's pending, and doing so may involve an "ioctl()"
398 to see if there's any pending input from an X server, and doing
399 that for every packet can be costly, especially on a big file. */
400 if (data_offset >= progbar_nextstep) {
401 file_pos = lseek(cf->filed, 0, SEEK_CUR);
402 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
403 if (prog_val > 1.0) {
404 /* The file probably grew while we were reading it.
405 Update "cf->f_len", and try again. */
406 fd = wtap_fd(cf->wth);
407 if (fstat(fd, &cf_stat) >= 0) {
408 cf->f_len = cf_stat.st_size;
409 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
411 /* If it's still > 1, either the "fstat()" failed (in which
412 case there's not much we can do about it), or the file
413 *shrank* (in which case there's not much we can do about
414 it); just clip the progress value at 1.0. */
418 if (progbar == NULL) {
419 /* Create the progress bar if necessary */
420 progbar = delayed_create_progress_dlg("Loading", load_msg,
421 &stop_flag, &start_time, prog_val);
425 if (progbar != NULL) {
426 g_snprintf(status_str, sizeof(status_str),
427 "%luKB of %luKB", file_pos / 1024, cf->f_len / 1024);
428 update_progress_dlg(progbar, prog_val, status_str);
430 progbar_nextstep += progbar_quantum;
434 /* Well, the user decided to abort the read. Destroy the progress
435 bar, close the capture file, and return READ_ABORTED so our caller
436 can do whatever is appropriate when that happens. */
437 destroy_progress_dlg(progbar);
438 cf->state = FILE_READ_ABORTED; /* so that we're allowed to close it */
439 packet_list_thaw(); /* undo our freeze */
441 return (READ_ABORTED);
443 read_packet(cf, data_offset);
446 /* We're done reading the file; destroy the progress bar if it was created. */
450 destroy_progress_dlg(progbar);
452 /* We're done reading sequentially through the file. */
453 cf->state = FILE_READ_DONE;
455 /* Close the sequential I/O side, to free up memory it requires. */
456 wtap_sequential_close(cf->wth);
458 /* Allow the protocol dissectors to free up memory that they
459 * don't need after the sequential run-through of the packets. */
460 postseq_cleanup_all_protocols();
462 /* Set the file encapsulation type now; we don't know what it is until
463 we've looked at all the packets, as we don't know until then whether
464 there's more than one type (and thus whether it's
465 WTAP_ENCAP_PER_PACKET). */
466 cf->lnk_t = wtap_file_encap(cf->wth);
468 cf->current_frame = cf->first_displayed;
471 statusbar_pop_file_msg();
472 set_display_filename(cf);
474 /* Enable menu items that make sense if you have a capture file you've
476 set_menus_for_capture_file(TRUE);
477 set_menus_for_unsaved_capture_file(!cf->user_saved);
479 /* Enable menu items that make sense if you have some captured packets. */
480 set_menus_for_captured_packets(TRUE);
482 /* If we have any displayed packets to select, select the first of those
483 packets by making the first row the selected row. */
484 if (cf->first_displayed != NULL)
485 packet_list_select_row(0);
488 /* Put up a message box noting that the read failed somewhere along
489 the line. Don't throw out the stuff we managed to read, though,
493 case WTAP_ERR_UNSUPPORTED_ENCAP:
494 errmsg = "The capture file is for a network type that Ethereal doesn't support.";
497 case WTAP_ERR_CANT_READ:
498 errmsg = "An attempt to read from the file failed for"
499 " some unknown reason.";
502 case WTAP_ERR_SHORT_READ:
503 errmsg = "The capture file appears to have been cut short"
504 " in the middle of a packet.";
507 case WTAP_ERR_BAD_RECORD:
508 snprintf(errmsg_errno, sizeof(errmsg_errno),
509 "The capture file appears to be damaged or corrupt.\n(%s)",
511 errmsg = errmsg_errno;
515 snprintf(errmsg_errno, sizeof(errmsg_errno),
516 "An error occurred while reading the"
517 " capture file: %s.", wtap_strerror(err));
518 errmsg = errmsg_errno;
521 snprintf(err_str, sizeof err_str, errmsg);
522 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
525 return (READ_SUCCESS);
530 cf_start_tail(char *fname, gboolean is_tempfile, capture_file *cf)
534 err = cf_open(fname, is_tempfile, cf);
536 /* Disable menu items that make no sense if you're currently running
538 set_menus_for_capture_in_progress(TRUE);
540 /* Enable menu items that make sense if you have some captured
541 packets (yes, I know, we don't have any *yet*). */
542 set_menus_for_captured_packets(TRUE);
544 statusbar_push_file_msg(" <live capture in progress>");
550 cf_continue_tail(capture_file *cf, int to_read, int *err)
552 long data_offset = 0;
557 packet_list_freeze();
559 while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
560 if (cf->state == FILE_READ_ABORTED) {
561 /* Well, the user decided to exit Ethereal. Break out of the
562 loop, and let the code below (which is called even if there
563 aren't any packets left to read) exit. */
566 read_packet(cf, data_offset);
572 /* XXX - this cheats and looks inside the packet list to find the final
574 if (auto_scroll_live && cf->plist_end != NULL)
575 packet_list_moveto_end();
577 if (cf->state == FILE_READ_ABORTED) {
578 /* Well, the user decided to exit Ethereal. Return READ_ABORTED
579 so that our caller can kill off the capture child process;
580 this will cause an EOF on the pipe from the child, so
581 "cf_finish_tail()" will be called, and it will clean up
584 } else if (*err != 0) {
585 /* We got an error reading the capture file.
586 XXX - pop up a dialog box? */
589 return (READ_SUCCESS);
593 cf_finish_tail(capture_file *cf, int *err)
600 packet_list_freeze();
602 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
603 if (cf->state == FILE_READ_ABORTED) {
604 /* Well, the user decided to abort the read. Break out of the
605 loop, and let the code below (which is called even if there
606 aren't any packets left to read) exit. */
609 read_packet(cf, data_offset);
612 if (cf->state == FILE_READ_ABORTED) {
613 /* Well, the user decided to abort the read. We're only called
614 when the child capture process closes the pipe to us (meaning
615 it's probably exited), so we can just close the capture
616 file; we return READ_ABORTED so our caller can do whatever
617 is appropriate when that happens. */
623 if (auto_scroll_live && cf->plist_end != NULL)
624 /* XXX - this cheats and looks inside the packet list to find the final
626 packet_list_moveto_end();
628 /* We're done reading sequentially through the file. */
629 cf->state = FILE_READ_DONE;
631 /* we have to update the f_len field */
632 /* Find the size of the file. */
633 fd = wtap_fd(cf->wth);
634 if (fstat(fd, &cf_stat) >= 0) {
635 cf->f_len = cf_stat.st_size;
638 /* We're done reading sequentially through the file; close the
639 sequential I/O side, to free up memory it requires. */
640 wtap_sequential_close(cf->wth);
642 /* Allow the protocol dissectors to free up memory that they
643 * don't need after the sequential run-through of the packets. */
644 postseq_cleanup_all_protocols();
646 /* Set the file encapsulation type now; we don't know what it is until
647 we've looked at all the packets, as we don't know until then whether
648 there's more than one type (and thus whether it's
649 WTAP_ENCAP_PER_PACKET). */
650 cf->lnk_t = wtap_file_encap(cf->wth);
652 /* Pop the "<live capture in progress>" message off the status bar. */
653 statusbar_pop_file_msg();
655 set_display_filename(cf);
657 /* Enable menu items that make sense if you're not currently running
659 set_menus_for_capture_in_progress(FALSE);
661 /* Enable menu items that make sense if you have a capture file
662 you've finished reading. */
663 set_menus_for_capture_file(TRUE);
664 set_menus_for_unsaved_capture_file(!cf->user_saved);
667 /* We got an error reading the capture file.
668 XXX - pop up a dialog box? */
672 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
673 "%sNo packets captured!%s\n\n"
674 "As no data was captured, closing the %scapture file!",
675 simple_dialog_primary_start(), simple_dialog_primary_end(),
676 (cf->is_tempfile) ? "temporary " : "");
679 return (READ_SUCCESS);
682 #endif /* HAVE_LIBPCAP */
685 cf_get_display_name(capture_file *cf)
689 /* Return a name to use in displays */
690 if (!cf->is_tempfile) {
691 /* Get the last component of the file name, and use that. */
693 displayname = get_basename(cf->filename);
695 /* Add this filename to the list of recent files in the "Recent Files" submenu */
696 add_menu_recent_capture_file(cf->filename);
698 displayname="(No file)";
701 /* The file we read is a temporary file from a live capture;
702 we don't mention its name. */
703 displayname = "(Untitled)";
709 color_filter_t *colorf;
711 } apply_color_filter_args;
714 * If no color filter has been applied, apply this one.
715 * (The "if no color filter has been applied" is to handle the case where
716 * more than one color filter matches the packet.)
719 apply_color_filter(gpointer filter_arg, gpointer argp)
721 color_filter_t *colorf = filter_arg;
722 apply_color_filter_args *args = argp;
724 if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
725 if (dfilter_apply_edt(colorf->c_colorfilter, args->edt))
726 args->colorf = colorf;
731 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
732 union wtap_pseudo_header *pseudo_header, const guchar *buf,
735 apply_color_filter_args args;
737 gboolean create_proto_tree = FALSE;
740 /* just add some value here until we know if it is being displayed or not */
741 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
743 /* We don't yet have a color filter to apply. */
746 /* If we don't have the time stamp of the first packet in the
747 capture, it's because this is the first packet. Save the time
748 stamp of this packet as the time stamp of the first packet. */
749 if (!firstsec && !firstusec) {
750 firstsec = fdata->abs_secs;
751 firstusec = fdata->abs_usecs;
753 /* if this frames is marked as a reference time frame, reset
754 firstsec and firstusec to this frame */
755 if(fdata->flags.ref_time){
756 firstsec = fdata->abs_secs;
757 firstusec = fdata->abs_usecs;
760 /* If we don't have the time stamp of the previous displayed packet,
761 it's because this is the first displayed packet. Save the time
762 stamp of this packet as the time stamp of the previous displayed
764 if (!prevsec && !prevusec) {
765 prevsec = fdata->abs_secs;
766 prevusec = fdata->abs_usecs;
769 /* Get the time elapsed between the first packet and this packet. */
770 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
771 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
773 /* If it's greater than the current elapsed time, set the elapsed time
774 to it (we check for "greater than" so as not to be confused by
775 time moving backwards). */
776 if ((gint32)cf->esec < fdata->rel_secs
777 || ((gint32)cf->esec == fdata->rel_secs && (gint32)cf->eusec < fdata->rel_usecs)) {
778 cf->esec = fdata->rel_secs;
779 cf->eusec = fdata->rel_usecs;
782 /* Get the time elapsed between the previous displayed packet and
784 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
785 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
789 we have a display filter and are re-applying it;
791 we have a list of color filters;
793 we have tap listeners;
795 allocate a protocol tree root node, so that we'll construct
796 a protocol tree against which a filter expression can be
798 if ((cf->dfcode != NULL && refilter) || filter_list != NULL
799 || num_tap_filters != 0)
800 create_proto_tree = TRUE;
802 /* Dissect the frame. */
803 edt = epan_dissect_new(create_proto_tree, FALSE);
805 if (cf->dfcode != NULL && refilter) {
806 epan_dissect_prime_dfilter(edt, cf->dfcode);
809 filter_list_prime_edt(edt);
812 epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
813 tap_push_tapped_queue(edt);
815 /* If we have a display filter, apply it if we're refiltering, otherwise
816 leave the "passed_dfilter" flag alone.
818 If we don't have a display filter, set "passed_dfilter" to 1. */
819 if (cf->dfcode != NULL) {
821 if (cf->dfcode != NULL)
822 fdata->flags.passed_dfilter = dfilter_apply_edt(cf->dfcode, edt) ? 1 : 0;
824 fdata->flags.passed_dfilter = 1;
827 fdata->flags.passed_dfilter = 1;
829 /* If we have color filters, and the frame is to be displayed, apply
830 the color filters. */
831 if (fdata->flags.passed_dfilter) {
832 if (filter_list != NULL) {
834 g_slist_foreach(filter_list, apply_color_filter, &args);
839 if( (fdata->flags.passed_dfilter)
840 || (edt->pi.fd->flags.ref_time) ){
841 /* This frame either passed the display filter list or is marked as
842 a time reference frame. All time reference frames are displayed
843 even if they dont pass the display filter */
844 /* if this was a TIME REF frame we should reset the cul bytes field */
845 if(edt->pi.fd->flags.ref_time){
846 cum_bytes = fdata->pkt_len;
847 fdata->cum_bytes = cum_bytes;
850 /* increase cum_bytes with this packets length */
851 cum_bytes += fdata->pkt_len;
853 epan_dissect_fill_in_columns(edt);
855 /* If we haven't yet seen the first frame, this is it.
857 XXX - we must do this before we add the row to the display,
858 as, if the display's GtkCList's selection mode is
859 GTK_SELECTION_BROWSE, when the first entry is added to it,
860 "select_packet()" will be called, and it will fetch the row
861 data for the 0th row, and will get a null pointer rather than
862 "fdata", as "gtk_clist_append()" won't yet have returned and
863 thus "gtk_clist_set_row_data()" won't yet have been called.
865 We thus need to leave behind bread crumbs so that
866 "select_packet()" can find this frame. See the comment
867 in "select_packet()". */
868 if (cf->first_displayed == NULL)
869 cf->first_displayed = fdata;
871 /* This is the last frame we've seen so far. */
872 cf->last_displayed = fdata;
874 row = packet_list_append(cf->cinfo.col_data, fdata);
876 /* If the packet matches a color filter,
877 * store matching color_filter_t object in frame data. */
878 if (filter_list != NULL && (args.colorf != NULL)) {
879 /* add the matching colorfilter to the frame data */
880 fdata->color_filter = args.colorf;
881 /* If packet is marked, use colors from preferences */
882 if (fdata->flags.marked) {
883 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
884 } else /* if (filter_list != NULL && (args.colorf != NULL)) */ {
885 packet_list_set_colors(row, &(args.colorf->fg_color),
886 &(args.colorf->bg_color));
889 /* No color filter match */
890 fdata->color_filter = NULL;
891 if (fdata->flags.marked) {
892 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
896 /* Set the time of the previous displayed frame to the time of this
898 prevsec = fdata->abs_secs;
899 prevusec = fdata->abs_usecs;
901 cf->displayed_count++;
903 /* This frame didn't pass the display filter, so it's not being added
904 to the clist, and thus has no row. */
907 epan_dissect_free(edt);
912 read_packet(capture_file *cf, long offset)
914 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
915 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
916 const guchar *buf = wtap_buf_ptr(cf->wth);
919 frame_data *plist_end;
922 /* Allocate the next list entry, and add it to the list. */
923 fdata = g_mem_chunk_alloc(cf->plist_chunk);
928 fdata->pkt_len = phdr->len;
929 fdata->cap_len = phdr->caplen;
930 fdata->file_off = offset;
931 fdata->lnk_t = phdr->pkt_encap;
932 fdata->abs_secs = phdr->ts.tv_sec;
933 fdata->abs_usecs = phdr->ts.tv_usec;
934 fdata->flags.encoding = CHAR_ASCII;
935 fdata->flags.visited = 0;
936 fdata->flags.marked = 0;
937 fdata->flags.ref_time = 0;
941 edt = epan_dissect_new(TRUE, FALSE);
942 epan_dissect_prime_dfilter(edt, cf->rfcode);
943 epan_dissect_run(edt, pseudo_header, buf, fdata, NULL);
944 passed = dfilter_apply_edt(cf->rfcode, edt);
945 epan_dissect_free(edt);
948 plist_end = cf->plist_end;
949 fdata->prev = plist_end;
950 if (plist_end != NULL)
951 plist_end->next = fdata;
954 cf->plist_end = fdata;
957 fdata->num = cf->count;
958 add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE);
960 /* XXX - if we didn't have read filters, or if we could avoid
961 allocating the "frame_data" structure until we knew whether
962 the frame passed the read filter, we could use a G_ALLOC_ONLY
965 ...but, at least in one test I did, where I just made the chunk
966 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
967 seem to save a noticeable amount of time or space. */
968 g_mem_chunk_free(cf->plist_chunk, fdata);
973 filter_packets(capture_file *cf, gchar *dftext)
976 char *filter_new = dftext ? dftext : "";
977 char *filter_old = cf->dfilter ? cf->dfilter : "";
980 /* if new filter equals old one, do nothing */
981 if (strcmp(filter_new, filter_old) == 0) {
985 if (dftext == NULL) {
986 /* The new filter is an empty filter (i.e., display all packets). */
990 * We have a filter; make a copy of it (as we'll be saving it),
991 * and try to compile it.
993 dftext = g_strdup(dftext);
994 if (!dfilter_compile(dftext, &dfcode)) {
995 /* The attempt failed; report an error. */
996 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
997 "%sInvalid display filter: \"%s\"!%s\n"
999 "Unable to parse display filter string (%s),\n"
1000 "see help for correct display filter syntax.",
1001 simple_dialog_primary_start(), dftext, simple_dialog_primary_end(),
1008 if (dfcode == NULL) {
1009 /* Yes - free the filter text, and set it to null. */
1015 /* We have a valid filter. Replace the current filter. */
1016 if (cf->dfilter != NULL)
1017 g_free(cf->dfilter);
1018 cf->dfilter = dftext;
1019 if (cf->dfcode != NULL)
1020 dfilter_free(cf->dfcode);
1021 cf->dfcode = dfcode;
1023 /* Now rescan the packet list, applying the new filter, but not
1024 throwing away information constructed on a previous pass. */
1025 if (dftext == NULL) {
1026 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1028 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1034 colorize_packets(capture_file *cf)
1036 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1040 reftime_packets(capture_file *cf)
1042 rescan_packets(cf, "Updating Reftime", "all packets", FALSE, FALSE);
1046 redissect_packets(capture_file *cf)
1048 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1051 /* Rescan the list of packets, reconstructing the CList.
1053 "action" describes why we're doing this; it's used in the progress
1056 "action_item" describes what we're doing; it's used in the progress
1059 "refilter" is TRUE if we need to re-evaluate the filter expression.
1061 "redissect" is TRUE if we need to make the dissectors reconstruct
1062 any state information they have (because a preference that affects
1063 some dissector has changed, meaning some dissector might construct
1064 its state differently from the way it was constructed the last time). */
1066 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1067 gboolean refilter, gboolean redissect)
1070 progdlg_t *progbar = NULL;
1075 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1076 int selected_row, prev_row, preceding_row, following_row;
1077 gboolean selected_frame_seen;
1080 GTimeVal start_time;
1081 gchar status_str[100];
1082 int progbar_nextstep;
1083 int progbar_quantum;
1086 reset_tap_listeners();
1087 /* Which frame, if any, is the currently selected frame?
1088 XXX - should the selected frame or the focus frame be the "current"
1089 frame, that frame being the one from which "Find Frame" searches
1091 selected_frame = cf->current_frame;
1093 /* We don't yet know what row that frame will be on, if any, after we
1094 rebuild the clist, however. */
1098 /* We need to re-initialize all the state information that protocols
1099 keep, because some preference that controls a dissector has changed,
1100 which might cause the state information to be constructed differently
1101 by that dissector. */
1103 /* Initialize all data structures used for dissection. */
1107 /* Freeze the packet list while we redo it, so we don't get any
1108 screen updates while it happens. */
1109 packet_list_freeze();
1112 packet_list_clear();
1114 /* We don't yet know which will be the first and last frames displayed. */
1115 cf->first_displayed = NULL;
1116 cf->last_displayed = NULL;
1118 /* We currently don't display any packets */
1119 cf->displayed_count = 0;
1121 /* Iterate through the list of frames. Call a routine for each frame
1122 to check whether it should be displayed and, if so, add it to
1123 the display list. */
1129 /* Update the progress bar when it gets to this value. */
1130 progbar_nextstep = 0;
1131 /* When we reach the value that triggers a progress bar update,
1132 bump that value by this amount. */
1133 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1134 /* Count of packets at which we've looked. */
1138 g_get_current_time(&start_time);
1140 row = -1; /* no previous row yet */
1145 preceding_frame = NULL;
1147 following_frame = NULL;
1149 selected_frame_seen = FALSE;
1151 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1152 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1153 when we update it, we have to run the GTK+ main loop to get it
1154 to repaint what's pending, and doing so may involve an "ioctl()"
1155 to see if there's any pending input from an X server, and doing
1156 that for every packet can be costly, especially on a big file. */
1157 if (count >= progbar_nextstep) {
1158 /* let's not divide by zero. I should never be started
1159 * with count == 0, so let's assert that
1161 g_assert(cf->count > 0);
1162 prog_val = (gfloat) count / cf->count;
1164 if (progbar == NULL)
1165 /* Create the progress bar if necessary */
1166 progbar = delayed_create_progress_dlg(action, action_item, &stop_flag,
1167 &start_time, prog_val);
1169 if (progbar != NULL) {
1170 g_snprintf(status_str, sizeof(status_str),
1171 "%4u of %u frames", count, cf->count);
1172 update_progress_dlg(progbar, prog_val, status_str);
1175 progbar_nextstep += progbar_quantum;
1179 /* Well, the user decided to abort the filtering. Just stop.
1181 XXX - go back to the previous filter? Users probably just
1182 want not to wait for a filtering operation to finish;
1183 unless we cancel by having no filter, reverting to the
1184 previous filter will probably be even more expensive than
1185 continuing the filtering, as it involves going back to the
1186 beginning and filtering, and even with no filter we currently
1187 have to re-generate the entire clist, which is also expensive.
1189 I'm not sure what Network Monitor does, but it doesn't appear
1190 to give you an unfiltered display if you cancel. */
1197 /* Since all state for the frame was destroyed, mark the frame
1198 * as not visited, free the GSList referring to the state
1199 * data (the per-frame data itself was freed by
1200 * "init_dissection()"), and null out the GSList pointer. */
1201 fdata->flags.visited = 0;
1203 g_slist_free(fdata->pfd);
1208 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1209 cf->pd, fdata->cap_len, &err, &err_info)) {
1210 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1211 cf_read_error_message(err, err_info), cf->filename);
1215 /* If the previous frame is displayed, and we haven't yet seen the
1216 selected frame, remember that frame - it's the closest one we've
1217 yet seen before the selected frame. */
1218 if (prev_row != -1 && !selected_frame_seen) {
1219 preceding_row = prev_row;
1220 preceding_frame = prev_frame;
1222 row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
1225 /* If this frame is displayed, and this is the first frame we've
1226 seen displayed after the selected frame, remember this frame -
1227 it's the closest one we've yet seen at or after the selected
1229 if (row != -1 && selected_frame_seen && following_row == -1) {
1230 following_row = row;
1231 following_frame = fdata;
1233 if (fdata == selected_frame) {
1235 selected_frame_seen = TRUE;
1238 /* Remember this row/frame - it'll be the previous row/frame
1239 on the next pass through the loop. */
1245 /* Clear out what remains of the visited flags and per-frame data
1248 XXX - that may cause various forms of bogosity when dissecting
1249 these frames, as they won't have been seen by this sequential
1250 pass, but the only alternative I see is to keep scanning them
1251 even though the user requested that the scan stop, and that
1252 would leave the user stuck with an Ethereal grinding on
1253 until it finishes. Should we just stick them with that? */
1254 for (; fdata != NULL; fdata = fdata->next) {
1255 fdata->flags.visited = 0;
1257 g_slist_free(fdata->pfd);
1263 /* We're done filtering the packets; destroy the progress bar if it
1265 if (progbar != NULL)
1266 destroy_progress_dlg(progbar);
1268 /* Unfreeze the packet list. */
1271 if (selected_row == -1) {
1272 /* The selected frame didn't pass the filter. */
1273 if (selected_frame == NULL) {
1274 /* That's because there *was* no selected frame. Make the first
1275 displayed frame the current frame. */
1278 /* Find the nearest displayed frame to the selected frame (whether
1279 it's before or after that frame) and make that the current frame.
1280 If the next and previous displayed frames are equidistant from the
1281 selected frame, choose the next one. */
1282 g_assert(following_frame == NULL ||
1283 following_frame->num >= selected_frame->num);
1284 g_assert(preceding_frame == NULL ||
1285 preceding_frame->num <= selected_frame->num);
1286 if (following_frame == NULL) {
1287 /* No frame after the selected frame passed the filter, so we
1288 have to select the last displayed frame before the selected
1290 selected_row = preceding_row;
1291 } else if (preceding_frame == NULL) {
1292 /* No frame before the selected frame passed the filter, so we
1293 have to select the first displayed frame after the selected
1295 selected_row = following_row;
1297 /* Choose the closer of the last displayed frame before the
1298 selected frame and the first displayed frame after the
1299 selected frame; in case of a tie, choose the first displayed
1300 frame after the selected frame. */
1301 if (following_frame->num - selected_frame->num <=
1302 selected_frame->num - preceding_frame->num) {
1303 selected_row = following_row;
1305 /* The previous frame is closer to the selected frame than the
1307 selected_row = preceding_row;
1313 if (selected_row == -1) {
1314 /* There are no frames displayed at all. */
1315 unselect_packet(cf);
1317 /* Either the frame that was selected passed the filter, or we've
1318 found the nearest displayed frame to that frame. Select it, make
1319 it the focus row, and make it visible. */
1320 packet_list_set_selected_row(selected_row);
1331 process_specified_packets(capture_file *cf, packet_range_t *range,
1332 const char *string1, const char *string2,
1333 gboolean (*callback)(capture_file *, frame_data *,
1334 union wtap_pseudo_header *, const guint8 *, void *),
1335 void *callback_args)
1340 union wtap_pseudo_header pseudo_header;
1341 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
1342 psp_return_t ret = PSP_FINISHED;
1344 progdlg_t *progbar = NULL;
1347 gboolean progbar_stop_flag;
1348 GTimeVal progbar_start_time;
1349 gchar progbar_status_str[100];
1350 int progbar_nextstep;
1351 int progbar_quantum;
1352 range_process_e process_this;
1354 /* Update the progress bar when it gets to this value. */
1355 progbar_nextstep = 0;
1356 /* When we reach the value that triggers a progress bar update,
1357 bump that value by this amount. */
1358 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1359 /* Count of packets at which we've looked. */
1362 progbar_stop_flag = FALSE;
1363 g_get_current_time(&progbar_start_time);
1365 packet_range_process_init(range);
1367 /* Iterate through the list of packets, printing the packets that
1368 were selected by the current display filter. */
1369 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1370 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1371 when we update it, we have to run the GTK+ main loop to get it
1372 to repaint what's pending, and doing so may involve an "ioctl()"
1373 to see if there's any pending input from an X server, and doing
1374 that for every packet can be costly, especially on a big file. */
1375 if (progbar_count >= progbar_nextstep) {
1376 /* let's not divide by zero. I should never be started
1377 * with count == 0, so let's assert that
1379 g_assert(cf->count > 0);
1380 progbar_val = (gfloat) progbar_count / cf->count;
1382 if (progbar == NULL)
1383 /* Create the progress bar if necessary */
1384 progbar = delayed_create_progress_dlg(string1, string2,
1386 &progbar_start_time,
1389 if (progbar != NULL) {
1390 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
1391 "%4u of %u packets", progbar_count, cf->count);
1392 update_progress_dlg(progbar, progbar_val, progbar_status_str);
1395 progbar_nextstep += progbar_quantum;
1398 if (progbar_stop_flag) {
1399 /* Well, the user decided to abort the operation. Just stop,
1400 and arrange to return TRUE to our caller, so they know it
1401 was stopped explicitly. */
1408 /* do we have to process this packet? */
1409 process_this = packet_range_process_packet(range, fdata);
1410 if (process_this == range_process_next) {
1411 /* this packet uninteresting, continue with next one */
1413 } else if (process_this == range_processing_finished) {
1414 /* all interesting packets processed, stop the loop */
1418 /* Get the packet */
1419 if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1420 pd, fdata->cap_len, &err, &err_info)) {
1421 /* Attempt to get the packet failed. */
1422 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1423 cf_read_error_message(err, err_info), cf->filename);
1427 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
1428 /* Callback failed. We assume it reported the error appropriately. */
1434 /* We're done printing the packets; destroy the progress bar if
1436 if (progbar != NULL)
1437 destroy_progress_dlg(progbar);
1443 retap_packet(capture_file *cf _U_, frame_data *fdata,
1444 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1447 epan_dissect_t *edt;
1449 /* If we have tap listeners, allocate a protocol tree root node, so that
1450 we'll construct a protocol tree against which a filter expression can
1452 edt = epan_dissect_new(num_tap_filters != 0, FALSE);
1453 tap_queue_init(edt);
1454 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1455 tap_push_tapped_queue(edt);
1456 epan_dissect_free(edt);
1462 retap_packets(capture_file *cf)
1464 packet_range_t range;
1466 /* Reset the tap listeners. */
1467 reset_tap_listeners();
1469 /* Iterate through the list of packets, dissecting all packets and
1470 re-running the taps. */
1471 packet_range_init(&range);
1472 packet_range_process_init(&range);
1473 switch (process_specified_packets(cf, &range, "Refiltering statistics on",
1474 "all packets", retap_packet,
1477 /* Completed successfully. */
1481 /* Well, the user decided to abort the refiltering.
1482 Return FALSE so our caller knows they did that. */
1486 /* Error while retapping. */
1494 print_args_t *print_args;
1496 gboolean print_separator;
1500 } print_callback_args_t;
1503 print_packet(capture_file *cf, frame_data *fdata,
1504 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1507 print_callback_args_t *args = argsp;
1508 epan_dissect_t *edt;
1515 if (args->print_args->print_summary) {
1516 /* Fill in the column information, but don't bother creating
1517 the logical protocol tree. */
1518 edt = epan_dissect_new(FALSE, FALSE);
1519 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
1520 epan_dissect_fill_in_columns(edt);
1521 cp = &args->line_buf[0];
1523 for (i = 0; i < cf->cinfo.num_cols; i++) {
1524 /* Find the length of the string for this column. */
1525 column_len = strlen(cf->cinfo.col_data[i]);
1526 if (args->col_widths[i] > column_len)
1527 column_len = args->col_widths[i];
1529 /* Make sure there's room in the line buffer for the column; if not,
1530 double its length. */
1531 line_len += column_len + 1; /* "+1" for space */
1532 if (line_len > args->line_buf_len) {
1533 cp_off = cp - args->line_buf;
1534 args->line_buf_len = 2 * line_len;
1535 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
1536 cp = args->line_buf + cp_off;
1539 /* Right-justify the packet number column. */
1540 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1541 sprintf(cp, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
1543 sprintf(cp, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
1545 if (i != cf->cinfo.num_cols - 1)
1549 print_line(args->print_fh, 0, args->print_args->format, args->line_buf);
1551 if (args->print_separator)
1552 print_line(args->print_fh, 0, args->print_args->format, "");
1554 /* Create the logical protocol tree, complete with the display
1555 representation of the items; we don't need the columns here,
1557 edt = epan_dissect_new(TRUE, TRUE);
1558 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1560 /* Print the information in that tree. */
1561 proto_tree_print(args->print_args, edt, args->print_fh);
1563 if (args->print_args->print_hex) {
1564 /* Print the full packet data as hex. */
1565 print_hex_data(args->print_fh, args->print_args->format, edt);
1568 /* Print a blank line if we print anything after this. */
1569 args->print_separator = TRUE;
1570 } /* if (print_summary) */
1571 epan_dissect_free(edt);
1573 return !ferror(args->print_fh);
1577 print_packets(capture_file *cf, print_args_t *print_args)
1580 print_callback_args_t callback_args;
1588 callback_args.print_fh = open_print_dest(print_args->to_file,
1590 if (callback_args.print_fh == NULL)
1591 return PP_OPEN_ERROR; /* attempt to open destination failed */
1593 print_preamble(callback_args.print_fh, print_args->format);
1594 if (ferror(callback_args.print_fh)) {
1595 close_print_dest(print_args->to_file, callback_args.print_fh);
1596 return PP_WRITE_ERROR;
1599 callback_args.print_args = print_args;
1600 callback_args.print_separator = FALSE;
1601 callback_args.line_buf = NULL;
1602 callback_args.line_buf_len = 256;
1603 callback_args.col_widths = NULL;
1604 if (print_args->print_summary) {
1605 /* We're printing packet summaries. Allocate the line buffer at
1606 its initial length. */
1607 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
1609 /* Find the widths for each of the columns - maximum of the
1610 width of the title and the width of the data - and print
1611 the column titles. */
1612 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1613 cp = &callback_args.line_buf[0];
1615 for (i = 0; i < cf->cinfo.num_cols; i++) {
1616 /* Don't pad the last column. */
1617 if (i == cf->cinfo.num_cols - 1)
1618 callback_args.col_widths[i] = 0;
1620 callback_args.col_widths[i] = strlen(cf->cinfo.col_title[i]);
1621 data_width = get_column_char_width(get_column_format(i));
1622 if (data_width > callback_args.col_widths[i])
1623 callback_args.col_widths[i] = data_width;
1626 /* Find the length of the string for this column. */
1627 column_len = strlen(cf->cinfo.col_title[i]);
1628 if (callback_args.col_widths[i] > column_len)
1629 column_len = callback_args.col_widths[i];
1631 /* Make sure there's room in the line buffer for the column; if not,
1632 double its length. */
1633 line_len += column_len + 1; /* "+1" for space */
1634 if (line_len > callback_args.line_buf_len) {
1635 cp_off = cp - callback_args.line_buf;
1636 callback_args.line_buf_len = 2 * line_len;
1637 callback_args.line_buf = g_realloc(callback_args.line_buf,
1638 callback_args.line_buf_len + 1);
1639 cp = callback_args.line_buf + cp_off;
1642 /* Right-justify the packet number column. */
1643 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1644 sprintf(cp, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1646 sprintf(cp, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1648 if (i != cf->cinfo.num_cols - 1)
1652 print_line(callback_args.print_fh, 0, print_args->format,
1653 callback_args.line_buf);
1654 } /* if (print_summary) */
1656 /* Iterate through the list of packets, printing the packets we were
1658 ret = process_specified_packets(cf, &print_args->range, "Printing",
1659 "selected packets", print_packet,
1662 if (callback_args.col_widths != NULL)
1663 g_free(callback_args.col_widths);
1664 if (callback_args.line_buf != NULL)
1665 g_free(callback_args.line_buf);
1670 /* Completed successfully. */
1674 /* Well, the user decided to abort the printing.
1676 XXX - note that what got generated before they did that
1677 will get printed if we're piping to a print program; we'd
1678 have to write to a file and then hand that to the print
1679 program to make it actually not print anything. */
1683 /* Error while printing.
1685 XXX - note that what got generated before they did that
1686 will get printed if we're piping to a print program; we'd
1687 have to write to a file and then hand that to the print
1688 program to make it actually not print anything. */
1689 close_print_dest(print_args->to_file, callback_args.print_fh);
1690 return PP_WRITE_ERROR;
1693 print_finale(callback_args.print_fh, print_args->format);
1694 if (ferror(callback_args.print_fh)) {
1695 close_print_dest(print_args->to_file, callback_args.print_fh);
1696 return PP_WRITE_ERROR;
1699 close_print_dest(print_args->to_file, callback_args.print_fh);
1704 /* Scan through the packet list and change all columns that use the
1705 "command-line-specified" time stamp format to use the current
1706 value of that format. */
1708 change_time_formats(capture_file *cf)
1711 progdlg_t *progbar = NULL;
1717 GTimeVal start_time;
1718 gchar status_str[100];
1719 int progbar_nextstep;
1720 int progbar_quantum;
1722 gboolean sorted_by_frame_column;
1724 /* Are there any columns with time stamps in the "command-line-specified"
1727 XXX - we have to force the "column is writable" flag on, as it
1728 might be off from the last frame that was dissected. */
1729 col_set_writable(&cf->cinfo, TRUE);
1730 if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
1731 /* No, there aren't any columns in that format, so we have no work
1735 first = cf->cinfo.col_first[COL_CLS_TIME];
1736 g_assert(first >= 0);
1737 last = cf->cinfo.col_last[COL_CLS_TIME];
1739 /* Freeze the packet list while we redo it, so we don't get any
1740 screen updates while it happens. */
1741 packet_list_freeze();
1743 /* Update the progress bar when it gets to this value. */
1744 progbar_nextstep = 0;
1745 /* When we reach the value that triggers a progress bar update,
1746 bump that value by this amount. */
1747 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1748 /* Count of packets at which we've looked. */
1751 /* If the rows are currently sorted by the frame column then we know
1752 * the row number of each packet: it's the row number of the previously
1753 * displayed packet + 1.
1755 * Otherwise, if the display is sorted by a different column then we have
1756 * to use the O(N) packet_list_find_row_from_data() (thus making the job
1757 * of changing the time display format O(N**2)).
1759 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
1760 * the row number and walks that many elements down the clist to find
1761 * the appropriate element.)
1763 sorted_by_frame_column = FALSE;
1764 for (i = 0; i < cf->cinfo.num_cols; i++) {
1765 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1767 sorted_by_frame_column = (i == packet_list_get_sort_column());
1773 g_get_current_time(&start_time);
1775 /* Iterate through the list of packets, checking whether the packet
1776 is in a row of the summary list and, if so, whether there are
1777 any columns that show the time in the "command-line-specified"
1778 format and, if so, update that row. */
1779 for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
1780 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1781 when we update it, we have to run the GTK+ main loop to get it
1782 to repaint what's pending, and doing so may involve an "ioctl()"
1783 to see if there's any pending input from an X server, and doing
1784 that for every packet can be costly, especially on a big file. */
1785 if (count >= progbar_nextstep) {
1786 /* let's not divide by zero. I should never be started
1787 * with count == 0, so let's assert that
1789 g_assert(cf->count > 0);
1791 prog_val = (gfloat) count / cf->count;
1793 if (progbar == NULL)
1794 /* Create the progress bar if necessary */
1795 progbar = delayed_create_progress_dlg("Changing", "time display",
1796 &stop_flag, &start_time, prog_val);
1798 if (progbar != NULL) {
1799 g_snprintf(status_str, sizeof(status_str),
1800 "%4u of %u packets", count, cf->count);
1801 update_progress_dlg(progbar, prog_val, status_str);
1804 progbar_nextstep += progbar_quantum;
1808 /* Well, the user decided to abort the redisplay. Just stop.
1810 XXX - this leaves the time field in the old format in
1811 frames we haven't yet processed. So it goes; should we
1812 simply not offer them the option of stopping? */
1818 /* Find what row this packet is in. */
1819 if (!sorted_by_frame_column) {
1820 /* This function is O(N), so we try to avoid using it... */
1821 row = packet_list_find_row_from_data(fdata);
1823 /* ...which we do by maintaining a count of packets that are
1824 being displayed (i.e., that have passed the display filter),
1825 and using the current value of that count as the row number
1826 (which is why we can only do it when the display is sorted
1827 by the frame number). */
1828 if (fdata->flags.passed_dfilter)
1835 /* This packet is in the summary list, on row "row". */
1837 for (i = first; i <= last; i++) {
1838 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1839 /* This is one of the columns that shows the time in
1840 "command-line-specified" format; update it. */
1841 cf->cinfo.col_buf[i][0] = '\0';
1842 col_set_cls_time(fdata, &cf->cinfo, i);
1843 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
1849 /* We're done redisplaying the packets; destroy the progress bar if it
1851 if (progbar != NULL)
1852 destroy_progress_dlg(progbar);
1854 /* Set the column widths of those columns that show the time in
1855 "command-line-specified" format. */
1856 for (i = first; i <= last; i++) {
1857 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1858 packet_list_set_cls_time_width(i);
1862 /* Unfreeze the packet list. */
1870 gboolean frame_matched;
1874 find_packet_protocol_tree(capture_file *cf, const char *string)
1878 mdata.string = string;
1879 mdata.string_len = strlen(string);
1880 return find_packet(cf, match_protocol_tree, &mdata);
1884 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
1886 match_data *mdata = criterion;
1887 epan_dissect_t *edt;
1889 /* Construct the protocol tree, including the displayed text */
1890 edt = epan_dissect_new(TRUE, TRUE);
1891 /* We don't need the column information */
1892 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
1894 /* Iterate through all the nodes, seeing if they have text that matches. */
1896 mdata->frame_matched = FALSE;
1897 proto_tree_children_foreach(edt->tree, match_subtree_text, mdata);
1898 epan_dissect_free(edt);
1899 return mdata->frame_matched;
1903 match_subtree_text(proto_node *node, gpointer data)
1905 match_data *mdata = (match_data*) data;
1906 const gchar *string = mdata->string;
1907 size_t string_len = mdata->string_len;
1908 capture_file *cf = mdata->cf;
1909 field_info *fi = PITEM_FINFO(node);
1910 gchar label_str[ITEM_LABEL_LENGTH];
1917 if (mdata->frame_matched) {
1918 /* We already had a match; don't bother doing any more work. */
1922 /* Don't match invisible entries. */
1926 /* was a free format label produced? */
1928 label_ptr = fi->rep->representation;
1930 /* no, make a generic label */
1931 label_ptr = label_str;
1932 proto_item_fill_label(fi, label_str);
1935 /* Does that label match? */
1936 label_len = strlen(label_ptr);
1937 for (i = 0; i < label_len; i++) {
1938 c_char = label_ptr[i];
1940 c_char = toupper(c_char);
1941 if (c_char == string[c_match]) {
1943 if (c_match == string_len) {
1944 /* No need to look further; we have a match */
1945 mdata->frame_matched = TRUE;
1952 /* Recurse into the subtree, if it exists */
1953 if (node->first_child != NULL)
1954 proto_tree_children_foreach(node, match_subtree_text, mdata);
1958 find_packet_summary_line(capture_file *cf, const char *string)
1962 mdata.string = string;
1963 mdata.string_len = strlen(string);
1964 return find_packet(cf, match_summary_line, &mdata);
1968 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
1970 match_data *mdata = criterion;
1971 const gchar *string = mdata->string;
1972 size_t string_len = mdata->string_len;
1973 epan_dissect_t *edt;
1974 const char *info_column;
1975 size_t info_column_len;
1976 gboolean frame_matched = FALSE;
1982 /* Don't bother constructing the protocol tree */
1983 edt = epan_dissect_new(FALSE, FALSE);
1984 /* Get the column information */
1985 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
1987 /* Find the Info column */
1988 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
1989 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
1990 /* Found it. See if we match. */
1991 info_column = edt->pi.cinfo->col_data[colx];
1992 info_column_len = strlen(info_column);
1993 for (i = 0; i < info_column_len; i++) {
1994 c_char = info_column[i];
1996 c_char = toupper(c_char);
1997 if (c_char == string[c_match]) {
1999 if (c_match == string_len) {
2000 frame_matched = TRUE;
2009 epan_dissect_free(edt);
2010 return frame_matched;
2016 } cbs_t; /* "Counted byte string" */
2019 find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
2024 info.data_len = string_size;
2026 /* String or hex search? */
2028 /* String search - what type of string? */
2029 switch (cf->scs_type) {
2031 case SCS_ASCII_AND_UNICODE:
2032 return find_packet(cf, match_ascii_and_unicode, &info);
2035 return find_packet(cf, match_ascii, &info);
2038 return find_packet(cf, match_unicode, &info);
2041 g_assert_not_reached();
2045 return find_packet(cf, match_binary, &info);
2049 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2051 cbs_t *info = criterion;
2052 const char *ascii_text = info->data;
2053 size_t textlen = info->data_len;
2054 gboolean frame_matched;
2060 frame_matched = FALSE;
2061 buf_len = fdata->pkt_len;
2062 for (i = 0; i < buf_len; i++) {
2065 c_char = toupper(c_char);
2067 if (c_char == ascii_text[c_match]) {
2069 if (c_match == textlen) {
2070 frame_matched = TRUE;
2077 return frame_matched;
2081 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2083 cbs_t *info = criterion;
2084 const char *ascii_text = info->data;
2085 size_t textlen = info->data_len;
2086 gboolean frame_matched;
2092 frame_matched = FALSE;
2093 buf_len = fdata->pkt_len;
2094 for (i = 0; i < buf_len; i++) {
2097 c_char = toupper(c_char);
2098 if (c_char == ascii_text[c_match]) {
2100 if (c_match == textlen) {
2101 frame_matched = TRUE;
2107 return frame_matched;
2111 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2113 cbs_t *info = criterion;
2114 const char *ascii_text = info->data;
2115 size_t textlen = info->data_len;
2116 gboolean frame_matched;
2122 frame_matched = FALSE;
2123 buf_len = fdata->pkt_len;
2124 for (i = 0; i < buf_len; i++) {
2127 c_char = toupper(c_char);
2128 if (c_char == ascii_text[c_match]) {
2131 if (c_match == textlen) {
2132 frame_matched = TRUE;
2138 return frame_matched;
2142 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
2144 cbs_t *info = criterion;
2145 const guint8 *binary_data = info->data;
2146 size_t datalen = info->data_len;
2147 gboolean frame_matched;
2152 frame_matched = FALSE;
2153 buf_len = fdata->pkt_len;
2154 for (i = 0; i < buf_len; i++) {
2155 if (cf->pd[i] == binary_data[c_match]) {
2157 if (c_match == datalen) {
2158 frame_matched = TRUE;
2164 return frame_matched;
2168 find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
2170 return find_packet(cf, match_dfilter, sfcode);
2174 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
2176 dfilter_t *sfcode = criterion;
2177 epan_dissect_t *edt;
2178 gboolean frame_matched;
2180 edt = epan_dissect_new(TRUE, FALSE);
2181 epan_dissect_prime_dfilter(edt, sfcode);
2182 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2183 frame_matched = dfilter_apply_edt(sfcode, edt);
2184 epan_dissect_free(edt);
2185 return frame_matched;
2189 find_packet(capture_file *cf,
2190 gboolean (*match_function)(capture_file *, frame_data *, void *),
2193 frame_data *start_fd;
2195 frame_data *new_fd = NULL;
2196 progdlg_t *progbar = NULL;
2203 GTimeVal start_time;
2204 gchar status_str[100];
2205 int progbar_nextstep;
2206 int progbar_quantum;
2208 start_fd = cf->current_frame;
2209 if (start_fd != NULL) {
2210 /* Iterate through the list of packets, starting at the packet we've
2211 picked, calling a routine to run the filter on the packet, see if
2212 it matches, and stop if so. */
2216 progbar_nextstep = 0;
2217 /* When we reach the value that triggers a progress bar update,
2218 bump that value by this amount. */
2219 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2222 g_get_current_time(&start_time);
2226 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2227 when we update it, we have to run the GTK+ main loop to get it
2228 to repaint what's pending, and doing so may involve an "ioctl()"
2229 to see if there's any pending input from an X server, and doing
2230 that for every packet can be costly, especially on a big file. */
2231 if (count >= progbar_nextstep) {
2232 /* let's not divide by zero. I should never be started
2233 * with count == 0, so let's assert that
2235 g_assert(cf->count > 0);
2237 prog_val = (gfloat) count / cf->count;
2239 /* Create the progress bar if necessary */
2240 if (progbar == NULL)
2241 progbar = delayed_create_progress_dlg("Searching", cf->sfilter,
2242 &stop_flag, &start_time, prog_val);
2244 if (progbar != NULL) {
2245 g_snprintf(status_str, sizeof(status_str),
2246 "%4u of %u packets", count, cf->count);
2247 update_progress_dlg(progbar, prog_val, status_str);
2250 progbar_nextstep += progbar_quantum;
2254 /* Well, the user decided to abort the search. Go back to the
2255 frame where we started. */
2260 /* Go past the current frame. */
2261 if (cf->sbackward) {
2262 /* Go on to the previous frame. */
2263 fdata = fdata->prev;
2265 fdata = cf->plist_end; /* wrap around */
2267 /* Go on to the next frame. */
2268 fdata = fdata->next;
2270 fdata = cf->plist; /* wrap around */
2275 /* Is this packet in the display? */
2276 if (fdata->flags.passed_dfilter) {
2277 /* Yes. Load its data. */
2278 if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
2279 cf->pd, fdata->cap_len, &err, &err_info)) {
2280 /* Read error. Report the error, and go back to the frame
2281 where we started. */
2282 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2283 cf_read_error_message(err, err_info), cf->filename);
2288 /* Does it match the search criterion? */
2289 if ((*match_function)(cf, fdata, criterion)) {
2291 break; /* found it! */
2295 if (fdata == start_fd) {
2296 /* We're back to the frame we were on originally, and that frame
2297 doesn't match the search filter. The search failed. */
2302 /* We're done scanning the packets; destroy the progress bar if it
2304 if (progbar != NULL)
2305 destroy_progress_dlg(progbar);
2308 if (new_fd != NULL) {
2309 /* We found a frame. Find what row it's in. */
2310 row = packet_list_find_row_from_data(new_fd);
2311 g_assert(row != -1);
2313 /* Select that row, make it the focus row, and make it visible. */
2314 packet_list_set_selected_row(row);
2315 return TRUE; /* success */
2317 return FALSE; /* failure */
2321 goto_frame(capture_file *cf, guint fnumber)
2326 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
2329 if (fdata == NULL) {
2330 /* we didn't find a packet with that packet number */
2331 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2332 "There is no packet with that packet number.");
2333 return FALSE; /* we failed to go to that packet */
2335 if (!fdata->flags.passed_dfilter) {
2336 /* that packet currently isn't displayed */
2337 /* XXX - add it to the set of displayed packets? */
2338 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2339 "That packet is not currently being displayed.");
2340 return FALSE; /* we failed to go to that packet */
2343 /* We found that packet, and it's currently being displayed.
2344 Find what row it's in. */
2345 row = packet_list_find_row_from_data(fdata);
2346 g_assert(row != -1);
2348 /* Select that row, make it the focus row, and make it visible. */
2349 packet_list_set_selected_row(row);
2350 return TRUE; /* we got to that packet */
2354 goto_top_frame(capture_file *cf)
2358 frame_data *lowest_fdata = NULL;
2360 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2361 if (fdata->flags.passed_dfilter) {
2362 lowest_fdata = fdata;
2367 if (lowest_fdata == NULL) {
2371 /* We found that packet, and it's currently being displayed.
2372 Find what row it's in. */
2373 row = packet_list_find_row_from_data(lowest_fdata);
2374 g_assert(row != -1);
2376 /* Select that row, make it the focus row, and make it visible. */
2377 packet_list_set_selected_row(row);
2378 return TRUE; /* we got to that packet */
2382 goto_bottom_frame(capture_file *cf)
2386 frame_data *highest_fdata = NULL;
2388 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2389 if (fdata->flags.passed_dfilter) {
2390 highest_fdata = fdata;
2394 if (highest_fdata == NULL) {
2398 /* We found that packet, and it's currently being displayed.
2399 Find what row it's in. */
2400 row = packet_list_find_row_from_data(highest_fdata);
2401 g_assert(row != -1);
2403 /* Select that row, make it the focus row, and make it visible. */
2404 packet_list_set_selected_row(row);
2405 return TRUE; /* we got to that packet */
2408 /* Select the packet on a given row. */
2410 select_packet(capture_file *cf, int row)
2416 /* Get the frame data struct pointer for this frame */
2417 fdata = (frame_data *)packet_list_get_row_data(row);
2419 if (fdata == NULL) {
2420 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
2421 the first entry is added to it by "real_insert_row()", that row
2422 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
2423 our version and the vanilla GTK+ version).
2425 This means that a "select-row" signal is emitted; this causes
2426 "packet_list_select_cb()" to be called, which causes "select_packet()"
2429 "select_packet()" fetches, above, the data associated with the
2430 row that was selected; however, as "gtk_clist_append()", which
2431 called "real_insert_row()", hasn't yet returned, we haven't yet
2432 associated any data with that row, so we get back a null pointer.
2434 We can't assume that there's only one frame in the frame list,
2435 either, as we may be filtering the display.
2437 We therefore assume that, if "row" is 0, i.e. the first row
2438 is being selected, and "cf->first_displayed" equals
2439 "cf->last_displayed", i.e. there's only one frame being
2440 displayed, that frame is the frame we want.
2442 This means we have to set "cf->first_displayed" and
2443 "cf->last_displayed" before adding the row to the
2444 GtkCList; see the comment in "add_packet_to_packet_list()". */
2446 if (row == 0 && cf->first_displayed == cf->last_displayed)
2447 fdata = cf->first_displayed;
2450 /* Get the data in that frame. */
2451 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
2452 cf->pd, fdata->cap_len, &err, &err_info)) {
2453 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2454 cf_read_error_message(err, err_info), cf->filename);
2458 /* Record that this frame is the current frame. */
2459 cf->current_frame = fdata;
2461 /* Create the logical protocol tree. */
2462 if (cf->edt != NULL) {
2463 epan_dissect_free(cf->edt);
2466 /* We don't need the columns here. */
2467 cf->edt = epan_dissect_new(TRUE, TRUE);
2468 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
2471 /* Display the GUI protocol tree and hex dump.
2472 XXX - why do we dump core if we call "proto_tree_draw()"
2473 before calling "add_byte_views()"? */
2474 add_main_byte_views(cf->edt);
2475 main_proto_tree_draw(cf->edt->tree);
2477 /* A packet is selected. */
2478 set_menus_for_selected_packet(cf);
2481 /* Unselect the selected packet, if any. */
2483 unselect_packet(capture_file *cf)
2485 /* Destroy the epan_dissect_t for the unselected packet. */
2486 if (cf->edt != NULL) {
2487 epan_dissect_free(cf->edt);
2491 /* Clear out the display of that packet. */
2492 clear_tree_and_hex_views();
2494 /* No packet is selected. */
2495 cf->current_frame = NULL;
2496 set_menus_for_selected_packet(cf);
2498 /* No protocol tree means no selected field. */
2502 /* Unset the selected protocol tree field, if any. */
2504 unselect_field(capture_file *cf)
2506 statusbar_pop_field_msg();
2507 cf->finfo_selected = NULL;
2508 set_menus_for_selected_tree_row(cf);
2512 * Mark a particular frame.
2515 mark_frame(capture_file *cf, frame_data *frame)
2517 frame->flags.marked = TRUE;
2522 * Unmark a particular frame.
2525 unmark_frame(capture_file *cf, frame_data *frame)
2527 frame->flags.marked = FALSE;
2534 } save_callback_args_t;
2537 * Save a capture to a file, in a particular format, saving either
2538 * all packets, all currently-displayed packets, or all marked packets.
2540 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
2541 * up a message box for the failure.
2544 save_packet(capture_file *cf _U_, frame_data *fdata,
2545 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2548 save_callback_args_t *args = argsp;
2549 struct wtap_pkthdr hdr;
2552 /* init the wtap header for saving */
2553 hdr.ts.tv_sec = fdata->abs_secs;
2554 hdr.ts.tv_usec = fdata->abs_usecs;
2555 hdr.caplen = fdata->cap_len;
2556 hdr.len = fdata->pkt_len;
2557 hdr.pkt_encap = fdata->lnk_t;
2559 /* and save the packet */
2560 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
2561 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, cf_write_error_message(err),
2569 cf_save(char *fname, capture_file *cf, packet_range_t *range, guint save_format)
2571 gchar *from_filename;
2572 gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
2577 struct stat infile, outfile;
2578 save_callback_args_t callback_args;
2580 name_ptr = get_basename(fname);
2581 msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
2582 save_msg = g_malloc(msg_len);
2583 snprintf(save_msg, msg_len, save_fmt, name_ptr);
2584 statusbar_push_file_msg(save_msg);
2588 * Check that the from file is not the same as to file
2589 * We do it here so we catch all cases ...
2590 * Unfortunately, the file requester gives us an absolute file
2591 * name and the read file name may be relative (if supplied on
2592 * the command line). From Joerg Mayer.
2594 infile.st_ino = 1; /* These prevent us from getting equality */
2595 outfile.st_ino = 2; /* If one or other of the files is not accessible */
2596 stat(cf->filename, &infile);
2597 stat(fname, &outfile);
2598 if (infile.st_ino == outfile.st_ino) {
2599 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2600 "Can't save over current capture file: %s!",
2605 packet_range_process_init(range);
2608 * if (!save_filtered && !save_marked && !save_manual_range &&
2609 * !save_marked_range && !save_curr && save_format == cf->cd_t) {
2612 if (packet_range_process_all(range) && save_format == cf->cd_t) {
2613 /* We're not filtering packets, and we're saving it in the format
2614 it's already in, so we can just move or copy the raw data. */
2616 if (cf->is_tempfile) {
2617 /* The file being saved is a temporary file from a live
2618 capture, so it doesn't need to stay around under that name;
2619 first, try renaming the capture buffer file to the new name. */
2621 if (rename(cf->filename, fname) == 0) {
2622 /* That succeeded - there's no need to copy the source file. */
2623 from_filename = NULL;
2626 if (errno == EXDEV) {
2627 /* They're on different file systems, so we have to copy the
2630 from_filename = cf->filename;
2632 /* The rename failed, but not because they're on different
2633 file systems - put up an error message. (Or should we
2634 just punt and try to copy? The only reason why I'd
2635 expect the rename to fail and the copy to succeed would
2636 be if we didn't have permission to remove the file from
2637 the temporary directory, and that might be fixable - but
2638 is it worth requiring the user to go off and fix it?) */
2639 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2640 file_rename_error_message(errno), fname);
2646 from_filename = cf->filename;
2649 /* It's a permanent file, so we should copy it, and not remove the
2652 from_filename = cf->filename;
2656 /* Copy the file, if we haven't moved it. */
2657 if (!copy_binary_file(from_filename, fname))
2661 /* Either we're filtering packets, or we're saving in a different
2662 format; we can't do that by copying or moving the capture file,
2663 we have to do it by writing the packets out in Wiretap. */
2664 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
2666 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2667 cf_open_error_message(err, NULL, TRUE, save_format), fname);
2671 /* XXX - we let the user save a subset of the packets.
2673 If we do that, should we make that file the current file? If so,
2674 it means we can no longer get at the other packets. What does
2677 /* Iterate through the list of packets, printing the packets we were
2680 XXX - we've already called "packet_range_process_init(range)", but
2681 "process_specified_packets()" will do it again. Fortunately,
2682 that's harmless in this case, as we haven't done anything to
2683 "range" since we initialized it. */
2684 callback_args.pdh = pdh;
2685 callback_args.fname = fname;
2686 switch (process_specified_packets(cf, range, "Saving",
2687 "selected packets", save_packet,
2691 /* Completed successfully. */
2695 /* The user decided to abort the saving.
2696 XXX - remove the output file? */
2700 /* Error while saving. */
2701 wtap_dump_close(pdh, &err);
2705 if (!wtap_dump_close(pdh, &err)) {
2706 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK, cf_close_error_message(err),
2712 /* Pop the "Saving:" message off the status bar. */
2713 statusbar_pop_file_msg();
2715 /* XXX: I'm not sure how this should look like! */
2716 if (packet_range_process_all(range)) {
2717 /*if (!save_filtered && !save_marked) {*/
2718 /* We saved the entire capture, not just some packets from it.
2719 Open and read the file we saved it to.
2721 XXX - this is somewhat of a waste; we already have the
2722 packets, all this gets us is updated file type information
2723 (which we could just stuff into "cf"), and having the new
2724 file be the one we have opened and from which we're reading
2725 the data, and it means we have to spend time opening and
2726 reading the file, which could be a significant amount of
2727 time if the file is large. */
2728 cf->user_saved = TRUE;
2730 if ((err = cf_open(fname, FALSE, cf)) == 0) {
2731 /* XXX - report errors if this fails?
2732 What should we return if it fails or is aborted? */
2733 switch (cf_read(cf)) {
2737 /* Just because we got an error, that doesn't mean we were unable
2738 to read any of the file; we handle what we could get from the
2743 /* The user bailed out of re-reading the capture file; the
2744 capture file has been closed - just return (without
2745 changing any menu settings; "cf_close()" set them
2746 correctly for the "no capture file open" state). */
2749 set_menus_for_unsaved_capture_file(FALSE);
2755 /* Pop the "Saving:" message off the status bar. */
2756 statusbar_pop_file_msg();
2761 cf_open_error_message(int err, gchar *err_info, gboolean for_writing,
2765 static char errmsg_errno[1024+1];
2768 /* Wiretap error. */
2771 case WTAP_ERR_NOT_REGULAR_FILE:
2772 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
2775 case WTAP_ERR_RANDOM_OPEN_PIPE:
2776 /* Seen only when opening a capture file for reading. */
2777 errmsg = "The file \"%s\" is a pipe or FIFO; Ethereal cannot read pipe or FIFO files.";
2780 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
2781 /* Seen only when opening a capture file for reading. */
2782 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
2785 case WTAP_ERR_UNSUPPORTED:
2786 /* Seen only when opening a capture file for reading. */
2787 snprintf(errmsg_errno, sizeof(errmsg_errno),
2788 "The file \"%%s\" is not a capture file in a format Ethereal understands.\n"
2791 errmsg = errmsg_errno;
2794 case WTAP_ERR_CANT_WRITE_TO_PIPE:
2795 /* Seen only when opening a capture file for writing. */
2796 snprintf(errmsg_errno, sizeof(errmsg_errno),
2797 "The file \"%%s\" is a pipe, and %s capture files cannot be "
2798 "written to a pipe.", wtap_file_type_string(file_type));
2799 errmsg = errmsg_errno;
2802 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
2803 /* Seen only when opening a capture file for writing. */
2804 errmsg = "Ethereal does not support writing capture files in that format.";
2807 case WTAP_ERR_UNSUPPORTED_ENCAP:
2809 errmsg = "Ethereal cannot save this capture in that format.";
2811 snprintf(errmsg_errno, sizeof(errmsg_errno),
2812 "The file \"%%s\" is a capture for a network type that Ethereal doesn't support.\n"
2815 errmsg = errmsg_errno;
2819 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
2821 errmsg = "Ethereal cannot save this capture in that format.";
2823 errmsg = "The file \"%s\" is a capture for a network type that Ethereal doesn't support.";
2826 case WTAP_ERR_BAD_RECORD:
2827 /* Seen only when opening a capture file for reading. */
2828 snprintf(errmsg_errno, sizeof(errmsg_errno),
2829 "The file \"%%s\" appears to be damaged or corrupt.\n"
2832 errmsg = errmsg_errno;
2835 case WTAP_ERR_CANT_OPEN:
2837 errmsg = "The file \"%s\" could not be created for some unknown reason.";
2839 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
2842 case WTAP_ERR_SHORT_READ:
2843 errmsg = "The file \"%s\" appears to have been cut short"
2844 " in the middle of a packet or other data.";
2847 case WTAP_ERR_SHORT_WRITE:
2848 errmsg = "A full header couldn't be written to the file \"%s\".";
2852 snprintf(errmsg_errno, sizeof(errmsg_errno),
2853 "The file \"%%s\" could not be %s: %s.",
2854 for_writing ? "created" : "opened",
2855 wtap_strerror(err));
2856 errmsg = errmsg_errno;
2860 errmsg = file_open_error_message(err, for_writing);
2865 file_rename_error_message(int err)
2868 static char errmsg_errno[1024+1];
2873 errmsg = "The path to the file \"%s\" does not exist.";
2877 errmsg = "You do not have permission to move the capture file to \"%s\".";
2881 snprintf(errmsg_errno, sizeof(errmsg_errno),
2882 "The file \"%%s\" could not be moved: %s.",
2883 wtap_strerror(err));
2884 errmsg = errmsg_errno;
2891 cf_read_error_message(int err, gchar *err_info)
2893 static char errmsg_errno[1024+1];
2897 case WTAP_ERR_UNSUPPORTED:
2898 case WTAP_ERR_UNSUPPORTED_ENCAP:
2899 case WTAP_ERR_BAD_RECORD:
2900 snprintf(errmsg_errno, sizeof(errmsg_errno),
2901 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
2902 wtap_strerror(err), err_info);
2906 snprintf(errmsg_errno, sizeof(errmsg_errno),
2907 "An error occurred while reading from the file \"%%s\": %s.",
2908 wtap_strerror(err));
2911 return errmsg_errno;
2915 cf_write_error_message(int err)
2918 static char errmsg_errno[1024+1];
2921 /* Wiretap error. */
2922 snprintf(errmsg_errno, sizeof(errmsg_errno),
2923 "An error occurred while writing to the file \"%%s\": %s.",
2924 wtap_strerror(err));
2925 errmsg = errmsg_errno;
2927 errmsg = file_write_error_message(err);
2931 /* Check for write errors - if the file is being written to an NFS server,
2932 a write error may not show up until the file is closed, as NFS clients
2933 might not send writes to the server until the "write()" call finishes,
2934 so that the write may fail on the server but the "write()" may succeed. */
2936 cf_close_error_message(int err)
2939 static char errmsg_errno[1024+1];
2942 /* Wiretap error. */
2945 case WTAP_ERR_CANT_CLOSE:
2946 errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
2949 case WTAP_ERR_SHORT_WRITE:
2950 errmsg = "Not all the packets could be written to the file \"%s\".";
2954 snprintf(errmsg_errno, sizeof(errmsg_errno),
2955 "An error occurred while closing the file \"%%s\": %s.",
2956 wtap_strerror(err));
2957 errmsg = errmsg_errno;
2961 /* We assume that a close error from the OS is really a write error. */
2962 errmsg = file_write_error_message(err);
2968 /* Copies a file in binary mode, for those operating systems that care about
2970 * Returns TRUE on success, FALSE on failure. If a failure, it also
2971 * displays a simple dialog window with the error message.
2974 copy_binary_file(char *from_filename, char *to_filename)
2976 int from_fd, to_fd, nread, nwritten, err;
2979 /* Copy the raw bytes of the file. */
2980 from_fd = open(from_filename, O_RDONLY | O_BINARY);
2983 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2984 file_open_error_message(err, TRUE), from_filename);
2988 /* Use open() instead of creat() so that we can pass the O_BINARY
2989 flag, which is relevant on Win32; it appears that "creat()"
2990 may open the file in text mode, not binary mode, but we want
2991 to copy the raw bytes of the file, so we need the output file
2992 to be open in binary mode. */
2993 to_fd = open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
2996 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2997 file_open_error_message(err, TRUE), to_filename);
3002 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
3003 nwritten = write(to_fd, pd, nread);
3004 if (nwritten < nread) {
3008 err = WTAP_ERR_SHORT_WRITE;
3009 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3010 file_write_error_message(err), to_filename);
3018 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3019 "An error occurred while reading from the file \"%s\": %s.",
3020 from_filename, strerror(err));
3026 if (close(to_fd) < 0) {
3028 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3029 file_write_error_message(err), to_filename);