4 * $Id: file.c,v 1.344 2004/01/21 22:00:27 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 cul_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 *file_rename_error_message(int err);
119 static char *file_close_error_message(int err);
120 static gboolean copy_binary_file(char *from_filename, char *to_filename);
122 /* Update the progress bar this many times when reading a file. */
123 #define N_PROGBAR_UPDATES 100
125 /* Number of "frame_data" structures per memory chunk.
126 XXX - is this the right number? */
127 #define FRAME_DATA_CHUNK_SIZE 1024
134 gboolean print_all_levels;
135 gboolean print_hex_for_data;
137 gint format; /* text or PostScript */
142 cf_open(char *fname, gboolean is_tempfile, capture_file *cf)
149 wth = wtap_open_offline(fname, &err, TRUE);
153 /* Find the size of the file. */
155 if (fstat(fd, &cf_stat) < 0) {
161 /* The open succeeded. Close whatever capture file we had open,
162 and fill in the information for this file. */
165 /* Initialize all data structures used for dissection. */
168 /* We're about to start reading the file. */
169 cf->state = FILE_READ_IN_PROGRESS;
173 cf->f_len = cf_stat.st_size;
175 /* Set the file name because we need it to set the follow stream filter.
176 XXX - is that still true? We need it for other reasons, though,
178 cf->filename = g_strdup(fname);
180 /* Indicate whether it's a permanent or temporary file. */
181 cf->is_tempfile = is_tempfile;
183 /* If it's a temporary capture buffer file, mark it as not saved. */
184 cf->user_saved = !is_tempfile;
186 cf->cd_t = wtap_file_type(cf->wth);
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 simple_dialog(ESD_TYPE_CRIT, NULL,
213 file_open_error_message(err, FALSE, 0), fname);
217 /* Reset everything to a pristine state */
219 cf_close(capture_file *cf)
221 /* Die if we're in the middle of reading a file. */
222 g_assert(cf->state != FILE_READ_IN_PROGRESS);
224 /* Destroy all windows, which refer to the
225 capture file we're closing. */
226 destroy_cfile_wins();
232 /* We have no file open... */
233 if (cf->filename != NULL) {
234 /* If it's a temporary file, remove it. */
236 unlink(cf->filename);
237 g_free(cf->filename);
240 /* ...which means we have nothing to save. */
241 cf->user_saved = FALSE;
243 if (cf->plist_chunk != NULL) {
244 g_mem_chunk_destroy(cf->plist_chunk);
245 cf->plist_chunk = NULL;
247 if (cf->rfcode != NULL) {
248 dfilter_free(cf->rfcode);
252 cf->plist_end = NULL;
253 unselect_packet(cf); /* nothing to select */
254 cf->first_displayed = NULL;
255 cf->last_displayed = NULL;
257 /* No frame selected, no field in that frame selected. */
258 cf->current_frame = NULL;
259 cf->finfo_selected = NULL;
261 /* Clear the packet list. */
262 packet_list_freeze();
266 /* Clear any file-related status bar messages.
267 XXX - should be "clear *ALL* file-related status bar messages;
268 will there ever be more than one on the stack? */
269 statusbar_pop_file_msg();
271 /* Restore the standard title bar message. */
272 set_main_window_name("The Ethereal Network Analyzer");
274 /* Disable all menu items that make sense only if you have a capture. */
275 set_menus_for_capture_file(FALSE);
276 set_menus_for_unsaved_capture_file(FALSE);
277 set_menus_for_captured_packets(FALSE);
278 set_menus_for_selected_packet(cf);
279 set_menus_for_capture_in_progress(FALSE);
280 set_menus_for_selected_tree_row(cf);
282 /* We have no file open. */
283 cf->state = FILE_CLOSED;
286 /* Set the file name in the status line, in the name for the main window,
287 and in the name for the main window's icon. */
289 set_display_filename(capture_file *cf)
293 static const gchar done_fmt_nodrops[] = " File: %s";
294 static const gchar done_fmt_drops[] = " File: %s Drops: %u";
296 gchar *win_name_fmt = "%s - Ethereal";
299 name_ptr = cf_get_display_name(cf);
301 if (!cf->is_tempfile) {
302 /* Add this filename to the list of recent files in the "Recent Files" submenu */
303 add_menu_recent_capture_file(cf->filename);
306 if (cf->drops_known) {
307 msg_len = strlen(name_ptr) + strlen(done_fmt_drops) + 64;
308 done_msg = g_malloc(msg_len);
309 snprintf(done_msg, msg_len, done_fmt_drops, name_ptr, cf->drops);
311 msg_len = strlen(name_ptr) + strlen(done_fmt_nodrops);
312 done_msg = g_malloc(msg_len);
313 snprintf(done_msg, msg_len, done_fmt_nodrops, name_ptr);
315 statusbar_push_file_msg(done_msg);
318 msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
319 win_name = g_malloc(msg_len);
320 snprintf(win_name, msg_len, win_name_fmt, name_ptr);
321 set_main_window_name(win_name);
326 cf_read(capture_file *cf, int *err)
328 gchar *name_ptr, *load_msg, *load_fmt = "%s";
331 char errmsg_errno[1024+1];
332 gchar err_str[2048+1];
334 progdlg_t *progbar = NULL;
337 * XXX - should be "off_t", but Wiretap would need more work to handle
338 * the full size of "off_t" on platforms where it's more than a "long"
346 gchar status_str[100];
347 int progbar_nextstep;
351 reset_tap_listeners();
352 tap_dfilter_dlg_update();
353 name_ptr = get_basename(cf->filename);
355 msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
356 load_msg = g_malloc(msg_len);
357 snprintf(load_msg, msg_len, load_fmt, name_ptr);
358 statusbar_push_file_msg(load_msg);
360 /* Update the progress bar when it gets to this value. */
361 progbar_nextstep = 0;
362 /* When we reach the value that triggers a progress bar update,
363 bump that value by this amount. */
364 progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
370 packet_list_freeze();
373 g_get_current_time(&start_time);
375 while ((wtap_read(cf->wth, err, &data_offset))) {
376 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
377 when we update it, we have to run the GTK+ main loop to get it
378 to repaint what's pending, and doing so may involve an "ioctl()"
379 to see if there's any pending input from an X server, and doing
380 that for every packet can be costly, especially on a big file. */
381 if (data_offset >= progbar_nextstep) {
382 file_pos = lseek(cf->filed, 0, SEEK_CUR);
383 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
384 if (prog_val > 1.0) {
385 /* The file probably grew while we were reading it.
386 Update "cf->f_len", and try again. */
387 fd = wtap_fd(cf->wth);
388 if (fstat(fd, &cf_stat) >= 0) {
389 cf->f_len = cf_stat.st_size;
390 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
392 /* If it's still > 1, either the "fstat()" failed (in which
393 case there's not much we can do about it), or the file
394 *shrank* (in which case there's not much we can do about
395 it); just clip the progress value at 1.0. */
399 if (progbar == NULL) {
400 /* Create the progress bar if necessary */
401 progbar = delayed_create_progress_dlg("Loading", load_msg,
402 &stop_flag, &start_time, prog_val);
406 if (progbar != NULL) {
407 g_snprintf(status_str, sizeof(status_str),
408 "%luKB of %luKB", file_pos / 1024, cf->f_len / 1024);
409 update_progress_dlg(progbar, prog_val, status_str);
411 progbar_nextstep += progbar_quantum;
415 /* Well, the user decided to abort the read. Destroy the progress
416 bar, close the capture file, and return READ_ABORTED so our caller
417 can do whatever is appropriate when that happens. */
418 destroy_progress_dlg(progbar);
419 cf->state = FILE_READ_ABORTED; /* so that we're allowed to close it */
420 packet_list_thaw(); /* undo our freeze */
422 return (READ_ABORTED);
424 read_packet(cf, data_offset);
427 /* We're done reading the file; destroy the progress bar if it was created. */
431 destroy_progress_dlg(progbar);
433 /* We're done reading sequentially through the file. */
434 cf->state = FILE_READ_DONE;
436 /* Close the sequential I/O side, to free up memory it requires. */
437 wtap_sequential_close(cf->wth);
439 /* Allow the protocol dissectors to free up memory that they
440 * don't need after the sequential run-through of the packets. */
441 postseq_cleanup_all_protocols();
443 /* Set the file encapsulation type now; we don't know what it is until
444 we've looked at all the packets, as we don't know until then whether
445 there's more than one type (and thus whether it's
446 WTAP_ENCAP_PER_PACKET). */
447 cf->lnk_t = wtap_file_encap(cf->wth);
449 cf->current_frame = cf->first_displayed;
452 statusbar_pop_file_msg();
453 set_display_filename(cf);
455 /* Enable menu items that make sense if you have a capture file you've
457 set_menus_for_capture_file(TRUE);
458 set_menus_for_unsaved_capture_file(!cf->user_saved);
460 /* Enable menu items that make sense if you have some captured packets. */
461 set_menus_for_captured_packets(TRUE);
463 /* If we have any displayed packets to select, select the first of those
464 packets by making the first row the selected row. */
465 if (cf->first_displayed != NULL)
466 packet_list_select_row(0);
469 /* Put up a message box noting that the read failed somewhere along
470 the line. Don't throw out the stuff we managed to read, though,
474 case WTAP_ERR_UNSUPPORTED_ENCAP:
475 errmsg = "The capture file is for a network type that Ethereal doesn't support.";
478 case WTAP_ERR_CANT_READ:
479 errmsg = "An attempt to read from the file failed for"
480 " some unknown reason.";
483 case WTAP_ERR_SHORT_READ:
484 errmsg = "The capture file appears to have been cut short"
485 " in the middle of a packet.";
488 case WTAP_ERR_BAD_RECORD:
489 errmsg = "The capture file appears to be damaged or corrupt.";
493 snprintf(errmsg_errno, sizeof(errmsg_errno),
494 "An error occurred while reading the"
495 " capture file: %s.", wtap_strerror(*err));
496 errmsg = errmsg_errno;
499 snprintf(err_str, sizeof err_str, errmsg);
500 simple_dialog(ESD_TYPE_CRIT, NULL, err_str);
503 return (READ_SUCCESS);
508 cf_start_tail(char *fname, gboolean is_tempfile, capture_file *cf)
512 err = cf_open(fname, is_tempfile, cf);
514 /* Disable menu items that make no sense if you're currently running
516 set_menus_for_capture_in_progress(TRUE);
518 /* Enable menu items that make sense if you have some captured
519 packets (yes, I know, we don't have any *yet*). */
520 set_menus_for_captured_packets(TRUE);
522 statusbar_push_file_msg(" <live capture in progress>");
528 cf_continue_tail(capture_file *cf, int to_read, int *err)
530 long data_offset = 0;
534 packet_list_freeze();
536 while (to_read != 0 && (wtap_read(cf->wth, err, &data_offset))) {
537 if (cf->state == FILE_READ_ABORTED) {
538 /* Well, the user decided to exit Ethereal. Break out of the
539 loop, and let the code below (which is called even if there
540 aren't any packets left to read) exit. */
543 read_packet(cf, data_offset);
549 /* XXX - this cheats and looks inside the packet list to find the final
551 if (auto_scroll_live && cf->plist_end != NULL)
552 packet_list_moveto_end();
554 if (cf->state == FILE_READ_ABORTED) {
555 /* Well, the user decided to exit Ethereal. Return READ_ABORTED
556 so that our caller can kill off the capture child process;
557 this will cause an EOF on the pipe from the child, so
558 "cf_finish_tail()" will be called, and it will clean up
561 } else if (*err != 0) {
562 /* We got an error reading the capture file.
563 XXX - pop up a dialog box? */
566 return (READ_SUCCESS);
570 cf_finish_tail(capture_file *cf, int *err)
574 packet_list_freeze();
576 while ((wtap_read(cf->wth, err, &data_offset))) {
577 if (cf->state == FILE_READ_ABORTED) {
578 /* Well, the user decided to abort the read. Break out of the
579 loop, and let the code below (which is called even if there
580 aren't any packets left to read) exit. */
583 read_packet(cf, data_offset);
586 if (cf->state == FILE_READ_ABORTED) {
587 /* Well, the user decided to abort the read. We're only called
588 when the child capture process closes the pipe to us (meaning
589 it's probably exited), so we can just close the capture
590 file; we return READ_ABORTED so our caller can do whatever
591 is appropriate when that happens. */
597 if (auto_scroll_live && cf->plist_end != NULL)
598 /* XXX - this cheats and looks inside the packet list to find the final
600 packet_list_moveto_end();
602 /* We're done reading sequentially through the file. */
603 cf->state = FILE_READ_DONE;
605 /* We're done reading sequentially through the file; close the
606 sequential I/O side, to free up memory it requires. */
607 wtap_sequential_close(cf->wth);
609 /* Allow the protocol dissectors to free up memory that they
610 * don't need after the sequential run-through of the packets. */
611 postseq_cleanup_all_protocols();
613 /* Set the file encapsulation type now; we don't know what it is until
614 we've looked at all the packets, as we don't know until then whether
615 there's more than one type (and thus whether it's
616 WTAP_ENCAP_PER_PACKET). */
617 cf->lnk_t = wtap_file_encap(cf->wth);
619 /* Pop the "<live capture in progress>" message off the status bar. */
620 statusbar_pop_file_msg();
622 set_display_filename(cf);
624 /* Enable menu items that make sense if you're not currently running
626 set_menus_for_capture_in_progress(FALSE);
628 /* Enable menu items that make sense if you have a capture file
629 you've finished reading. */
630 set_menus_for_capture_file(TRUE);
631 set_menus_for_unsaved_capture_file(!cf->user_saved);
634 /* We got an error reading the capture file.
635 XXX - pop up a dialog box? */
638 return (READ_SUCCESS);
640 #endif /* HAVE_LIBPCAP */
643 cf_get_display_name(capture_file *cf)
647 /* Return a name to use in displays */
648 if (!cf->is_tempfile) {
649 /* Get the last component of the file name, and use that. */
651 displayname = get_basename(cf->filename);
653 /* Add this filename to the list of recent files in the "Recent Files" submenu */
654 add_menu_recent_capture_file(cf->filename);
656 displayname="<no file>";
659 /* The file we read is a temporary file from a live capture;
660 we don't mention its name. */
661 displayname = "<capture>";
667 color_filter_t *colorf;
669 } apply_color_filter_args;
672 * If no color filter has been applied, apply this one.
673 * (The "if no color filter has been applied" is to handle the case where
674 * more than one color filter matches the packet.)
677 apply_color_filter(gpointer filter_arg, gpointer argp)
679 color_filter_t *colorf = filter_arg;
680 apply_color_filter_args *args = argp;
682 if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
683 if (dfilter_apply_edt(colorf->c_colorfilter, args->edt))
684 args->colorf = colorf;
689 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
690 union wtap_pseudo_header *pseudo_header, const guchar *buf,
693 apply_color_filter_args args;
695 gboolean create_proto_tree = FALSE;
698 /* just add some value here until we know if it is being displayed or not */
699 fdata->cul_bytes = cul_bytes + fdata->pkt_len;
701 /* We don't yet have a color filter to apply. */
704 /* If we don't have the time stamp of the first packet in the
705 capture, it's because this is the first packet. Save the time
706 stamp of this packet as the time stamp of the first packet. */
707 if (!firstsec && !firstusec) {
708 firstsec = fdata->abs_secs;
709 firstusec = fdata->abs_usecs;
711 /* if this frames is marked as a reference time frame, reset
712 firstsec and firstusec to this frame */
713 if(fdata->flags.ref_time){
714 firstsec = fdata->abs_secs;
715 firstusec = fdata->abs_usecs;
718 /* If we don't have the time stamp of the previous displayed packet,
719 it's because this is the first displayed packet. Save the time
720 stamp of this packet as the time stamp of the previous displayed
722 if (!prevsec && !prevusec) {
723 prevsec = fdata->abs_secs;
724 prevusec = fdata->abs_usecs;
727 /* Get the time elapsed between the first packet and this packet. */
728 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
729 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
731 /* If it's greater than the current elapsed time, set the elapsed time
732 to it (we check for "greater than" so as not to be confused by
733 time moving backwards). */
734 if ((gint32)cf->esec < fdata->rel_secs
735 || ((gint32)cf->esec == fdata->rel_secs && (gint32)cf->eusec < fdata->rel_usecs)) {
736 cf->esec = fdata->rel_secs;
737 cf->eusec = fdata->rel_usecs;
740 /* Get the time elapsed between the previous displayed packet and
742 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
743 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
747 we have a display filter and are re-applying it;
749 we have a list of color filters;
751 we have tap listeners;
753 allocate a protocol tree root node, so that we'll construct
754 a protocol tree against which a filter expression can be
756 if ((cf->dfcode != NULL && refilter) || filter_list != NULL
757 || num_tap_filters != 0)
758 create_proto_tree = TRUE;
760 /* Dissect the frame. */
761 edt = epan_dissect_new(create_proto_tree, FALSE);
763 if (cf->dfcode != NULL && refilter) {
764 epan_dissect_prime_dfilter(edt, cf->dfcode);
767 filter_list_prime_edt(edt);
770 epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
771 tap_push_tapped_queue(edt);
773 /* If we have a display filter, apply it if we're refiltering, otherwise
774 leave the "passed_dfilter" flag alone.
776 If we don't have a display filter, set "passed_dfilter" to 1. */
777 if (cf->dfcode != NULL) {
779 if (cf->dfcode != NULL)
780 fdata->flags.passed_dfilter = dfilter_apply_edt(cf->dfcode, edt) ? 1 : 0;
782 fdata->flags.passed_dfilter = 1;
785 fdata->flags.passed_dfilter = 1;
787 /* If we have color filters, and the frame is to be displayed, apply
788 the color filters. */
789 if (fdata->flags.passed_dfilter) {
790 if (filter_list != NULL) {
792 g_slist_foreach(filter_list, apply_color_filter, &args);
797 if( (fdata->flags.passed_dfilter)
798 || (edt->pi.fd->flags.ref_time) ){
799 /* This frame either passed the display filter list or is marked as
800 a time reference frame. All time reference frames are displayed
801 even if they dont pass the display filter */
802 /* if this was a TIME REF frame we should reset the cul bytes field */
803 if(edt->pi.fd->flags.ref_time){
804 cul_bytes = fdata->pkt_len;
805 fdata->cul_bytes = cul_bytes;
808 /* increase cul_bytes with this packets length */
809 cul_bytes += fdata->pkt_len;
811 epan_dissect_fill_in_columns(edt);
813 /* If we haven't yet seen the first frame, this is it.
815 XXX - we must do this before we add the row to the display,
816 as, if the display's GtkCList's selection mode is
817 GTK_SELECTION_BROWSE, when the first entry is added to it,
818 "select_packet()" will be called, and it will fetch the row
819 data for the 0th row, and will get a null pointer rather than
820 "fdata", as "gtk_clist_append()" won't yet have returned and
821 thus "gtk_clist_set_row_data()" won't yet have been called.
823 We thus need to leave behind bread crumbs so that
824 "select_packet()" can find this frame. See the comment
825 in "select_packet()". */
826 if (cf->first_displayed == NULL)
827 cf->first_displayed = fdata;
829 /* This is the last frame we've seen so far. */
830 cf->last_displayed = fdata;
832 row = packet_list_append(cf->cinfo.col_data, fdata);
834 /* If the packet matches a color filter,
835 * store matching color_filter_t object in frame data. */
836 if (filter_list != NULL && (args.colorf != NULL)) {
837 /* add the matching colorfilter to the frame data */
838 fdata->color_filter = args.colorf;
839 /* If packet is marked, use colors from preferences */
840 if (fdata->flags.marked) {
841 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
842 } else /* if (filter_list != NULL && (args.colorf != NULL)) */ {
843 packet_list_set_colors(row, &(args.colorf->fg_color),
844 &(args.colorf->bg_color));
847 /* No color filter match */
848 fdata->color_filter = NULL;
849 if (fdata->flags.marked) {
850 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
854 /* Set the time of the previous displayed frame to the time of this
856 prevsec = fdata->abs_secs;
857 prevusec = fdata->abs_usecs;
859 /* This frame didn't pass the display filter, so it's not being added
860 to the clist, and thus has no row. */
863 epan_dissect_free(edt);
868 read_packet(capture_file *cf, long offset)
870 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
871 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
872 const guchar *buf = wtap_buf_ptr(cf->wth);
875 frame_data *plist_end;
878 /* Allocate the next list entry, and add it to the list. */
879 fdata = g_mem_chunk_alloc(cf->plist_chunk);
884 fdata->pkt_len = phdr->len;
885 fdata->cap_len = phdr->caplen;
886 fdata->file_off = offset;
887 fdata->lnk_t = phdr->pkt_encap;
888 fdata->abs_secs = phdr->ts.tv_sec;
889 fdata->abs_usecs = phdr->ts.tv_usec;
890 fdata->flags.encoding = CHAR_ASCII;
891 fdata->flags.visited = 0;
892 fdata->flags.marked = 0;
893 fdata->flags.ref_time = 0;
897 edt = epan_dissect_new(TRUE, FALSE);
898 epan_dissect_prime_dfilter(edt, cf->rfcode);
899 epan_dissect_run(edt, pseudo_header, buf, fdata, NULL);
900 passed = dfilter_apply_edt(cf->rfcode, edt);
901 epan_dissect_free(edt);
904 plist_end = cf->plist_end;
905 fdata->prev = plist_end;
906 if (plist_end != NULL)
907 plist_end->next = fdata;
910 cf->plist_end = fdata;
913 fdata->num = cf->count;
914 add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE);
916 /* XXX - if we didn't have read filters, or if we could avoid
917 allocating the "frame_data" structure until we knew whether
918 the frame passed the read filter, we could use a G_ALLOC_ONLY
921 ...but, at least in one test I did, where I just made the chunk
922 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
923 seem to save a noticeable amount of time or space. */
924 g_mem_chunk_free(cf->plist_chunk, fdata);
929 filter_packets(capture_file *cf, gchar *dftext)
933 if (dftext == NULL) {
934 /* The new filter is an empty filter (i.e., display all packets). */
938 * We have a filter; make a copy of it (as we'll be saving it),
939 * and try to compile it.
941 dftext = g_strdup(dftext);
942 if (!dfilter_compile(dftext, &dfcode)) {
943 /* The attempt failed; report an error. */
944 simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
949 if (dfcode == NULL) {
950 /* Yes - free the filter text, and set it to null. */
956 /* We have a valid filter. Replace the current filter. */
957 if (cf->dfilter != NULL)
959 cf->dfilter = dftext;
960 if (cf->dfcode != NULL)
961 dfilter_free(cf->dfcode);
964 /* Now rescan the packet list, applying the new filter, but not
965 throwing away information constructed on a previous pass. */
966 if (dftext == NULL) {
967 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
969 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
975 colorize_packets(capture_file *cf)
977 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
981 reftime_packets(capture_file *cf)
983 rescan_packets(cf, "Updating Reftime", "all packets", FALSE, FALSE);
987 redissect_packets(capture_file *cf)
989 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
992 /* Rescan the list of packets, reconstructing the CList.
994 "action" describes why we're doing this; it's used in the progress
997 "action_item" describes what we're doing; it's used in the progress
1000 "refilter" is TRUE if we need to re-evaluate the filter expression.
1002 "redissect" is TRUE if we need to make the dissectors reconstruct
1003 any state information they have (because a preference that affects
1004 some dissector has changed, meaning some dissector might construct
1005 its state differently from the way it was constructed the last time). */
1007 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1008 gboolean refilter, gboolean redissect)
1011 progdlg_t *progbar = NULL;
1015 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1016 int selected_row, prev_row, preceding_row, following_row;
1017 gboolean selected_frame_seen;
1020 GTimeVal start_time;
1021 gchar status_str[100];
1022 int progbar_nextstep;
1023 int progbar_quantum;
1026 reset_tap_listeners();
1027 /* Which frame, if any, is the currently selected frame?
1028 XXX - should the selected frame or the focus frame be the "current"
1029 frame, that frame being the one from which "Find Frame" searches
1031 selected_frame = cf->current_frame;
1033 /* We don't yet know what row that frame will be on, if any, after we
1034 rebuild the clist, however. */
1038 /* We need to re-initialize all the state information that protocols
1039 keep, because some preference that controls a dissector has changed,
1040 which might cause the state information to be constructed differently
1041 by that dissector. */
1043 /* Initialize all data structures used for dissection. */
1047 /* Freeze the packet list while we redo it, so we don't get any
1048 screen updates while it happens. */
1049 packet_list_freeze();
1052 packet_list_clear();
1054 /* We don't yet know which will be the first and last frames displayed. */
1055 cf->first_displayed = NULL;
1056 cf->last_displayed = NULL;
1058 /* Iterate through the list of frames. Call a routine for each frame
1059 to check whether it should be displayed and, if so, add it to
1060 the display list. */
1066 /* Update the progress bar when it gets to this value. */
1067 progbar_nextstep = 0;
1068 /* When we reach the value that triggers a progress bar update,
1069 bump that value by this amount. */
1070 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1071 /* Count of packets at which we've looked. */
1075 g_get_current_time(&start_time);
1077 row = -1; /* no previous row yet */
1082 preceding_frame = NULL;
1084 following_frame = NULL;
1086 selected_frame_seen = FALSE;
1088 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1089 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1090 when we update it, we have to run the GTK+ main loop to get it
1091 to repaint what's pending, and doing so may involve an "ioctl()"
1092 to see if there's any pending input from an X server, and doing
1093 that for every packet can be costly, especially on a big file. */
1094 if (count >= progbar_nextstep) {
1095 /* let's not divide by zero. I should never be started
1096 * with count == 0, so let's assert that
1098 g_assert(cf->count > 0);
1099 prog_val = (gfloat) count / cf->count;
1101 if (progbar == NULL)
1102 /* Create the progress bar if necessary */
1103 progbar = delayed_create_progress_dlg(action, action_item, &stop_flag,
1104 &start_time, prog_val);
1106 if (progbar != NULL) {
1107 g_snprintf(status_str, sizeof(status_str),
1108 "%4u of %u frames", count, cf->count);
1109 update_progress_dlg(progbar, prog_val, status_str);
1112 progbar_nextstep += progbar_quantum;
1116 /* Well, the user decided to abort the filtering. Just stop.
1118 XXX - go back to the previous filter? Users probably just
1119 want not to wait for a filtering operation to finish;
1120 unless we cancel by having no filter, reverting to the
1121 previous filter will probably be even more expensive than
1122 continuing the filtering, as it involves going back to the
1123 beginning and filtering, and even with no filter we currently
1124 have to re-generate the entire clist, which is also expensive.
1126 I'm not sure what Network Monitor does, but it doesn't appear
1127 to give you an unfiltered display if you cancel. */
1134 /* Since all state for the frame was destroyed, mark the frame
1135 * as not visited, free the GSList referring to the state
1136 * data (the per-frame data itself was freed by
1137 * "init_dissection()"), and null out the GSList pointer. */
1138 fdata->flags.visited = 0;
1140 g_slist_free(fdata->pfd);
1145 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1146 cf->pd, fdata->cap_len, &err)) {
1147 simple_dialog(ESD_TYPE_CRIT, NULL,
1148 file_read_error_message(err), cf->filename);
1152 /* If the previous frame is displayed, and we haven't yet seen the
1153 selected frame, remember that frame - it's the closest one we've
1154 yet seen before the selected frame. */
1155 if (prev_row != -1 && !selected_frame_seen) {
1156 preceding_row = prev_row;
1157 preceding_frame = prev_frame;
1159 row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
1162 /* If this frame is displayed, and this is the first frame we've
1163 seen displayed after the selected frame, remember this frame -
1164 it's the closest one we've yet seen at or after the selected
1166 if (row != -1 && selected_frame_seen && following_row == -1) {
1167 following_row = row;
1168 following_frame = fdata;
1170 if (fdata == selected_frame) {
1172 selected_frame_seen = TRUE;
1175 /* Remember this row/frame - it'll be the previous row/frame
1176 on the next pass through the loop. */
1182 /* Clear out what remains of the visited flags and per-frame data
1185 XXX - that may cause various forms of bogosity when dissecting
1186 these frames, as they won't have been seen by this sequential
1187 pass, but the only alternative I see is to keep scanning them
1188 even though the user requested that the scan stop, and that
1189 would leave the user stuck with an Ethereal grinding on
1190 until it finishes. Should we just stick them with that? */
1191 for (; fdata != NULL; fdata = fdata->next) {
1192 fdata->flags.visited = 0;
1194 g_slist_free(fdata->pfd);
1200 /* We're done filtering the packets; destroy the progress bar if it
1202 if (progbar != NULL)
1203 destroy_progress_dlg(progbar);
1205 /* Unfreeze the packet list. */
1208 if (selected_row == -1) {
1209 /* The selected frame didn't pass the filter. */
1210 if (selected_frame == NULL) {
1211 /* That's because there *was* no selected frame. Make the first
1212 displayed frame the current frame. */
1215 /* Find the nearest displayed frame to the selected frame (whether
1216 it's before or after that frame) and make that the current frame.
1217 If the next and previous displayed frames are equidistant from the
1218 selected frame, choose the next one. */
1219 g_assert(following_frame == NULL ||
1220 following_frame->num >= selected_frame->num);
1221 g_assert(preceding_frame == NULL ||
1222 preceding_frame->num <= selected_frame->num);
1223 if (following_frame == NULL) {
1224 /* No frame after the selected frame passed the filter, so we
1225 have to select the last displayed frame before the selected
1227 selected_row = preceding_row;
1228 } else if (preceding_frame == NULL) {
1229 /* No frame before the selected frame passed the filter, so we
1230 have to select the first displayed frame after the selected
1232 selected_row = following_row;
1234 /* Choose the closer of the last displayed frame before the
1235 selected frame and the first displayed frame after the
1236 selected frame; in case of a tie, choose the first displayed
1237 frame after the selected frame. */
1238 if (following_frame->num - selected_frame->num <=
1239 selected_frame->num - preceding_frame->num) {
1240 selected_row = following_row;
1242 /* The previous frame is closer to the selected frame than the
1244 selected_row = preceding_row;
1250 if (selected_row == -1) {
1251 /* There are no frames displayed at all. */
1252 unselect_packet(cf);
1254 /* Either the frame that was selected passed the filter, or we've
1255 found the nearest displayed frame to that frame. Select it, make
1256 it the focus row, and make it visible. */
1257 packet_list_set_selected_row(selected_row);
1268 process_specified_packets(capture_file *cf, packet_range_t *range,
1269 const char *string1, const char *string2,
1270 gboolean (*callback)(capture_file *, frame_data *,
1271 union wtap_pseudo_header *, const guint8 *, void *),
1272 void *callback_args)
1276 union wtap_pseudo_header pseudo_header;
1277 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
1278 psp_return_t ret = PSP_FINISHED;
1280 progdlg_t *progbar = NULL;
1283 gboolean progbar_stop_flag;
1284 GTimeVal progbar_start_time;
1285 gchar progbar_status_str[100];
1286 int progbar_nextstep;
1287 int progbar_quantum;
1288 range_process_e process_this;
1290 /* Update the progress bar when it gets to this value. */
1291 progbar_nextstep = 0;
1292 /* When we reach the value that triggers a progress bar update,
1293 bump that value by this amount. */
1294 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1295 /* Count of packets at which we've looked. */
1298 progbar_stop_flag = FALSE;
1299 g_get_current_time(&progbar_start_time);
1301 packet_range_process_init(range);
1303 /* Iterate through the list of packets, printing the packets that
1304 were selected by the current display filter. */
1305 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1306 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1307 when we update it, we have to run the GTK+ main loop to get it
1308 to repaint what's pending, and doing so may involve an "ioctl()"
1309 to see if there's any pending input from an X server, and doing
1310 that for every packet can be costly, especially on a big file. */
1311 if (progbar_count >= progbar_nextstep) {
1312 /* let's not divide by zero. I should never be started
1313 * with count == 0, so let's assert that
1315 g_assert(cf->count > 0);
1316 progbar_val = (gfloat) progbar_count / cf->count;
1318 if (progbar == NULL)
1319 /* Create the progress bar if necessary */
1320 progbar = delayed_create_progress_dlg(string1, string2,
1322 &progbar_start_time,
1325 if (progbar != NULL) {
1326 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
1327 "%4u of %u packets", progbar_count, cf->count);
1328 update_progress_dlg(progbar, progbar_val, progbar_status_str);
1331 progbar_nextstep += progbar_quantum;
1334 if (progbar_stop_flag) {
1335 /* Well, the user decided to abort the operation. Just stop,
1336 and arrange to return TRUE to our caller, so they know it
1337 was stopped explicitly. */
1344 /* do we have to process this packet? */
1345 process_this = packet_range_process_packet(range, fdata);
1346 if (process_this == range_process_next) {
1347 /* this packet uninteresting, continue with next one */
1349 } else if (process_this == range_processing_finished) {
1350 /* all interesting packets processed, stop the loop */
1354 /* Get the packet */
1355 if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1356 pd, fdata->cap_len, &err)) {
1357 /* Attempt to get the packet failed. */
1358 simple_dialog(ESD_TYPE_CRIT, NULL, file_read_error_message(err),
1363 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
1364 /* Callback failed. We assume it reported the error appropriately. */
1370 /* We're done printing the packets; destroy the progress bar if
1372 if (progbar != NULL)
1373 destroy_progress_dlg(progbar);
1379 retap_packet(capture_file *cf _U_, frame_data *fdata,
1380 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1383 epan_dissect_t *edt;
1385 /* If we have tap listeners, allocate a protocol tree root node, so that
1386 we'll construct a protocol tree against which a filter expression can
1388 edt = epan_dissect_new(num_tap_filters != 0, FALSE);
1389 tap_queue_init(edt);
1390 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1391 tap_push_tapped_queue(edt);
1392 epan_dissect_free(edt);
1398 retap_packets(capture_file *cf)
1400 packet_range_t range;
1402 /* Reset the tap listeners. */
1403 reset_tap_listeners();
1405 /* Iterate through the list of packets, dissecting all packets and
1406 re-running the taps. */
1407 packet_range_init(&range);
1408 packet_range_process_init(&range);
1409 switch (process_specified_packets(cf, &range, "Refiltering statistics on",
1410 "all packets", retap_packet,
1413 /* Completed successfully. */
1417 /* Well, the user decided to abort the refiltering.
1418 Return FALSE so our caller knows they did that. */
1422 /* Error while retapping. */
1430 print_args_t *print_args;
1431 gboolean print_separator;
1435 } print_callback_args_t;
1438 print_packet(capture_file *cf, frame_data *fdata,
1439 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1442 print_callback_args_t *args = argsp;
1443 epan_dissect_t *edt;
1450 if (args->print_args->print_summary) {
1451 /* Fill in the column information, but don't bother creating
1452 the logical protocol tree. */
1453 edt = epan_dissect_new(FALSE, FALSE);
1454 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
1455 epan_dissect_fill_in_columns(edt);
1456 cp = &args->line_buf[0];
1458 for (i = 0; i < cf->cinfo.num_cols; i++) {
1459 /* Find the length of the string for this column. */
1460 column_len = strlen(cf->cinfo.col_data[i]);
1461 if (args->col_widths[i] > column_len)
1462 column_len = args->col_widths[i];
1464 /* Make sure there's room in the line buffer for the column; if not,
1465 double its length. */
1466 line_len += column_len + 1; /* "+1" for space */
1467 if (line_len > args->line_buf_len) {
1468 cp_off = cp - args->line_buf;
1469 args->line_buf_len = 2 * line_len;
1470 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
1471 cp = args->line_buf + cp_off;
1474 /* Right-justify the packet number column. */
1475 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1476 sprintf(cp, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
1478 sprintf(cp, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
1480 if (i != cf->cinfo.num_cols - 1)
1484 print_line(cf->print_fh, 0, args->print_args->format, args->line_buf);
1486 if (args->print_separator)
1487 print_line(cf->print_fh, 0, args->print_args->format, "");
1489 /* Create the logical protocol tree, complete with the display
1490 representation of the items; we don't need the columns here,
1492 edt = epan_dissect_new(TRUE, TRUE);
1493 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1495 /* Print the information in that tree. */
1496 proto_tree_print(args->print_args, edt, cf->print_fh);
1498 if (args->print_args->print_hex) {
1499 /* Print the full packet data as hex. */
1500 print_hex_data(cf->print_fh, args->print_args->format, edt);
1503 /* Print a blank line if we print anything after this. */
1504 args->print_separator = TRUE;
1505 } /* if (print_summary) */
1506 epan_dissect_free(edt);
1512 print_packets(capture_file *cf, print_args_t *print_args)
1515 print_callback_args_t callback_args;
1522 cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
1523 if (cf->print_fh == NULL)
1524 return FALSE; /* attempt to open destination failed */
1526 print_preamble(cf->print_fh, print_args->format);
1528 callback_args.print_args = print_args;
1529 callback_args.print_separator = FALSE;
1530 callback_args.line_buf = NULL;
1531 callback_args.line_buf_len = 256;
1532 callback_args.col_widths = NULL;
1533 if (print_args->print_summary) {
1534 /* We're printing packet summaries. Allocate the line buffer at
1535 its initial length. */
1536 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
1538 /* Find the widths for each of the columns - maximum of the
1539 width of the title and the width of the data - and print
1540 the column titles. */
1541 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1542 cp = &callback_args.line_buf[0];
1544 for (i = 0; i < cf->cinfo.num_cols; i++) {
1545 /* Don't pad the last column. */
1546 if (i == cf->cinfo.num_cols - 1)
1547 callback_args.col_widths[i] = 0;
1549 callback_args.col_widths[i] = strlen(cf->cinfo.col_title[i]);
1550 data_width = get_column_char_width(get_column_format(i));
1551 if (data_width > callback_args.col_widths[i])
1552 callback_args.col_widths[i] = data_width;
1555 /* Find the length of the string for this column. */
1556 column_len = strlen(cf->cinfo.col_title[i]);
1557 if (callback_args.col_widths[i] > column_len)
1558 column_len = callback_args.col_widths[i];
1560 /* Make sure there's room in the line buffer for the column; if not,
1561 double its length. */
1562 line_len += column_len + 1; /* "+1" for space */
1563 if (line_len > callback_args.line_buf_len) {
1564 cp_off = cp - callback_args.line_buf;
1565 callback_args.line_buf_len = 2 * line_len;
1566 callback_args.line_buf = g_realloc(callback_args.line_buf,
1567 callback_args.line_buf_len + 1);
1568 cp = callback_args.line_buf + cp_off;
1571 /* Right-justify the packet number column. */
1572 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1573 sprintf(cp, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1575 sprintf(cp, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1577 if (i != cf->cinfo.num_cols - 1)
1581 print_line(cf->print_fh, 0, print_args->format, callback_args.line_buf);
1582 } /* if (print_summary) */
1584 /* Iterate through the list of packets, printing the packets we were
1586 switch (process_specified_packets(cf, &print_args->range, "Printing",
1587 "selected packets", print_packet,
1590 /* Completed successfully. */
1594 /* Well, the user decided to abort the printing.
1596 XXX - note that what got generated before they did that
1597 will get printed, as we're piping to a print program; we'd
1598 have to write to a file and then hand that to the print
1599 program to make it actually not print anything. */
1603 /* Error while saving. */
1607 if (callback_args.col_widths != NULL)
1608 g_free(callback_args.col_widths);
1609 if (callback_args.line_buf != NULL)
1610 g_free(callback_args.line_buf);
1612 print_finale(cf->print_fh, print_args->format);
1614 close_print_dest(print_args->to_file, cf->print_fh);
1616 cf->print_fh = NULL;
1621 /* Scan through the packet list and change all columns that use the
1622 "command-line-specified" time stamp format to use the current
1623 value of that format. */
1625 change_time_formats(capture_file *cf)
1628 progdlg_t *progbar = NULL;
1634 GTimeVal start_time;
1635 gchar status_str[100];
1636 int progbar_nextstep;
1637 int progbar_quantum;
1639 gboolean sorted_by_frame_column;
1641 /* Are there any columns with time stamps in the "command-line-specified"
1644 XXX - we have to force the "column is writable" flag on, as it
1645 might be off from the last frame that was dissected. */
1646 col_set_writable(&cf->cinfo, TRUE);
1647 if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
1648 /* No, there aren't any columns in that format, so we have no work
1652 first = cf->cinfo.col_first[COL_CLS_TIME];
1653 g_assert(first >= 0);
1654 last = cf->cinfo.col_last[COL_CLS_TIME];
1656 /* Freeze the packet list while we redo it, so we don't get any
1657 screen updates while it happens. */
1658 packet_list_freeze();
1660 /* Update the progress bar when it gets to this value. */
1661 progbar_nextstep = 0;
1662 /* When we reach the value that triggers a progress bar update,
1663 bump that value by this amount. */
1664 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1665 /* Count of packets at which we've looked. */
1668 /* If the rows are currently sorted by the frame column then we know
1669 * the row number of each packet: it's the row number of the previously
1670 * displayed packet + 1.
1672 * Otherwise, if the display is sorted by a different column then we have
1673 * to use the O(N) packet_list_find_row_from_data() (thus making the job
1674 * of changing the time display format O(N**2)).
1676 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
1677 * the row number and walks that many elements down the clist to find
1678 * the appropriate element.)
1680 sorted_by_frame_column = FALSE;
1681 for (i = 0; i < cf->cinfo.num_cols; i++) {
1682 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1684 sorted_by_frame_column = (i == packet_list_get_sort_column());
1690 g_get_current_time(&start_time);
1692 /* Iterate through the list of packets, checking whether the packet
1693 is in a row of the summary list and, if so, whether there are
1694 any columns that show the time in the "command-line-specified"
1695 format and, if so, update that row. */
1696 for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
1697 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1698 when we update it, we have to run the GTK+ main loop to get it
1699 to repaint what's pending, and doing so may involve an "ioctl()"
1700 to see if there's any pending input from an X server, and doing
1701 that for every packet can be costly, especially on a big file. */
1702 if (count >= progbar_nextstep) {
1703 /* let's not divide by zero. I should never be started
1704 * with count == 0, so let's assert that
1706 g_assert(cf->count > 0);
1708 prog_val = (gfloat) count / cf->count;
1710 if (progbar == NULL)
1711 /* Create the progress bar if necessary */
1712 progbar = delayed_create_progress_dlg("Changing", "time display",
1713 &stop_flag, &start_time, prog_val);
1715 if (progbar != NULL) {
1716 g_snprintf(status_str, sizeof(status_str),
1717 "%4u of %u packets", count, cf->count);
1718 update_progress_dlg(progbar, prog_val, status_str);
1721 progbar_nextstep += progbar_quantum;
1725 /* Well, the user decided to abort the redisplay. Just stop.
1727 XXX - this leaves the time field in the old format in
1728 frames we haven't yet processed. So it goes; should we
1729 simply not offer them the option of stopping? */
1735 /* Find what row this packet is in. */
1736 if (!sorted_by_frame_column) {
1737 /* This function is O(N), so we try to avoid using it... */
1738 row = packet_list_find_row_from_data(fdata);
1740 /* ...which we do by maintaining a count of packets that are
1741 being displayed (i.e., that have passed the display filter),
1742 and using the current value of that count as the row number
1743 (which is why we can only do it when the display is sorted
1744 by the frame number). */
1745 if (fdata->flags.passed_dfilter)
1752 /* This packet is in the summary list, on row "row". */
1754 for (i = first; i <= last; i++) {
1755 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1756 /* This is one of the columns that shows the time in
1757 "command-line-specified" format; update it. */
1758 cf->cinfo.col_buf[i][0] = '\0';
1759 col_set_cls_time(fdata, &cf->cinfo, i);
1760 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
1766 /* We're done redisplaying the packets; destroy the progress bar if it
1768 if (progbar != NULL)
1769 destroy_progress_dlg(progbar);
1771 /* Set the column widths of those columns that show the time in
1772 "command-line-specified" format. */
1773 for (i = first; i <= last; i++) {
1774 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1775 packet_list_set_cls_time_width(i);
1779 /* Unfreeze the packet list. */
1787 gboolean frame_matched;
1791 find_packet_protocol_tree(capture_file *cf, const char *string)
1795 mdata.string = string;
1796 mdata.string_len = strlen(string);
1797 return find_packet(cf, match_protocol_tree, &mdata);
1801 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
1803 match_data *mdata = criterion;
1804 epan_dissect_t *edt;
1806 /* Construct the protocol tree, including the displayed text */
1807 edt = epan_dissect_new(TRUE, TRUE);
1808 /* We don't need the column information */
1809 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
1811 /* Iterate through all the nodes, seeing if they have text that matches. */
1813 mdata->frame_matched = FALSE;
1814 proto_tree_children_foreach(edt->tree, match_subtree_text, mdata);
1815 epan_dissect_free(edt);
1816 return mdata->frame_matched;
1820 match_subtree_text(proto_node *node, gpointer data)
1822 match_data *mdata = (match_data*) data;
1823 const gchar *string = mdata->string;
1824 size_t string_len = mdata->string_len;
1825 capture_file *cf = mdata->cf;
1826 field_info *fi = PITEM_FINFO(node);
1827 gchar label_str[ITEM_LABEL_LENGTH];
1834 if (mdata->frame_matched) {
1835 /* We already had a match; don't bother doing any more work. */
1839 /* Don't match invisible entries. */
1843 /* was a free format label produced? */
1845 label_ptr = fi->rep->representation;
1847 /* no, make a generic label */
1848 label_ptr = label_str;
1849 proto_item_fill_label(fi, label_str);
1852 /* Does that label match? */
1853 label_len = strlen(label_ptr);
1854 for (i = 0; i < label_len; i++) {
1855 c_char = label_ptr[i];
1857 c_char = toupper(c_char);
1858 if (c_char == string[c_match]) {
1860 if (c_match == string_len) {
1861 /* No need to look further; we have a match */
1862 mdata->frame_matched = TRUE;
1869 /* Recurse into the subtree, if it exists */
1870 if (node->first_child != NULL)
1871 proto_tree_children_foreach(node, match_subtree_text, mdata);
1875 find_packet_summary_line(capture_file *cf, const char *string)
1879 mdata.string = string;
1880 mdata.string_len = strlen(string);
1881 return find_packet(cf, match_summary_line, &mdata);
1885 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
1887 match_data *mdata = criterion;
1888 const gchar *string = mdata->string;
1889 size_t string_len = mdata->string_len;
1890 epan_dissect_t *edt;
1891 const char *info_column;
1892 size_t info_column_len;
1893 gboolean frame_matched = FALSE;
1899 /* Don't bother constructing the protocol tree */
1900 edt = epan_dissect_new(FALSE, FALSE);
1901 /* Get the column information */
1902 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
1904 /* Find the Info column */
1905 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
1906 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
1907 /* Found it. See if we match. */
1908 info_column = edt->pi.cinfo->col_data[colx];
1909 info_column_len = strlen(info_column);
1910 for (i = 0; i < info_column_len; i++) {
1911 c_char = info_column[i];
1913 c_char = toupper(c_char);
1914 if (c_char == string[c_match]) {
1916 if (c_match == string_len) {
1917 frame_matched = TRUE;
1926 epan_dissect_free(edt);
1927 return frame_matched;
1933 } cbs_t; /* "Counted byte string" */
1936 find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
1941 info.data_len = string_size;
1943 /* String or hex search? */
1945 /* String search - what type of string? */
1946 switch (cf->scs_type) {
1948 case SCS_ASCII_AND_UNICODE:
1949 return find_packet(cf, match_ascii_and_unicode, &info);
1952 return find_packet(cf, match_ascii, &info);
1955 return find_packet(cf, match_unicode, &info);
1958 g_assert_not_reached();
1962 return find_packet(cf, match_binary, &info);
1966 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
1968 cbs_t *info = criterion;
1969 const char *ascii_text = info->data;
1970 size_t textlen = info->data_len;
1971 gboolean frame_matched;
1977 frame_matched = FALSE;
1978 buf_len = fdata->pkt_len;
1979 for (i = 0; i < buf_len; i++) {
1982 c_char = toupper(c_char);
1984 if (c_char == ascii_text[c_match]) {
1986 if (c_match == textlen) {
1987 frame_matched = TRUE;
1994 return frame_matched;
1998 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2000 cbs_t *info = criterion;
2001 const char *ascii_text = info->data;
2002 size_t textlen = info->data_len;
2003 gboolean frame_matched;
2009 frame_matched = FALSE;
2010 buf_len = fdata->pkt_len;
2011 for (i = 0; i < buf_len; i++) {
2014 c_char = toupper(c_char);
2015 if (c_char == ascii_text[c_match]) {
2017 if (c_match == textlen) {
2018 frame_matched = TRUE;
2024 return frame_matched;
2028 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2030 cbs_t *info = criterion;
2031 const char *ascii_text = info->data;
2032 size_t textlen = info->data_len;
2033 gboolean frame_matched;
2039 frame_matched = FALSE;
2040 buf_len = fdata->pkt_len;
2041 for (i = 0; i < buf_len; i++) {
2044 c_char = toupper(c_char);
2045 if (c_char == ascii_text[c_match]) {
2048 if (c_match == textlen) {
2049 frame_matched = TRUE;
2055 return frame_matched;
2059 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
2061 cbs_t *info = criterion;
2062 const guint8 *binary_data = info->data;
2063 size_t datalen = info->data_len;
2064 gboolean frame_matched;
2069 frame_matched = FALSE;
2070 buf_len = fdata->pkt_len;
2071 for (i = 0; i < buf_len; i++) {
2072 if (cf->pd[i] == binary_data[c_match]) {
2074 if (c_match == datalen) {
2075 frame_matched = TRUE;
2081 return frame_matched;
2085 find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
2087 return find_packet(cf, match_dfilter, sfcode);
2091 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
2093 dfilter_t *sfcode = criterion;
2094 epan_dissect_t *edt;
2095 gboolean frame_matched;
2097 edt = epan_dissect_new(TRUE, FALSE);
2098 epan_dissect_prime_dfilter(edt, sfcode);
2099 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2100 frame_matched = dfilter_apply_edt(sfcode, edt);
2101 epan_dissect_free(edt);
2102 return frame_matched;
2106 find_packet(capture_file *cf,
2107 gboolean (*match_function)(capture_file *, frame_data *, void *),
2110 frame_data *start_fd;
2112 frame_data *new_fd = NULL;
2113 progdlg_t *progbar = NULL;
2119 GTimeVal start_time;
2120 gchar status_str[100];
2121 int progbar_nextstep;
2122 int progbar_quantum;
2124 start_fd = cf->current_frame;
2125 if (start_fd != NULL) {
2126 /* Iterate through the list of packets, starting at the packet we've
2127 picked, calling a routine to run the filter on the packet, see if
2128 it matches, and stop if so. */
2132 progbar_nextstep = 0;
2133 /* When we reach the value that triggers a progress bar update,
2134 bump that value by this amount. */
2135 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2138 g_get_current_time(&start_time);
2142 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2143 when we update it, we have to run the GTK+ main loop to get it
2144 to repaint what's pending, and doing so may involve an "ioctl()"
2145 to see if there's any pending input from an X server, and doing
2146 that for every packet can be costly, especially on a big file. */
2147 if (count >= progbar_nextstep) {
2148 /* let's not divide by zero. I should never be started
2149 * with count == 0, so let's assert that
2151 g_assert(cf->count > 0);
2153 prog_val = (gfloat) count / cf->count;
2155 /* Create the progress bar if necessary */
2156 if (progbar == NULL)
2157 progbar = delayed_create_progress_dlg("Searching", cf->sfilter,
2158 &stop_flag, &start_time, prog_val);
2160 if (progbar != NULL) {
2161 g_snprintf(status_str, sizeof(status_str),
2162 "%4u of %u packets", count, cf->count);
2163 update_progress_dlg(progbar, prog_val, status_str);
2166 progbar_nextstep += progbar_quantum;
2170 /* Well, the user decided to abort the search. Go back to the
2171 frame where we started. */
2176 /* Go past the current frame. */
2177 if (cf->sbackward) {
2178 /* Go on to the previous frame. */
2179 fdata = fdata->prev;
2181 fdata = cf->plist_end; /* wrap around */
2183 /* Go on to the next frame. */
2184 fdata = fdata->next;
2186 fdata = cf->plist; /* wrap around */
2191 /* Is this packet in the display? */
2192 if (fdata->flags.passed_dfilter) {
2193 /* Yes. Load its data. */
2194 if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
2195 cf->pd, fdata->cap_len, &err)) {
2196 /* Read error. Report the error, and go back to the frame
2197 where we started. */
2198 simple_dialog(ESD_TYPE_CRIT, NULL,
2199 file_read_error_message(err), cf->filename);
2204 /* Does it match the search criterion? */
2205 if ((*match_function)(cf, fdata, criterion)) {
2207 break; /* found it! */
2211 if (fdata == start_fd) {
2212 /* We're back to the frame we were on originally, and that frame
2213 doesn't match the search filter. The search failed. */
2218 /* We're done scanning the packets; destroy the progress bar if it
2220 if (progbar != NULL)
2221 destroy_progress_dlg(progbar);
2224 if (new_fd != NULL) {
2225 /* We found a frame. Find what row it's in. */
2226 row = packet_list_find_row_from_data(new_fd);
2227 g_assert(row != -1);
2229 /* Select that row, make it the focus row, and make it visible. */
2230 packet_list_set_selected_row(row);
2231 return TRUE; /* success */
2233 return FALSE; /* failure */
2237 goto_frame(capture_file *cf, guint fnumber)
2242 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
2245 if (fdata == NULL) {
2246 /* we didn't find a packet with that packet number */
2247 simple_dialog(ESD_TYPE_CRIT, NULL,
2248 "There is no packet with that packet number.");
2249 return FALSE; /* we failed to go to that packet */
2251 if (!fdata->flags.passed_dfilter) {
2252 /* that packet currently isn't displayed */
2253 /* XXX - add it to the set of displayed packets? */
2254 simple_dialog(ESD_TYPE_CRIT, NULL,
2255 "That packet is not currently being displayed.");
2256 return FALSE; /* we failed to go to that packet */
2259 /* We found that packet, and it's currently being displayed.
2260 Find what row it's in. */
2261 row = packet_list_find_row_from_data(fdata);
2262 g_assert(row != -1);
2264 /* Select that row, make it the focus row, and make it visible. */
2265 packet_list_set_selected_row(row);
2266 return TRUE; /* we got to that packet */
2270 goto_top_frame(capture_file *cf)
2274 frame_data *lowest_fdata = NULL;
2276 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2277 if (fdata->flags.passed_dfilter) {
2278 lowest_fdata = fdata;
2283 if (lowest_fdata == NULL) {
2287 /* We found that packet, and it's currently being displayed.
2288 Find what row it's in. */
2289 row = packet_list_find_row_from_data(lowest_fdata);
2290 g_assert(row != -1);
2292 /* Select that row, make it the focus row, and make it visible. */
2293 packet_list_set_selected_row(row);
2294 return TRUE; /* we got to that packet */
2298 goto_bottom_frame(capture_file *cf)
2302 frame_data *highest_fdata = NULL;
2304 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2305 if (fdata->flags.passed_dfilter) {
2306 highest_fdata = fdata;
2310 if (highest_fdata == NULL) {
2314 /* We found that packet, and it's currently being displayed.
2315 Find what row it's in. */
2316 row = packet_list_find_row_from_data(highest_fdata);
2317 g_assert(row != -1);
2319 /* Select that row, make it the focus row, and make it visible. */
2320 packet_list_set_selected_row(row);
2321 return TRUE; /* we got to that packet */
2324 /* Select the packet on a given row. */
2326 select_packet(capture_file *cf, int row)
2331 /* Get the frame data struct pointer for this frame */
2332 fdata = (frame_data *)packet_list_get_row_data(row);
2334 if (fdata == NULL) {
2335 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
2336 the first entry is added to it by "real_insert_row()", that row
2337 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
2338 our version and the vanilla GTK+ version).
2340 This means that a "select-row" signal is emitted; this causes
2341 "packet_list_select_cb()" to be called, which causes "select_packet()"
2344 "select_packet()" fetches, above, the data associated with the
2345 row that was selected; however, as "gtk_clist_append()", which
2346 called "real_insert_row()", hasn't yet returned, we haven't yet
2347 associated any data with that row, so we get back a null pointer.
2349 We can't assume that there's only one frame in the frame list,
2350 either, as we may be filtering the display.
2352 We therefore assume that, if "row" is 0, i.e. the first row
2353 is being selected, and "cf->first_displayed" equals
2354 "cf->last_displayed", i.e. there's only one frame being
2355 displayed, that frame is the frame we want.
2357 This means we have to set "cf->first_displayed" and
2358 "cf->last_displayed" before adding the row to the
2359 GtkCList; see the comment in "add_packet_to_packet_list()". */
2361 if (row == 0 && cf->first_displayed == cf->last_displayed)
2362 fdata = cf->first_displayed;
2365 /* Get the data in that frame. */
2366 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
2367 cf->pd, fdata->cap_len, &err)) {
2368 simple_dialog(ESD_TYPE_CRIT, NULL,
2369 file_read_error_message(err), cf->filename);
2373 /* Record that this frame is the current frame. */
2374 cf->current_frame = fdata;
2376 /* Create the logical protocol tree. */
2377 if (cf->edt != NULL) {
2378 epan_dissect_free(cf->edt);
2381 /* We don't need the columns here. */
2382 cf->edt = epan_dissect_new(TRUE, TRUE);
2383 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
2386 /* Display the GUI protocol tree and hex dump.
2387 XXX - why do we dump core if we call "proto_tree_draw()"
2388 before calling "add_byte_views()"? */
2389 add_main_byte_views(cf->edt);
2390 main_proto_tree_draw(cf->edt->tree);
2392 /* A packet is selected. */
2393 set_menus_for_selected_packet(cf);
2396 /* Unselect the selected packet, if any. */
2398 unselect_packet(capture_file *cf)
2400 /* Destroy the epan_dissect_t for the unselected packet. */
2401 if (cf->edt != NULL) {
2402 epan_dissect_free(cf->edt);
2406 /* Clear out the display of that packet. */
2407 clear_tree_and_hex_views();
2409 /* No packet is selected. */
2410 cf->current_frame = NULL;
2411 set_menus_for_selected_packet(cf);
2413 /* No protocol tree means no selected field. */
2417 /* Unset the selected protocol tree field, if any. */
2419 unselect_field(capture_file *cf)
2421 statusbar_pop_field_msg();
2422 cf->finfo_selected = NULL;
2423 set_menus_for_selected_tree_row(cf);
2427 * Mark a particular frame.
2430 mark_frame(capture_file *cf, frame_data *frame)
2432 frame->flags.marked = TRUE;
2437 * Unmark a particular frame.
2440 unmark_frame(capture_file *cf, frame_data *frame)
2442 frame->flags.marked = FALSE;
2449 } save_callback_args_t;
2452 * Save a capture to a file, in a particular format, saving either
2453 * all packets, all currently-displayed packets, or all marked packets.
2455 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
2456 * up a message box for the failure.
2459 save_packet(capture_file *cf _U_, frame_data *fdata,
2460 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2463 save_callback_args_t *args = argsp;
2464 struct wtap_pkthdr hdr;
2467 /* init the wtap header for saving */
2468 hdr.ts.tv_sec = fdata->abs_secs;
2469 hdr.ts.tv_usec = fdata->abs_usecs;
2470 hdr.caplen = fdata->cap_len;
2471 hdr.len = fdata->pkt_len;
2472 hdr.pkt_encap = fdata->lnk_t;
2474 /* and save the packet */
2475 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
2476 simple_dialog(ESD_TYPE_CRIT, NULL, file_write_error_message(err),
2484 cf_save(char *fname, capture_file *cf, packet_range_t *range, guint save_format)
2486 gchar *from_filename;
2487 gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
2492 struct stat infile, outfile;
2493 save_callback_args_t callback_args;
2495 name_ptr = get_basename(fname);
2496 msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
2497 save_msg = g_malloc(msg_len);
2498 snprintf(save_msg, msg_len, save_fmt, name_ptr);
2499 statusbar_push_file_msg(save_msg);
2503 * Check that the from file is not the same as to file
2504 * We do it here so we catch all cases ...
2505 * Unfortunately, the file requester gives us an absolute file
2506 * name and the read file name may be relative (if supplied on
2507 * the command line). From Joerg Mayer.
2509 infile.st_ino = 1; /* These prevent us from getting equality */
2510 outfile.st_ino = 2; /* If one or other of the files is not accessible */
2511 stat(cf->filename, &infile);
2512 stat(fname, &outfile);
2513 if (infile.st_ino == outfile.st_ino) {
2514 simple_dialog(ESD_TYPE_CRIT, NULL,
2515 "Can't save over current capture file: %s!",
2520 packet_range_process_init(range);
2523 * if (!save_filtered && !save_marked && !save_manual_range &&
2524 * !save_marked_range && !save_curr && save_format == cf->cd_t) {
2527 if (packet_range_process_all(range) && save_format == cf->cd_t) {
2528 /* We're not filtering packets, and we're saving it in the format
2529 it's already in, so we can just move or copy the raw data. */
2531 if (cf->is_tempfile) {
2532 /* The file being saved is a temporary file from a live
2533 capture, so it doesn't need to stay around under that name;
2534 first, try renaming the capture buffer file to the new name. */
2536 if (rename(cf->filename, fname) == 0) {
2537 /* That succeeded - there's no need to copy the source file. */
2538 from_filename = NULL;
2541 if (errno == EXDEV) {
2542 /* They're on different file systems, so we have to copy the
2545 from_filename = cf->filename;
2547 /* The rename failed, but not because they're on different
2548 file systems - put up an error message. (Or should we
2549 just punt and try to copy? The only reason why I'd
2550 expect the rename to fail and the copy to succeed would
2551 be if we didn't have permission to remove the file from
2552 the temporary directory, and that might be fixable - but
2553 is it worth requiring the user to go off and fix it?) */
2554 simple_dialog(ESD_TYPE_CRIT, NULL,
2555 file_rename_error_message(errno), fname);
2561 from_filename = cf->filename;
2564 /* It's a permanent file, so we should copy it, and not remove the
2567 from_filename = cf->filename;
2571 /* Copy the file, if we haven't moved it. */
2572 if (!copy_binary_file(from_filename, fname))
2576 /* Either we're filtering packets, or we're saving in a different
2577 format; we can't do that by copying or moving the capture file,
2578 we have to do it by writing the packets out in Wiretap. */
2579 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
2581 simple_dialog(ESD_TYPE_CRIT, NULL,
2582 file_open_error_message(err, TRUE, save_format), fname);
2586 /* XXX - we let the user save a subset of the packets.
2588 If we do that, should we make that file the current file? If so,
2589 it means we can no longer get at the other packets. What does
2592 /* Iterate through the list of packets, printing the packets we were
2595 XXX - we've already called "packet_range_process_init(range)", but
2596 "process_specified_packets()" will do it again. Fortunately,
2597 that's harmless in this case, as we haven't done anything to
2598 "range" since we initialized it. */
2599 callback_args.pdh = pdh;
2600 callback_args.fname = fname;
2601 switch (process_specified_packets(cf, range, "Saving",
2602 "selected packets", save_packet,
2606 /* Completed successfully. */
2610 /* The user decided to abort the saving.
2611 XXX - remove the output file? */
2615 /* Error while saving. */
2616 wtap_dump_close(pdh, &err);
2620 if (!wtap_dump_close(pdh, &err)) {
2621 simple_dialog(ESD_TYPE_WARN, NULL, file_close_error_message(err), fname);
2626 /* Pop the "Saving:" message off the status bar. */
2627 statusbar_pop_file_msg();
2629 /* XXX: I'm not sure how this should look like! */
2630 if (packet_range_process_all(range)) {
2631 /*if (!save_filtered && !save_marked) {*/
2632 /* We saved the entire capture, not just some packets from it.
2633 Open and read the file we saved it to.
2635 XXX - this is somewhat of a waste; we already have the
2636 packets, all this gets us is updated file type information
2637 (which we could just stuff into "cf"), and having the new
2638 file be the one we have opened and from which we're reading
2639 the data, and it means we have to spend time opening and
2640 reading the file, which could be a significant amount of
2641 time if the file is large. */
2642 cf->user_saved = TRUE;
2644 if ((err = cf_open(fname, FALSE, cf)) == 0) {
2645 /* XXX - report errors if this fails?
2646 What should we return if it fails or is aborted? */
2647 switch (cf_read(cf, &err)) {
2651 /* Just because we got an error, that doesn't mean we were unable
2652 to read any of the file; we handle what we could get from the
2657 /* The user bailed out of re-reading the capture file; the
2658 capture file has been closed - just return (without
2659 changing any menu settings; "cf_close()" set them
2660 correctly for the "no capture file open" state). */
2663 set_menus_for_unsaved_capture_file(FALSE);
2669 /* Pop the "Saving:" message off the status bar. */
2670 statusbar_pop_file_msg();
2675 file_open_error_message(int err, gboolean for_writing, int file_type)
2678 static char errmsg_errno[1024+1];
2682 case WTAP_ERR_NOT_REGULAR_FILE:
2683 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
2686 case WTAP_ERR_RANDOM_OPEN_PIPE:
2687 /* Seen only when opening a capture file for reading. */
2688 errmsg = "The file \"%s\" is a pipe or FIFO; Ethereal cannot read pipe or FIFO files.";
2691 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
2692 case WTAP_ERR_UNSUPPORTED:
2693 /* Seen only when opening a capture file for reading. */
2694 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
2697 case WTAP_ERR_CANT_WRITE_TO_PIPE:
2698 /* Seen only when opening a capture file for writing. */
2699 snprintf(errmsg_errno, sizeof(errmsg_errno),
2700 "The file \"%%s\" is a pipe, and %s capture files cannot be "
2701 "written to a pipe.", wtap_file_type_string(file_type));
2702 errmsg = errmsg_errno;
2705 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
2706 /* Seen only when opening a capture file for writing. */
2707 errmsg = "Ethereal does not support writing capture files in that format.";
2710 case WTAP_ERR_UNSUPPORTED_ENCAP:
2711 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
2713 errmsg = "Ethereal cannot save this capture in that format.";
2715 errmsg = "The file \"%s\" is a capture for a network type that Ethereal doesn't support.";
2718 case WTAP_ERR_BAD_RECORD:
2719 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
2722 case WTAP_ERR_CANT_OPEN:
2724 errmsg = "The file \"%s\" could not be created for some unknown reason.";
2726 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
2729 case WTAP_ERR_SHORT_READ:
2730 errmsg = "The file \"%s\" appears to have been cut short"
2731 " in the middle of a packet or other data.";
2734 case WTAP_ERR_SHORT_WRITE:
2735 errmsg = "A full header couldn't be written to the file \"%s\".";
2740 errmsg = "The path to the file \"%s\" does not exist.";
2742 errmsg = "The file \"%s\" does not exist.";
2747 errmsg = "You do not have permission to create or write to the file \"%s\".";
2749 errmsg = "You do not have permission to read the file \"%s\".";
2753 errmsg = "\"%s\" is a directory (folder), not a file.";
2757 snprintf(errmsg_errno, sizeof(errmsg_errno),
2758 "The file \"%%s\" could not be %s: %s.",
2759 for_writing ? "created" : "opened",
2760 wtap_strerror(err));
2761 errmsg = errmsg_errno;
2768 file_rename_error_message(int err)
2771 static char errmsg_errno[1024+1];
2776 errmsg = "The path to the file \"%s\" does not exist.";
2780 errmsg = "You do not have permission to move the capture file to \"%s\".";
2784 snprintf(errmsg_errno, sizeof(errmsg_errno),
2785 "The file \"%%s\" could not be moved: %s.",
2786 wtap_strerror(err));
2787 errmsg = errmsg_errno;
2794 file_read_error_message(int err)
2796 static char errmsg_errno[1024+1];
2798 snprintf(errmsg_errno, sizeof(errmsg_errno),
2799 "An error occurred while reading from the file \"%%s\": %s.",
2800 wtap_strerror(err));
2801 return errmsg_errno;
2805 file_write_error_message(int err)
2808 static char errmsg_errno[1024+1];
2813 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
2818 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
2823 snprintf(errmsg_errno, sizeof(errmsg_errno),
2824 "An error occurred while writing to the file \"%%s\": %s.",
2825 wtap_strerror(err));
2826 errmsg = errmsg_errno;
2832 /* Check for write errors - if the file is being written to an NFS server,
2833 a write error may not show up until the file is closed, as NFS clients
2834 might not send writes to the server until the "write()" call finishes,
2835 so that the write may fail on the server but the "write()" may succeed. */
2837 file_close_error_message(int err)
2840 static char errmsg_errno[1024+1];
2844 case WTAP_ERR_CANT_CLOSE:
2845 errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
2848 case WTAP_ERR_SHORT_WRITE:
2849 errmsg = "Not all the packets could be written to the file \"%s\".";
2853 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
2858 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
2863 snprintf(errmsg_errno, sizeof(errmsg_errno),
2864 "An error occurred while closing the file \"%%s\": %s.",
2865 wtap_strerror(err));
2866 errmsg = errmsg_errno;
2873 /* Copies a file in binary mode, for those operating systems that care about
2875 * Returns TRUE on success, FALSE on failure. If a failure, it also
2876 * displays a simple dialog window with the error message.
2879 copy_binary_file(char *from_filename, char *to_filename)
2881 int from_fd, to_fd, nread, nwritten, err;
2884 /* Copy the raw bytes of the file. */
2885 from_fd = open(from_filename, O_RDONLY | O_BINARY);
2888 simple_dialog(ESD_TYPE_CRIT, NULL,
2889 file_open_error_message(err, TRUE, 0), from_filename);
2893 /* Use open() instead of creat() so that we can pass the O_BINARY
2894 flag, which is relevant on Win32; it appears that "creat()"
2895 may open the file in text mode, not binary mode, but we want
2896 to copy the raw bytes of the file, so we need the output file
2897 to be open in binary mode. */
2898 to_fd = open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
2901 simple_dialog(ESD_TYPE_CRIT, NULL,
2902 file_open_error_message(err, TRUE, 0), to_filename);
2907 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
2908 nwritten = write(to_fd, pd, nread);
2909 if (nwritten < nread) {
2913 err = WTAP_ERR_SHORT_WRITE;
2914 simple_dialog(ESD_TYPE_CRIT, NULL,
2915 file_write_error_message(err), to_filename);
2923 simple_dialog(ESD_TYPE_CRIT, NULL,
2924 file_read_error_message(err), from_filename);
2930 if (close(to_fd) < 0) {
2932 simple_dialog(ESD_TYPE_CRIT, NULL,
2933 file_close_error_message(err), to_filename);