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 NEED_STRERROR_H
50 #include <epan/epan.h>
51 #include <epan/filesystem.h>
54 #include "color_filters.h"
55 #include <epan/column.h>
56 #include <epan/packet.h>
57 #include "packet-range.h"
63 #include "alert_box.h"
64 #include "simple_dialog.h"
65 #include "progress_dlg.h"
67 #include <epan/prefs.h>
68 #include <epan/dfilter/dfilter.h>
69 #include <epan/conversation.h>
70 #include <epan/epan_dissect.h>
72 #include "stat_menu.h"
73 #include "tap_dfilter_dlg.h"
74 #include <epan/dissectors/packet-data.h>
75 #include <epan/timestamp.h>
76 #include "file_util.h"
81 gboolean auto_scroll_live;
84 static nstime_t first_ts;
85 static nstime_t prev_ts;
86 static guint32 cum_bytes = 0;
88 static void cf_reset_state(capture_file *cf);
90 static void read_packet(capture_file *cf, long offset);
92 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
93 gboolean refilter, gboolean redissect);
95 static gboolean match_protocol_tree(capture_file *cf, frame_data *fdata,
97 static void match_subtree_text(proto_node *node, gpointer data);
98 static gboolean match_summary_line(capture_file *cf, frame_data *fdata,
100 static gboolean match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
102 static gboolean match_ascii(capture_file *cf, frame_data *fdata,
104 static gboolean match_unicode(capture_file *cf, frame_data *fdata,
106 static gboolean match_binary(capture_file *cf, frame_data *fdata,
108 static gboolean match_dfilter(capture_file *cf, frame_data *fdata,
110 static gboolean find_packet(capture_file *cf,
111 gboolean (*match_function)(capture_file *, frame_data *, void *),
114 static void cf_open_failure_alert_box(const char *filename, int err,
115 gchar *err_info, gboolean for_writing,
117 static const char *file_rename_error_message(int err);
118 static void cf_write_failure_alert_box(const char *filename, int err);
119 static void cf_close_failure_alert_box(const char *filename, int err);
120 static gboolean copy_binary_file(const char *from_filename, const 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
130 /* one callback for now, we could have a list later */
131 static cf_callback_t cf_cb = NULL;
132 static gpointer cf_cb_user_data = NULL;
135 cf_callback_invoke(int event, gpointer data)
137 g_assert(cf_cb != NULL);
138 cf_cb(event, data, cf_cb_user_data);
143 cf_callback_add(cf_callback_t func, gpointer user_data)
145 /* More than one callback listener is currently not implemented,
146 but should be easy to do. */
147 g_assert(cf_cb == NULL);
149 cf_cb_user_data = user_data;
153 cf_callback_remove(cf_callback_t func _U_)
155 g_assert(cf_cb != NULL);
157 cf_cb_user_data = NULL;
161 cf_timestamp_auto_precision(capture_file *cf)
163 int prec = timestamp_get_precision();
166 /* don't try to get the file's precision if none is opened */
167 if(cf->state == FILE_CLOSED) {
171 /* if we are in auto mode, set precision of current file */
172 if(prec == TS_PREC_AUTO ||
173 prec == TS_PREC_AUTO_SEC ||
174 prec == TS_PREC_AUTO_DSEC ||
175 prec == TS_PREC_AUTO_CSEC ||
176 prec == TS_PREC_AUTO_MSEC ||
177 prec == TS_PREC_AUTO_USEC ||
178 prec == TS_PREC_AUTO_NSEC)
180 switch(wtap_file_tsprecision(cf->wth)) {
181 case(WTAP_FILE_TSPREC_SEC):
182 timestamp_set_precision(TS_PREC_AUTO_SEC);
184 case(WTAP_FILE_TSPREC_DSEC):
185 timestamp_set_precision(TS_PREC_AUTO_DSEC);
187 case(WTAP_FILE_TSPREC_CSEC):
188 timestamp_set_precision(TS_PREC_AUTO_CSEC);
190 case(WTAP_FILE_TSPREC_MSEC):
191 timestamp_set_precision(TS_PREC_AUTO_MSEC);
193 case(WTAP_FILE_TSPREC_USEC):
194 timestamp_set_precision(TS_PREC_AUTO_USEC);
196 case(WTAP_FILE_TSPREC_NSEC):
197 timestamp_set_precision(TS_PREC_AUTO_NSEC);
200 g_assert_not_reached();
207 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
212 wth = wtap_open_offline(fname, err, &err_info, TRUE);
216 /* The open succeeded. Close whatever capture file we had open,
217 and fill in the information for this file. */
220 /* Initialize all data structures used for dissection. */
223 /* We're about to start reading the file. */
224 cf->state = FILE_READ_IN_PROGRESS;
229 /* Set the file name because we need it to set the follow stream filter.
230 XXX - is that still true? We need it for other reasons, though,
232 cf->filename = g_strdup(fname);
234 /* Indicate whether it's a permanent or temporary file. */
235 cf->is_tempfile = is_tempfile;
237 /* If it's a temporary capture buffer file, mark it as not saved. */
238 cf->user_saved = !is_tempfile;
240 cf->cd_t = wtap_file_type(cf->wth);
242 cf->displayed_count = 0;
243 cf->marked_count = 0;
244 cf->drops_known = FALSE;
246 cf->snap = wtap_snapshot_length(cf->wth);
248 /* Snapshot length not known. */
249 cf->has_snap = FALSE;
250 cf->snap = WTAP_MAX_PACKET_SIZE;
253 nstime_set_zero(&cf->elapsed_time);
254 nstime_set_zero(&first_ts);
255 nstime_set_zero(&prev_ts);
257 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
259 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
261 g_assert(cf->plist_chunk);
263 /* change the time formats now, as we might have a new precision */
264 cf_change_time_formats(cf);
266 fileset_file_opened(fname);
271 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
277 * Reset the state for the currently closed file, but don't do the
278 * UI callbacks; this is for use in "cf_open()", where we don't
279 * want the UI to go from "file open" to "file closed" back to
280 * "file open", we want it to go from "old file open" to "new file
281 * open and being read".
284 cf_reset_state(capture_file *cf)
286 /* Die if we're in the middle of reading a file. */
287 g_assert(cf->state != FILE_READ_IN_PROGRESS);
293 /* We have no file open... */
294 if (cf->filename != NULL) {
295 /* If it's a temporary file, remove it. */
297 eth_unlink(cf->filename);
298 g_free(cf->filename);
301 /* ...which means we have nothing to save. */
302 cf->user_saved = FALSE;
304 if (cf->plist_chunk != NULL) {
305 g_mem_chunk_destroy(cf->plist_chunk);
306 cf->plist_chunk = NULL;
308 if (cf->rfcode != NULL) {
309 dfilter_free(cf->rfcode);
313 cf->plist_end = NULL;
314 cf_unselect_packet(cf); /* nothing to select */
315 cf->first_displayed = NULL;
316 cf->last_displayed = NULL;
318 /* No frame selected, no field in that frame selected. */
319 cf->current_frame = NULL;
320 cf->finfo_selected = NULL;
322 /* Clear the packet list. */
323 packet_list_freeze();
329 nstime_set_zero(&cf->elapsed_time);
331 reset_tap_listeners();
333 /* We have no file open. */
334 cf->state = FILE_CLOSED;
336 fileset_file_closed();
339 /* Reset everything to a pristine state */
341 cf_close(capture_file *cf)
343 /* do GUI things even if file is already closed,
344 * e.g. to cleanup things if a capture couldn't be started */
345 cf_callback_invoke(cf_cb_file_closing, cf);
347 /* close things, if not already closed before */
348 if(cf->state != FILE_CLOSED) {
352 cleanup_dissection();
355 cf_callback_invoke(cf_cb_file_closed, cf);
359 cf_read(capture_file *cf)
363 const gchar *name_ptr;
365 char errmsg_errno[1024+1];
366 gchar err_str[2048+1];
368 progdlg_t *progbar = NULL;
370 gint64 size, file_pos;
373 gchar status_str[100];
374 gint64 progbar_nextstep;
375 gint64 progbar_quantum;
379 reset_tap_listeners();
380 tap_dfilter_dlg_update();
382 cf_callback_invoke(cf_cb_file_read_start, cf);
384 name_ptr = get_basename(cf->filename);
386 /* Find the size of the file. */
387 size = wtap_file_size(cf->wth, NULL);
389 /* Update the progress bar when it gets to this value. */
390 progbar_nextstep = 0;
391 /* When we reach the value that triggers a progress bar update,
392 bump that value by this amount. */
394 progbar_quantum = size/N_PROGBAR_UPDATES;
397 /* Progress so far. */
400 packet_list_freeze();
403 g_get_current_time(&start_time);
405 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
407 /* Create the progress bar if necessary.
408 We check on every iteration of the loop, so that it takes no
409 longer than the standard time to create it (otherwise, for a
410 large file, we might take considerably longer than that standard
411 time in order to get to the next progress bar step). */
412 if (progbar == NULL) {
413 progbar = delayed_create_progress_dlg("Loading", name_ptr,
414 TRUE, &stop_flag, &start_time, progbar_val);
417 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
418 when we update it, we have to run the GTK+ main loop to get it
419 to repaint what's pending, and doing so may involve an "ioctl()"
420 to see if there's any pending input from an X server, and doing
421 that for every packet can be costly, especially on a big file. */
422 if (data_offset >= progbar_nextstep) {
423 file_pos = wtap_read_so_far(cf->wth, NULL);
424 progbar_val = (gfloat) file_pos / (gfloat) size;
425 if (progbar_val > 1.0) {
426 /* The file probably grew while we were reading it.
427 Update file size, and try again. */
428 size = wtap_file_size(cf->wth, NULL);
430 progbar_val = (gfloat) file_pos / (gfloat) size;
431 /* If it's still > 1, either "wtap_file_size()" failed (in which
432 case there's not much we can do about it), or the file
433 *shrank* (in which case there's not much we can do about
434 it); just clip the progress value at 1.0. */
435 if (progbar_val > 1.0)
438 if (progbar != NULL) {
439 g_snprintf(status_str, sizeof(status_str),
440 "%" PRId64 "KB of %" PRId64 "KB",
441 file_pos / 1024, size / 1024);
442 update_progress_dlg(progbar, progbar_val, status_str);
444 progbar_nextstep += progbar_quantum;
449 /* Well, the user decided to abort the read. He/She will be warned and
450 it might be enough for him/her to work with the already loaded
452 This is especially true for very large capture files, where you don't
453 want to wait loading the whole file (which may last minutes or even
454 hours even on fast machines) just to see that it was the wrong file. */
457 read_packet(cf, data_offset);
460 /* We're done reading the file; destroy the progress bar if it was created. */
462 destroy_progress_dlg(progbar);
464 /* We're done reading sequentially through the file. */
465 cf->state = FILE_READ_DONE;
467 /* Close the sequential I/O side, to free up memory it requires. */
468 wtap_sequential_close(cf->wth);
470 /* Allow the protocol dissectors to free up memory that they
471 * don't need after the sequential run-through of the packets. */
472 postseq_cleanup_all_protocols();
474 /* Set the file encapsulation type now; we don't know what it is until
475 we've looked at all the packets, as we don't know until then whether
476 there's more than one type (and thus whether it's
477 WTAP_ENCAP_PER_PACKET). */
478 cf->lnk_t = wtap_file_encap(cf->wth);
480 cf->current_frame = cf->first_displayed;
483 cf_callback_invoke(cf_cb_file_read_finished, cf);
485 /* If we have any displayed packets to select, select the first of those
486 packets by making the first row the selected row. */
487 if (cf->first_displayed != NULL)
488 packet_list_select_row(0);
491 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
492 "%sFile loading was cancelled!%s\n"
494 "The remaining packets in the file were discarded.\n"
496 "As a lot of packets from the original file will be missing,\n"
497 "remember to be careful when saving the current content to a file.\n",
498 simple_dialog_primary_start(), simple_dialog_primary_end());
499 return CF_READ_ERROR;
503 /* Put up a message box noting that the read failed somewhere along
504 the line. Don't throw out the stuff we managed to read, though,
508 case WTAP_ERR_UNSUPPORTED_ENCAP:
509 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
510 "The capture file has a packet with a network type that Ethereal doesn't support.\n(%s)",
513 errmsg = errmsg_errno;
516 case WTAP_ERR_CANT_READ:
517 errmsg = "An attempt to read from the capture file failed for"
518 " some unknown reason.";
521 case WTAP_ERR_SHORT_READ:
522 errmsg = "The capture file appears to have been cut short"
523 " in the middle of a packet.";
526 case WTAP_ERR_BAD_RECORD:
527 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
528 "The capture file appears to be damaged or corrupt.\n(%s)",
531 errmsg = errmsg_errno;
535 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
536 "An error occurred while reading the"
537 " capture file: %s.", wtap_strerror(err));
538 errmsg = errmsg_errno;
541 g_snprintf(err_str, sizeof err_str, errmsg);
542 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
543 return CF_READ_ERROR;
550 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
552 cf_status_t cf_status;
554 cf_status = cf_open(cf, fname, is_tempfile, err);
559 cf_continue_tail(capture_file *cf, int to_read, int *err)
561 long data_offset = 0;
566 packet_list_freeze();
568 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
570 while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
571 if (cf->state == FILE_READ_ABORTED) {
572 /* Well, the user decided to exit Ethereal. Break out of the
573 loop, and let the code below (which is called even if there
574 aren't any packets left to read) exit. */
577 read_packet(cf, data_offset);
581 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
582 cf->count, cf->state, *err);*/
584 /* XXX - this cheats and looks inside the packet list to find the final
586 if (auto_scroll_live && cf->plist_end != NULL)
587 packet_list_moveto_end();
591 if (cf->state == FILE_READ_ABORTED) {
592 /* Well, the user decided to exit Ethereal. Return CF_READ_ABORTED
593 so that our caller can kill off the capture child process;
594 this will cause an EOF on the pipe from the child, so
595 "cf_finish_tail()" will be called, and it will clean up
597 return CF_READ_ABORTED;
598 } else if (*err != 0) {
599 /* We got an error reading the capture file.
600 XXX - pop up a dialog box instead? */
601 g_warning("Error \"%s\" while reading: \"%s\"\n",
602 wtap_strerror(*err), cf->filename);
604 return CF_READ_ERROR;
610 cf_finish_tail(capture_file *cf, int *err)
615 if(cf->wth == NULL) {
617 return CF_READ_ERROR;
620 packet_list_freeze();
622 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
623 if (cf->state == FILE_READ_ABORTED) {
624 /* Well, the user decided to abort the read. Break out of the
625 loop, and let the code below (which is called even if there
626 aren't any packets left to read) exit. */
629 read_packet(cf, data_offset);
634 if (cf->state == FILE_READ_ABORTED) {
635 /* Well, the user decided to abort the read. We're only called
636 when the child capture process closes the pipe to us (meaning
637 it's probably exited), so we can just close the capture
638 file; we return CF_READ_ABORTED so our caller can do whatever
639 is appropriate when that happens. */
641 return CF_READ_ABORTED;
644 if (auto_scroll_live && cf->plist_end != NULL)
645 /* XXX - this cheats and looks inside the packet list to find the final
647 packet_list_moveto_end();
649 /* We're done reading sequentially through the file. */
650 cf->state = FILE_READ_DONE;
652 /* We're done reading sequentially through the file; close the
653 sequential I/O side, to free up memory it requires. */
654 wtap_sequential_close(cf->wth);
656 /* Allow the protocol dissectors to free up memory that they
657 * don't need after the sequential run-through of the packets. */
658 postseq_cleanup_all_protocols();
660 /* Set the file encapsulation type now; we don't know what it is until
661 we've looked at all the packets, as we don't know until then whether
662 there's more than one type (and thus whether it's
663 WTAP_ENCAP_PER_PACKET). */
664 cf->lnk_t = wtap_file_encap(cf->wth);
667 /* We got an error reading the capture file.
668 XXX - pop up a dialog box? */
669 return CF_READ_ERROR;
674 #endif /* HAVE_LIBPCAP */
677 cf_get_display_name(capture_file *cf)
679 const gchar *displayname;
681 /* Return a name to use in displays */
682 if (!cf->is_tempfile) {
683 /* Get the last component of the file name, and use that. */
685 displayname = get_basename(cf->filename);
687 displayname="(No file)";
690 /* The file we read is a temporary file from a live capture;
691 we don't mention its name. */
692 displayname = "(Untitled)";
697 /* XXX - use a macro instead? */
699 cf_get_packet_count(capture_file *cf)
704 /* XXX - use a macro instead? */
706 cf_set_packet_count(capture_file *cf, int packet_count)
708 cf->count = packet_count;
711 /* XXX - use a macro instead? */
713 cf_is_tempfile(capture_file *cf)
715 return cf->is_tempfile;
718 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
720 cf->is_tempfile = is_tempfile;
724 /* XXX - use a macro instead? */
725 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
727 cf->drops_known = drops_known;
730 /* XXX - use a macro instead? */
731 void cf_set_drops(capture_file *cf, guint32 drops)
736 /* XXX - use a macro instead? */
737 gboolean cf_get_drops_known(capture_file *cf)
739 return cf->drops_known;
742 /* XXX - use a macro instead? */
743 guint32 cf_get_drops(capture_file *cf)
748 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
754 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
755 union wtap_pseudo_header *pseudo_header, const guchar *buf,
759 gboolean create_proto_tree = FALSE;
762 /* just add some value here until we know if it is being displayed or not */
763 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
765 /* If we don't have the time stamp of the first packet in the
766 capture, it's because this is the first packet. Save the time
767 stamp of this packet as the time stamp of the first packet. */
768 if (nstime_is_zero(&first_ts)) {
769 first_ts = fdata->abs_ts;
771 /* if this frames is marked as a reference time frame, reset
772 firstsec and firstusec to this frame */
773 if(fdata->flags.ref_time){
774 first_ts = fdata->abs_ts;
777 /* If we don't have the time stamp of the previous displayed packet,
778 it's because this is the first displayed packet. Save the time
779 stamp of this packet as the time stamp of the previous displayed
781 if (nstime_is_zero(&prev_ts)) {
782 prev_ts = fdata->abs_ts;
785 /* Get the time elapsed between the first packet and this packet. */
786 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
788 /* If it's greater than the current elapsed time, set the elapsed time
789 to it (we check for "greater than" so as not to be confused by
790 time moving backwards). */
791 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
792 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
793 cf->elapsed_time = fdata->rel_ts;
796 /* Get the time elapsed between the previous displayed packet and
798 nstime_delta(&fdata->del_ts, &fdata->abs_ts, &prev_ts);
802 we have a display filter and are re-applying it;
804 we have a list of color filters;
806 we have tap listeners;
808 allocate a protocol tree root node, so that we'll construct
809 a protocol tree against which a filter expression can be
811 if ((cf->dfcode != NULL && refilter) || color_filters_used()
812 || num_tap_filters != 0)
813 create_proto_tree = TRUE;
815 /* Dissect the frame. */
816 edt = epan_dissect_new(create_proto_tree, FALSE);
818 if (cf->dfcode != NULL && refilter) {
819 epan_dissect_prime_dfilter(edt, cf->dfcode);
821 if (color_filters_used()) {
822 color_filters_prime_edt(edt);
825 epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
826 tap_push_tapped_queue(edt);
828 /* If we have a display filter, apply it if we're refiltering, otherwise
829 leave the "passed_dfilter" flag alone.
831 If we don't have a display filter, set "passed_dfilter" to 1. */
832 if (cf->dfcode != NULL) {
834 fdata->flags.passed_dfilter = dfilter_apply_edt(cf->dfcode, edt) ? 1 : 0;
837 fdata->flags.passed_dfilter = 1;
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 "cf_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 "cf_select_packet()" can find this frame. See the comment
867 in "cf_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 /* colorize packet: if packet is marked, use preferences,
877 otherwise try to apply color filters */
878 if (fdata->flags.marked) {
879 fdata->color_filter = NULL;
880 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
882 fdata->color_filter = color_filters_colorize_packet(row, edt);
885 /* Set the time of the previous displayed frame to the time of this
887 prev_ts = fdata->abs_ts;
889 cf->displayed_count++;
891 /* This frame didn't pass the display filter, so it's not being added
892 to the clist, and thus has no row. */
895 epan_dissect_free(edt);
900 read_packet(capture_file *cf, long offset)
902 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
903 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
904 const guchar *buf = wtap_buf_ptr(cf->wth);
907 frame_data *plist_end;
910 /* Allocate the next list entry, and add it to the list. */
911 fdata = g_mem_chunk_alloc(cf->plist_chunk);
917 fdata->pkt_len = phdr->len;
918 fdata->cap_len = phdr->caplen;
919 fdata->file_off = offset;
920 fdata->lnk_t = phdr->pkt_encap;
921 fdata->flags.encoding = CHAR_ASCII;
922 fdata->flags.visited = 0;
923 fdata->flags.marked = 0;
924 fdata->flags.ref_time = 0;
925 fdata->color_filter = NULL;
927 fdata->abs_ts = *((nstime_t *) &phdr->ts);
931 edt = epan_dissect_new(TRUE, FALSE);
932 epan_dissect_prime_dfilter(edt, cf->rfcode);
933 epan_dissect_run(edt, pseudo_header, buf, fdata, NULL);
934 passed = dfilter_apply_edt(cf->rfcode, edt);
935 epan_dissect_free(edt);
938 plist_end = cf->plist_end;
939 fdata->prev = plist_end;
940 if (plist_end != NULL)
941 plist_end->next = fdata;
944 cf->plist_end = fdata;
947 cf->f_datalen = offset + phdr->caplen;
948 fdata->num = cf->count;
949 add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE);
951 /* XXX - if we didn't have read filters, or if we could avoid
952 allocating the "frame_data" structure until we knew whether
953 the frame passed the read filter, we could use a G_ALLOC_ONLY
956 ...but, at least in one test I did, where I just made the chunk
957 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
958 seem to save a noticeable amount of time or space. */
959 g_mem_chunk_free(cf->plist_chunk, fdata);
964 cf_merge_files(char **out_filenamep, int in_file_count,
965 char *const *in_filenames, int file_type, gboolean do_append)
967 merge_in_file_t *in_files;
973 int open_err, read_err, write_err, close_err;
977 char errmsg_errno[1024+1];
978 gchar err_str[2048+1];
980 gboolean got_read_error = FALSE, got_write_error = FALSE;
982 progdlg_t *progbar = NULL;
984 gint64 f_len, file_pos;
987 gchar status_str[100];
988 gint64 progbar_nextstep;
989 gint64 progbar_quantum;
991 /* open the input files */
992 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
993 &open_err, &err_info, &err_fileno)) {
995 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1000 if (*out_filenamep != NULL) {
1001 out_filename = *out_filenamep;
1002 out_fd = eth_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1006 out_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
1009 out_filename = g_strdup(tmpname);
1010 *out_filenamep = out_filename;
1014 merge_close_in_files(in_file_count, in_files);
1016 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1020 pdh = wtap_dump_fdopen(out_fd, file_type,
1021 merge_select_frame_type(in_file_count, in_files),
1022 merge_max_snapshot_length(in_file_count, in_files),
1023 FALSE /* compressed */, &open_err);
1026 merge_close_in_files(in_file_count, in_files);
1028 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1033 /* Get the sum of the sizes of all the files. */
1035 for (i = 0; i < in_file_count; i++)
1036 f_len += in_files[i].size;
1038 /* Update the progress bar when it gets to this value. */
1039 progbar_nextstep = 0;
1040 /* When we reach the value that triggers a progress bar update,
1041 bump that value by this amount. */
1042 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1043 /* Progress so far. */
1047 g_get_current_time(&start_time);
1049 /* do the merge (or append) */
1052 wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1055 wth = merge_read_packet(in_file_count, in_files, &read_err,
1059 got_read_error = TRUE;
1063 /* Get the sum of the data offsets in all of the files. */
1065 for (i = 0; i < in_file_count; i++)
1066 data_offset += in_files[i].data_offset;
1068 /* Create the progress bar if necessary.
1069 We check on every iteration of the loop, so that it takes no
1070 longer than the standard time to create it (otherwise, for a
1071 large file, we might take considerably longer than that standard
1072 time in order to get to the next progress bar step). */
1073 if (progbar == NULL) {
1074 progbar = delayed_create_progress_dlg("Merging", "files",
1075 FALSE, &stop_flag, &start_time, progbar_val);
1078 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1079 when we update it, we have to run the GTK+ main loop to get it
1080 to repaint what's pending, and doing so may involve an "ioctl()"
1081 to see if there's any pending input from an X server, and doing
1082 that for every packet can be costly, especially on a big file. */
1083 if (data_offset >= progbar_nextstep) {
1084 /* Get the sum of the seek positions in all of the files. */
1086 for (i = 0; i < in_file_count; i++)
1087 file_pos += wtap_read_so_far(in_files[i].wth, NULL);
1088 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1089 if (progbar_val > 1.0) {
1090 /* Some file probably grew while we were reading it.
1091 That "shouldn't happen", so we'll just clip the progress
1095 if (progbar != NULL) {
1096 g_snprintf(status_str, sizeof(status_str),
1097 "%" PRId64 "KB of %" PRId64 "KB",
1098 file_pos / 1024, f_len / 1024);
1099 update_progress_dlg(progbar, progbar_val, status_str);
1101 progbar_nextstep += progbar_quantum;
1105 /* Well, the user decided to abort the merge. */
1109 if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1110 wtap_buf_ptr(wth), &write_err)) {
1111 got_write_error = TRUE;
1116 /* We're done merging the files; destroy the progress bar if it was created. */
1117 if (progbar != NULL)
1118 destroy_progress_dlg(progbar);
1120 merge_close_in_files(in_file_count, in_files);
1121 if (!got_read_error && !got_write_error) {
1122 if (!wtap_dump_close(pdh, &write_err))
1123 got_write_error = TRUE;
1125 wtap_dump_close(pdh, &close_err);
1127 if (got_read_error) {
1129 * Find the file on which we got the error, and report the error.
1131 for (i = 0; i < in_file_count; i++) {
1132 if (in_files[i].state == GOT_ERROR) {
1133 /* Put up a message box noting that a read failed somewhere along
1137 case WTAP_ERR_UNSUPPORTED_ENCAP:
1138 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1139 "The capture file %%s has a packet with a network type that Ethereal doesn't support.\n(%s)",
1142 errmsg = errmsg_errno;
1145 case WTAP_ERR_CANT_READ:
1146 errmsg = "An attempt to read from the capture file %s failed for"
1147 " some unknown reason.";
1150 case WTAP_ERR_SHORT_READ:
1151 errmsg = "The capture file %s appears to have been cut short"
1152 " in the middle of a packet.";
1155 case WTAP_ERR_BAD_RECORD:
1156 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1157 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1160 errmsg = errmsg_errno;
1164 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1165 "An error occurred while reading the"
1166 " capture file %%s: %s.", wtap_strerror(read_err));
1167 errmsg = errmsg_errno;
1170 g_snprintf(err_str, sizeof err_str, errmsg, in_files[i].filename);
1171 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
1176 if (got_write_error) {
1177 /* Put up an alert box for the write error. */
1178 cf_write_failure_alert_box(out_filename, write_err);
1181 if (got_read_error || got_write_error || stop_flag) {
1182 /* Callers aren't expected to treat an error or an explicit abort
1183 differently - we put up error dialogs ourselves, so they don't
1191 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1194 const char *filter_new = dftext ? dftext : "";
1195 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1197 /* if new filter equals old one, do nothing unless told to do so */
1198 if (!force && strcmp(filter_new, filter_old) == 0) {
1202 if (dftext == NULL) {
1203 /* The new filter is an empty filter (i.e., display all packets). */
1207 * We have a filter; make a copy of it (as we'll be saving it),
1208 * and try to compile it.
1210 dftext = g_strdup(dftext);
1211 if (!dfilter_compile(dftext, &dfcode)) {
1212 /* The attempt failed; report an error. */
1213 gchar *safe_dftext = simple_dialog_format_message(dftext);
1214 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1216 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1219 "The following display filter isn't a valid display filter:\n%s\n"
1220 "See the help for a description of the display filter syntax.",
1221 simple_dialog_primary_start(), safe_dfilter_error_msg,
1222 simple_dialog_primary_end(), safe_dftext);
1223 g_free(safe_dfilter_error_msg);
1224 g_free(safe_dftext);
1230 if (dfcode == NULL) {
1231 /* Yes - free the filter text, and set it to null. */
1237 /* We have a valid filter. Replace the current filter. */
1238 if (cf->dfilter != NULL)
1239 g_free(cf->dfilter);
1240 cf->dfilter = dftext;
1241 if (cf->dfcode != NULL)
1242 dfilter_free(cf->dfcode);
1243 cf->dfcode = dfcode;
1245 /* Now rescan the packet list, applying the new filter, but not
1246 throwing away information constructed on a previous pass. */
1247 if (dftext == NULL) {
1248 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1250 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1256 cf_colorize_packets(capture_file *cf)
1258 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1262 cf_reftime_packets(capture_file *cf)
1264 rescan_packets(cf, "Updating Reftime", "all packets", FALSE, FALSE);
1268 cf_redissect_packets(capture_file *cf)
1270 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1273 /* Rescan the list of packets, reconstructing the CList.
1275 "action" describes why we're doing this; it's used in the progress
1278 "action_item" describes what we're doing; it's used in the progress
1281 "refilter" is TRUE if we need to re-evaluate the filter expression.
1283 "redissect" is TRUE if we need to make the dissectors reconstruct
1284 any state information they have (because a preference that affects
1285 some dissector has changed, meaning some dissector might construct
1286 its state differently from the way it was constructed the last time). */
1288 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1289 gboolean refilter, gboolean redissect)
1292 progdlg_t *progbar = NULL;
1297 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1298 int selected_row, prev_row, preceding_row, following_row;
1299 gboolean selected_frame_seen;
1302 GTimeVal start_time;
1303 gchar status_str[100];
1304 int progbar_nextstep;
1305 int progbar_quantum;
1308 reset_tap_listeners();
1309 /* Which frame, if any, is the currently selected frame?
1310 XXX - should the selected frame or the focus frame be the "current"
1311 frame, that frame being the one from which "Find Frame" searches
1313 selected_frame = cf->current_frame;
1315 /* We don't yet know what row that frame will be on, if any, after we
1316 rebuild the clist, however. */
1320 /* We need to re-initialize all the state information that protocols
1321 keep, because some preference that controls a dissector has changed,
1322 which might cause the state information to be constructed differently
1323 by that dissector. */
1325 /* Initialize all data structures used for dissection. */
1329 /* Freeze the packet list while we redo it, so we don't get any
1330 screen updates while it happens. */
1331 packet_list_freeze();
1334 packet_list_clear();
1336 /* We don't yet know which will be the first and last frames displayed. */
1337 cf->first_displayed = NULL;
1338 cf->last_displayed = NULL;
1340 /* We currently don't display any packets */
1341 cf->displayed_count = 0;
1343 /* Iterate through the list of frames. Call a routine for each frame
1344 to check whether it should be displayed and, if so, add it to
1345 the display list. */
1346 nstime_set_zero(&first_ts);
1347 nstime_set_zero(&prev_ts);
1349 /* Update the progress bar when it gets to this value. */
1350 progbar_nextstep = 0;
1351 /* When we reach the value that triggers a progress bar update,
1352 bump that value by this amount. */
1353 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1354 /* Count of packets at which we've looked. */
1356 /* Progress so far. */
1360 g_get_current_time(&start_time);
1362 row = -1; /* no previous row yet */
1367 preceding_frame = NULL;
1369 following_frame = NULL;
1371 selected_frame_seen = FALSE;
1373 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1374 /* Create the progress bar if necessary.
1375 We check on every iteration of the loop, so that it takes no
1376 longer than the standard time to create it (otherwise, for a
1377 large file, we might take considerably longer than that standard
1378 time in order to get to the next progress bar step). */
1379 if (progbar == NULL)
1380 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1381 &stop_flag, &start_time,
1384 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1385 when we update it, we have to run the GTK+ main loop to get it
1386 to repaint what's pending, and doing so may involve an "ioctl()"
1387 to see if there's any pending input from an X server, and doing
1388 that for every packet can be costly, especially on a big file. */
1389 if (count >= progbar_nextstep) {
1390 /* let's not divide by zero. I should never be started
1391 * with count == 0, so let's assert that
1393 g_assert(cf->count > 0);
1394 progbar_val = (gfloat) count / cf->count;
1396 if (progbar != NULL) {
1397 g_snprintf(status_str, sizeof(status_str),
1398 "%4u of %u frames", count, cf->count);
1399 update_progress_dlg(progbar, progbar_val, status_str);
1402 progbar_nextstep += progbar_quantum;
1406 /* Well, the user decided to abort the filtering. Just stop.
1408 XXX - go back to the previous filter? Users probably just
1409 want not to wait for a filtering operation to finish;
1410 unless we cancel by having no filter, reverting to the
1411 previous filter will probably be even more expensive than
1412 continuing the filtering, as it involves going back to the
1413 beginning and filtering, and even with no filter we currently
1414 have to re-generate the entire clist, which is also expensive.
1416 I'm not sure what Network Monitor does, but it doesn't appear
1417 to give you an unfiltered display if you cancel. */
1424 /* Since all state for the frame was destroyed, mark the frame
1425 * as not visited, free the GSList referring to the state
1426 * data (the per-frame data itself was freed by
1427 * "init_dissection()"), and null out the GSList pointer. */
1428 fdata->flags.visited = 0;
1430 g_slist_free(fdata->pfd);
1435 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1436 cf->pd, fdata->cap_len, &err, &err_info)) {
1437 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1438 cf_read_error_message(err, err_info), cf->filename);
1442 /* If the previous frame is displayed, and we haven't yet seen the
1443 selected frame, remember that frame - it's the closest one we've
1444 yet seen before the selected frame. */
1445 if (prev_row != -1 && !selected_frame_seen) {
1446 preceding_row = prev_row;
1447 preceding_frame = prev_frame;
1449 row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
1452 /* If this frame is displayed, and this is the first frame we've
1453 seen displayed after the selected frame, remember this frame -
1454 it's the closest one we've yet seen at or after the selected
1456 if (row != -1 && selected_frame_seen && following_row == -1) {
1457 following_row = row;
1458 following_frame = fdata;
1460 if (fdata == selected_frame) {
1462 selected_frame_seen = TRUE;
1465 /* Remember this row/frame - it'll be the previous row/frame
1466 on the next pass through the loop. */
1472 /* Clear out what remains of the visited flags and per-frame data
1475 XXX - that may cause various forms of bogosity when dissecting
1476 these frames, as they won't have been seen by this sequential
1477 pass, but the only alternative I see is to keep scanning them
1478 even though the user requested that the scan stop, and that
1479 would leave the user stuck with an Ethereal grinding on
1480 until it finishes. Should we just stick them with that? */
1481 for (; fdata != NULL; fdata = fdata->next) {
1482 fdata->flags.visited = 0;
1484 g_slist_free(fdata->pfd);
1490 /* We're done filtering the packets; destroy the progress bar if it
1492 if (progbar != NULL)
1493 destroy_progress_dlg(progbar);
1495 /* Unfreeze the packet list. */
1498 if (selected_row == -1) {
1499 /* The selected frame didn't pass the filter. */
1500 if (selected_frame == NULL) {
1501 /* That's because there *was* no selected frame. Make the first
1502 displayed frame the current frame. */
1505 /* Find the nearest displayed frame to the selected frame (whether
1506 it's before or after that frame) and make that the current frame.
1507 If the next and previous displayed frames are equidistant from the
1508 selected frame, choose the next one. */
1509 g_assert(following_frame == NULL ||
1510 following_frame->num >= selected_frame->num);
1511 g_assert(preceding_frame == NULL ||
1512 preceding_frame->num <= selected_frame->num);
1513 if (following_frame == NULL) {
1514 /* No frame after the selected frame passed the filter, so we
1515 have to select the last displayed frame before the selected
1517 selected_row = preceding_row;
1518 } else if (preceding_frame == NULL) {
1519 /* No frame before the selected frame passed the filter, so we
1520 have to select the first displayed frame after the selected
1522 selected_row = following_row;
1524 /* Choose the closer of the last displayed frame before the
1525 selected frame and the first displayed frame after the
1526 selected frame; in case of a tie, choose the first displayed
1527 frame after the selected frame. */
1528 if (following_frame->num - selected_frame->num <=
1529 selected_frame->num - preceding_frame->num) {
1530 selected_row = following_row;
1532 /* The previous frame is closer to the selected frame than the
1534 selected_row = preceding_row;
1540 if (selected_row == -1) {
1541 /* There are no frames displayed at all. */
1542 cf_unselect_packet(cf);
1544 /* Either the frame that was selected passed the filter, or we've
1545 found the nearest displayed frame to that frame. Select it, make
1546 it the focus row, and make it visible. */
1547 packet_list_set_selected_row(selected_row);
1558 process_specified_packets(capture_file *cf, packet_range_t *range,
1559 const char *string1, const char *string2, gboolean terminate_is_stop,
1560 gboolean (*callback)(capture_file *, frame_data *,
1561 union wtap_pseudo_header *, const guint8 *, void *),
1562 void *callback_args)
1567 union wtap_pseudo_header pseudo_header;
1568 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
1569 psp_return_t ret = PSP_FINISHED;
1571 progdlg_t *progbar = NULL;
1574 gboolean progbar_stop_flag;
1575 GTimeVal progbar_start_time;
1576 gchar progbar_status_str[100];
1577 int progbar_nextstep;
1578 int progbar_quantum;
1579 range_process_e process_this;
1581 /* Update the progress bar when it gets to this value. */
1582 progbar_nextstep = 0;
1583 /* When we reach the value that triggers a progress bar update,
1584 bump that value by this amount. */
1585 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1586 /* Count of packets at which we've looked. */
1588 /* Progress so far. */
1591 progbar_stop_flag = FALSE;
1592 g_get_current_time(&progbar_start_time);
1594 packet_range_process_init(range);
1596 /* Iterate through the list of packets, printing the packets that
1597 were selected by the current display filter. */
1598 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1599 /* Create the progress bar if necessary.
1600 We check on every iteration of the loop, so that it takes no
1601 longer than the standard time to create it (otherwise, for a
1602 large file, we might take considerably longer than that standard
1603 time in order to get to the next progress bar step). */
1604 if (progbar == NULL)
1605 progbar = delayed_create_progress_dlg(string1, string2,
1608 &progbar_start_time,
1611 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1612 when we update it, we have to run the GTK+ main loop to get it
1613 to repaint what's pending, and doing so may involve an "ioctl()"
1614 to see if there's any pending input from an X server, and doing
1615 that for every packet can be costly, especially on a big file. */
1616 if (progbar_count >= progbar_nextstep) {
1617 /* let's not divide by zero. I should never be started
1618 * with count == 0, so let's assert that
1620 g_assert(cf->count > 0);
1621 progbar_val = (gfloat) progbar_count / cf->count;
1623 if (progbar != NULL) {
1624 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
1625 "%4u of %u packets", progbar_count, cf->count);
1626 update_progress_dlg(progbar, progbar_val, progbar_status_str);
1629 progbar_nextstep += progbar_quantum;
1632 if (progbar_stop_flag) {
1633 /* Well, the user decided to abort the operation. Just stop,
1634 and arrange to return PSP_STOPPED to our caller, so they know
1635 it was stopped explicitly. */
1642 /* do we have to process this packet? */
1643 process_this = packet_range_process_packet(range, fdata);
1644 if (process_this == range_process_next) {
1645 /* this packet uninteresting, continue with next one */
1647 } else if (process_this == range_processing_finished) {
1648 /* all interesting packets processed, stop the loop */
1652 /* Get the packet */
1653 if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1654 pd, fdata->cap_len, &err, &err_info)) {
1655 /* Attempt to get the packet failed. */
1656 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1657 cf_read_error_message(err, err_info), cf->filename);
1661 /* Process the packet */
1662 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
1663 /* Callback failed. We assume it reported the error appropriately. */
1669 /* We're done printing the packets; destroy the progress bar if
1671 if (progbar != NULL)
1672 destroy_progress_dlg(progbar);
1678 retap_packet(capture_file *cf _U_, frame_data *fdata,
1679 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1682 column_info *cinfo = argsp;
1683 epan_dissect_t *edt;
1685 /* If we have tap listeners, allocate a protocol tree root node, so that
1686 we'll construct a protocol tree against which a filter expression can
1688 edt = epan_dissect_new(num_tap_filters != 0, FALSE);
1689 tap_queue_init(edt);
1690 epan_dissect_run(edt, pseudo_header, pd, fdata, cinfo);
1691 tap_push_tapped_queue(edt);
1692 epan_dissect_free(edt);
1698 cf_retap_packets(capture_file *cf, gboolean do_columns)
1700 packet_range_t range;
1702 /* Reset the tap listeners. */
1703 reset_tap_listeners();
1705 /* Iterate through the list of packets, dissecting all packets and
1706 re-running the taps. */
1707 packet_range_init(&range);
1708 packet_range_process_init(&range);
1709 switch (process_specified_packets(cf, &range, "Refiltering statistics on",
1710 "all packets", TRUE, retap_packet,
1711 do_columns ? &cf->cinfo : NULL)) {
1713 /* Completed successfully. */
1717 /* Well, the user decided to abort the refiltering.
1718 Return CF_READ_ABORTED so our caller knows they did that. */
1719 return CF_READ_ABORTED;
1722 /* Error while retapping. */
1723 return CF_READ_ERROR;
1726 g_assert_not_reached();
1731 print_args_t *print_args;
1732 gboolean print_header_line;
1733 char *header_line_buf;
1734 int header_line_buf_len;
1735 gboolean print_formfeed;
1736 gboolean print_separator;
1740 } print_callback_args_t;
1743 print_packet(capture_file *cf, frame_data *fdata,
1744 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1747 print_callback_args_t *args = argsp;
1748 epan_dissect_t *edt;
1754 gboolean proto_tree_needed;
1755 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
1756 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
1758 /* Create the protocol tree, and make it visible, if we're printing
1759 the dissection or the hex data.
1760 XXX - do we need it if we're just printing the hex data? */
1762 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex;
1763 edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
1765 /* Fill in the column information if we're printing the summary
1767 if (args->print_args->print_summary) {
1768 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
1769 epan_dissect_fill_in_columns(edt);
1771 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1773 if (args->print_formfeed) {
1774 if (!new_page(args->print_args->stream))
1777 if (args->print_separator) {
1778 if (!print_line(args->print_args->stream, 0, ""))
1784 * We generate bookmarks, if the output format supports them.
1785 * The name is "__frameN__".
1787 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
1789 if (args->print_args->print_summary) {
1790 if (args->print_header_line) {
1791 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
1793 args->print_header_line = FALSE; /* we might not need to print any more */
1795 cp = &args->line_buf[0];
1797 for (i = 0; i < cf->cinfo.num_cols; i++) {
1798 /* Find the length of the string for this column. */
1799 column_len = strlen(cf->cinfo.col_data[i]);
1800 if (args->col_widths[i] > column_len)
1801 column_len = args->col_widths[i];
1803 /* Make sure there's room in the line buffer for the column; if not,
1804 double its length. */
1805 line_len += column_len + 1; /* "+1" for space */
1806 if (line_len > args->line_buf_len) {
1807 cp_off = cp - args->line_buf;
1808 args->line_buf_len = 2 * line_len;
1809 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
1810 cp = args->line_buf + cp_off;
1813 /* Right-justify the packet number column. */
1814 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1815 sprintf(cp, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
1817 sprintf(cp, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
1819 if (i != cf->cinfo.num_cols - 1)
1825 * Generate a bookmark, using the summary line as the title.
1827 if (!print_bookmark(args->print_args->stream, bookmark_name,
1831 if (!print_line(args->print_args->stream, 0, args->line_buf))
1835 * Generate a bookmark, using "Frame N" as the title, as we're not
1836 * printing the summary line.
1838 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
1839 if (!print_bookmark(args->print_args->stream, bookmark_name,
1842 } /* if (print_summary) */
1844 if (args->print_args->print_dissections != print_dissections_none) {
1845 if (args->print_args->print_summary) {
1846 /* Separate the summary line from the tree with a blank line. */
1847 if (!print_line(args->print_args->stream, 0, ""))
1851 /* Print the information in that tree. */
1852 if (!proto_tree_print(args->print_args, edt, args->print_args->stream))
1855 /* Print a blank line if we print anything after this (aka more than one packet). */
1856 args->print_separator = TRUE;
1858 /* Print a header line if we print any more packet summaries */
1859 args->print_header_line = TRUE;
1862 if (args->print_args->print_hex) {
1863 /* Print the full packet data as hex. */
1864 if (!print_hex_data(args->print_args->stream, edt))
1867 /* Print a blank line if we print anything after this (aka more than one packet). */
1868 args->print_separator = TRUE;
1870 /* Print a header line if we print any more packet summaries */
1871 args->print_header_line = TRUE;
1872 } /* if (args->print_args->print_dissections != print_dissections_none) */
1874 epan_dissect_free(edt);
1876 /* do we want to have a formfeed between each packet from now on? */
1877 if(args->print_args->print_formfeed) {
1878 args->print_formfeed = TRUE;
1884 epan_dissect_free(edt);
1889 cf_print_packets(capture_file *cf, print_args_t *print_args)
1892 print_callback_args_t callback_args;
1900 callback_args.print_args = print_args;
1901 callback_args.print_header_line = TRUE;
1902 callback_args.header_line_buf = NULL;
1903 callback_args.header_line_buf_len = 256;
1904 callback_args.print_formfeed = FALSE;
1905 callback_args.print_separator = FALSE;
1906 callback_args.line_buf = NULL;
1907 callback_args.line_buf_len = 256;
1908 callback_args.col_widths = NULL;
1910 if (!print_preamble(print_args->stream, cf->filename)) {
1911 destroy_print_stream(print_args->stream);
1912 return CF_PRINT_WRITE_ERROR;
1915 if (print_args->print_summary) {
1916 /* We're printing packet summaries. Allocate the header line buffer
1917 and get the column widths. */
1918 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
1920 /* Find the widths for each of the columns - maximum of the
1921 width of the title and the width of the data - and construct
1922 a buffer with a line containing the column titles. */
1923 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1924 cp = &callback_args.header_line_buf[0];
1926 for (i = 0; i < cf->cinfo.num_cols; i++) {
1927 /* Don't pad the last column. */
1928 if (i == cf->cinfo.num_cols - 1)
1929 callback_args.col_widths[i] = 0;
1931 callback_args.col_widths[i] = strlen(cf->cinfo.col_title[i]);
1932 data_width = get_column_char_width(get_column_format(i));
1933 if (data_width > callback_args.col_widths[i])
1934 callback_args.col_widths[i] = data_width;
1937 /* Find the length of the string for this column. */
1938 column_len = strlen(cf->cinfo.col_title[i]);
1939 if (callback_args.col_widths[i] > column_len)
1940 column_len = callback_args.col_widths[i];
1942 /* Make sure there's room in the line buffer for the column; if not,
1943 double its length. */
1944 line_len += column_len + 1; /* "+1" for space */
1945 if (line_len > callback_args.header_line_buf_len) {
1946 cp_off = cp - callback_args.header_line_buf;
1947 callback_args.header_line_buf_len = 2 * line_len;
1948 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
1949 callback_args.header_line_buf_len + 1);
1950 cp = callback_args.header_line_buf + cp_off;
1953 /* Right-justify the packet number column. */
1954 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1955 sprintf(cp, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1957 sprintf(cp, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1959 if (i != cf->cinfo.num_cols - 1)
1964 /* Now start out the main line buffer with the same length as the
1965 header line buffer. */
1966 callback_args.line_buf_len = callback_args.header_line_buf_len;
1967 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
1968 } /* if (print_summary) */
1970 /* Iterate through the list of packets, printing the packets we were
1972 ret = process_specified_packets(cf, &print_args->range, "Printing",
1973 "selected packets", TRUE, print_packet,
1976 if (callback_args.header_line_buf != NULL)
1977 g_free(callback_args.header_line_buf);
1978 if (callback_args.line_buf != NULL)
1979 g_free(callback_args.line_buf);
1980 if (callback_args.col_widths != NULL)
1981 g_free(callback_args.col_widths);
1986 /* Completed successfully. */
1990 /* Well, the user decided to abort the printing.
1992 XXX - note that what got generated before they did that
1993 will get printed if we're piping to a print program; we'd
1994 have to write to a file and then hand that to the print
1995 program to make it actually not print anything. */
1999 /* Error while printing.
2001 XXX - note that what got generated before they did that
2002 will get printed if we're piping to a print program; we'd
2003 have to write to a file and then hand that to the print
2004 program to make it actually not print anything. */
2005 destroy_print_stream(print_args->stream);
2006 return CF_PRINT_WRITE_ERROR;
2009 if (!print_finale(print_args->stream)) {
2010 destroy_print_stream(print_args->stream);
2011 return CF_PRINT_WRITE_ERROR;
2014 if (!destroy_print_stream(print_args->stream))
2015 return CF_PRINT_WRITE_ERROR;
2021 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2022 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2026 epan_dissect_t *edt;
2028 /* Create the protocol tree, but don't fill in the column information. */
2029 edt = epan_dissect_new(TRUE, TRUE);
2030 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
2032 /* Write out the information in that tree. */
2033 proto_tree_write_pdml(edt, fh);
2035 epan_dissect_free(edt);
2041 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2046 fh = eth_fopen(print_args->file, "w");
2048 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2050 write_pdml_preamble(fh);
2053 return CF_PRINT_WRITE_ERROR;
2056 /* Iterate through the list of packets, printing the packets we were
2058 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2059 "selected packets", TRUE,
2060 write_pdml_packet, fh);
2065 /* Completed successfully. */
2069 /* Well, the user decided to abort the printing. */
2073 /* Error while printing. */
2075 return CF_PRINT_WRITE_ERROR;
2078 write_pdml_finale(fh);
2081 return CF_PRINT_WRITE_ERROR;
2084 /* XXX - check for an error */
2091 write_psml_packet(capture_file *cf, frame_data *fdata,
2092 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2096 epan_dissect_t *edt;
2098 /* Fill in the column information, but don't create the protocol tree. */
2099 edt = epan_dissect_new(FALSE, FALSE);
2100 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2101 epan_dissect_fill_in_columns(edt);
2103 /* Write out the information in that tree. */
2104 proto_tree_write_psml(edt, fh);
2106 epan_dissect_free(edt);
2112 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2117 fh = eth_fopen(print_args->file, "w");
2119 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2121 write_psml_preamble(fh);
2124 return CF_PRINT_WRITE_ERROR;
2127 /* Iterate through the list of packets, printing the packets we were
2129 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2130 "selected packets", TRUE,
2131 write_psml_packet, fh);
2136 /* Completed successfully. */
2140 /* Well, the user decided to abort the printing. */
2144 /* Error while printing. */
2146 return CF_PRINT_WRITE_ERROR;
2149 write_psml_finale(fh);
2152 return CF_PRINT_WRITE_ERROR;
2155 /* XXX - check for an error */
2162 write_csv_packet(capture_file *cf, frame_data *fdata,
2163 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2167 epan_dissect_t *edt;
2169 /* Fill in the column information, but don't create the protocol tree. */
2170 edt = epan_dissect_new(FALSE, FALSE);
2171 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2172 epan_dissect_fill_in_columns(edt);
2174 /* Write out the information in that tree. */
2175 proto_tree_write_csv(edt, fh);
2177 epan_dissect_free(edt);
2183 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2188 fh = eth_fopen(print_args->file, "w");
2190 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2192 write_csv_preamble(fh);
2195 return CF_PRINT_WRITE_ERROR;
2198 /* Iterate through the list of packets, printing the packets we were
2200 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2201 "selected packets", TRUE,
2202 write_csv_packet, fh);
2207 /* Completed successfully. */
2211 /* Well, the user decided to abort the printing. */
2215 /* Error while printing. */
2217 return CF_PRINT_WRITE_ERROR;
2220 write_csv_finale(fh);
2223 return CF_PRINT_WRITE_ERROR;
2226 /* XXX - check for an error */
2232 /* Scan through the packet list and change all columns that use the
2233 "command-line-specified" time stamp format to use the current
2234 value of that format. */
2236 cf_change_time_formats(capture_file *cf)
2239 progdlg_t *progbar = NULL;
2245 GTimeVal start_time;
2246 gchar status_str[100];
2247 int progbar_nextstep;
2248 int progbar_quantum;
2250 gboolean sorted_by_frame_column;
2253 /* adjust timestamp precision if auto is selected */
2254 cf_timestamp_auto_precision(cf);
2256 /* Are there any columns with time stamps in the "command-line-specified"
2259 XXX - we have to force the "column is writable" flag on, as it
2260 might be off from the last frame that was dissected. */
2261 col_set_writable(&cf->cinfo, TRUE);
2262 if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
2263 /* No, there aren't any columns in that format, so we have no work
2267 first = cf->cinfo.col_first[COL_CLS_TIME];
2268 g_assert(first >= 0);
2269 last = cf->cinfo.col_last[COL_CLS_TIME];
2271 /* Freeze the packet list while we redo it, so we don't get any
2272 screen updates while it happens. */
2273 packet_list_freeze();
2275 /* Update the progress bar when it gets to this value. */
2276 progbar_nextstep = 0;
2277 /* When we reach the value that triggers a progress bar update,
2278 bump that value by this amount. */
2279 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2280 /* Count of packets at which we've looked. */
2282 /* Progress so far. */
2285 /* If the rows are currently sorted by the frame column then we know
2286 * the row number of each packet: it's the row number of the previously
2287 * displayed packet + 1.
2289 * Otherwise, if the display is sorted by a different column then we have
2290 * to use the O(N) packet_list_find_row_from_data() (thus making the job
2291 * of changing the time display format O(N**2)).
2293 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
2294 * the row number and walks that many elements down the clist to find
2295 * the appropriate element.)
2297 sorted_by_frame_column = FALSE;
2298 for (i = 0; i < cf->cinfo.num_cols; i++) {
2299 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2301 sorted_by_frame_column = (i == packet_list_get_sort_column());
2307 g_get_current_time(&start_time);
2309 /* Iterate through the list of packets, checking whether the packet
2310 is in a row of the summary list and, if so, whether there are
2311 any columns that show the time in the "command-line-specified"
2312 format and, if so, update that row. */
2313 for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
2314 /* Create the progress bar if necessary.
2315 We check on every iteration of the loop, so that it takes no
2316 longer than the standard time to create it (otherwise, for a
2317 large file, we might take considerably longer than that standard
2318 time in order to get to the next progress bar step). */
2319 if (progbar == NULL)
2320 progbar = delayed_create_progress_dlg("Changing", "time display",
2321 TRUE, &stop_flag, &start_time, progbar_val);
2323 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2324 when we update it, we have to run the GTK+ main loop to get it
2325 to repaint what's pending, and doing so may involve an "ioctl()"
2326 to see if there's any pending input from an X server, and doing
2327 that for every packet can be costly, especially on a big file. */
2328 if (count >= progbar_nextstep) {
2329 /* let's not divide by zero. I should never be started
2330 * with count == 0, so let's assert that
2332 g_assert(cf->count > 0);
2334 progbar_val = (gfloat) count / cf->count;
2336 if (progbar != NULL) {
2337 g_snprintf(status_str, sizeof(status_str),
2338 "%4u of %u packets", count, cf->count);
2339 update_progress_dlg(progbar, progbar_val, status_str);
2342 progbar_nextstep += progbar_quantum;
2346 /* Well, the user decided to abort the redisplay. Just stop.
2348 XXX - this leaves the time field in the old format in
2349 frames we haven't yet processed. So it goes; should we
2350 simply not offer them the option of stopping? */
2356 /* Find what row this packet is in. */
2357 if (!sorted_by_frame_column) {
2358 /* This function is O(N), so we try to avoid using it... */
2359 row = packet_list_find_row_from_data(fdata);
2361 /* ...which we do by maintaining a count of packets that are
2362 being displayed (i.e., that have passed the display filter),
2363 and using the current value of that count as the row number
2364 (which is why we can only do it when the display is sorted
2365 by the frame number). */
2366 if (fdata->flags.passed_dfilter)
2373 /* This packet is in the summary list, on row "row". */
2375 for (i = first; i <= last; i++) {
2376 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2377 /* This is one of the columns that shows the time in
2378 "command-line-specified" format; update it. */
2379 cf->cinfo.col_buf[i][0] = '\0';
2380 col_set_cls_time(fdata, &cf->cinfo, i);
2381 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
2387 /* We're done redisplaying the packets; destroy the progress bar if it
2389 if (progbar != NULL)
2390 destroy_progress_dlg(progbar);
2392 /* Set the column widths of those columns that show the time in
2393 "command-line-specified" format. */
2394 for (i = first; i <= last; i++) {
2395 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2396 packet_list_set_cls_time_width(i);
2400 /* Unfreeze the packet list. */
2408 gboolean frame_matched;
2412 cf_find_packet_protocol_tree(capture_file *cf, const char *string)
2416 mdata.string = string;
2417 mdata.string_len = strlen(string);
2418 return find_packet(cf, match_protocol_tree, &mdata);
2422 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2424 match_data *mdata = criterion;
2425 epan_dissect_t *edt;
2427 /* Construct the protocol tree, including the displayed text */
2428 edt = epan_dissect_new(TRUE, TRUE);
2429 /* We don't need the column information */
2430 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2432 /* Iterate through all the nodes, seeing if they have text that matches. */
2434 mdata->frame_matched = FALSE;
2435 proto_tree_children_foreach(edt->tree, match_subtree_text, mdata);
2436 epan_dissect_free(edt);
2437 return mdata->frame_matched;
2441 match_subtree_text(proto_node *node, gpointer data)
2443 match_data *mdata = (match_data*) data;
2444 const gchar *string = mdata->string;
2445 size_t string_len = mdata->string_len;
2446 capture_file *cf = mdata->cf;
2447 field_info *fi = PITEM_FINFO(node);
2448 gchar label_str[ITEM_LABEL_LENGTH];
2455 if (mdata->frame_matched) {
2456 /* We already had a match; don't bother doing any more work. */
2460 /* Don't match invisible entries. */
2461 if (PROTO_ITEM_IS_HIDDEN(node))
2464 /* was a free format label produced? */
2466 label_ptr = fi->rep->representation;
2468 /* no, make a generic label */
2469 label_ptr = label_str;
2470 proto_item_fill_label(fi, label_str);
2473 /* Does that label match? */
2474 label_len = strlen(label_ptr);
2475 for (i = 0; i < label_len; i++) {
2476 c_char = label_ptr[i];
2478 c_char = toupper(c_char);
2479 if (c_char == string[c_match]) {
2481 if (c_match == string_len) {
2482 /* No need to look further; we have a match */
2483 mdata->frame_matched = TRUE;
2490 /* Recurse into the subtree, if it exists */
2491 if (node->first_child != NULL)
2492 proto_tree_children_foreach(node, match_subtree_text, mdata);
2496 cf_find_packet_summary_line(capture_file *cf, const char *string)
2500 mdata.string = string;
2501 mdata.string_len = strlen(string);
2502 return find_packet(cf, match_summary_line, &mdata);
2506 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2508 match_data *mdata = criterion;
2509 const gchar *string = mdata->string;
2510 size_t string_len = mdata->string_len;
2511 epan_dissect_t *edt;
2512 const char *info_column;
2513 size_t info_column_len;
2514 gboolean frame_matched = FALSE;
2520 /* Don't bother constructing the protocol tree */
2521 edt = epan_dissect_new(FALSE, FALSE);
2522 /* Get the column information */
2523 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2525 /* Find the Info column */
2526 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2527 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2528 /* Found it. See if we match. */
2529 info_column = edt->pi.cinfo->col_data[colx];
2530 info_column_len = strlen(info_column);
2531 for (i = 0; i < info_column_len; i++) {
2532 c_char = info_column[i];
2534 c_char = toupper(c_char);
2535 if (c_char == string[c_match]) {
2537 if (c_match == string_len) {
2538 frame_matched = TRUE;
2547 epan_dissect_free(edt);
2548 return frame_matched;
2554 } cbs_t; /* "Counted byte string" */
2557 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
2562 info.data_len = string_size;
2564 /* String or hex search? */
2566 /* String search - what type of string? */
2567 switch (cf->scs_type) {
2569 case SCS_ASCII_AND_UNICODE:
2570 return find_packet(cf, match_ascii_and_unicode, &info);
2573 return find_packet(cf, match_ascii, &info);
2576 return find_packet(cf, match_unicode, &info);
2579 g_assert_not_reached();
2583 return find_packet(cf, match_binary, &info);
2587 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2589 cbs_t *info = criterion;
2590 const char *ascii_text = info->data;
2591 size_t textlen = info->data_len;
2592 gboolean frame_matched;
2598 frame_matched = FALSE;
2599 buf_len = fdata->pkt_len;
2600 for (i = 0; i < buf_len; i++) {
2603 c_char = toupper(c_char);
2605 if (c_char == ascii_text[c_match]) {
2607 if (c_match == textlen) {
2608 frame_matched = TRUE;
2615 return frame_matched;
2619 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2621 cbs_t *info = criterion;
2622 const char *ascii_text = info->data;
2623 size_t textlen = info->data_len;
2624 gboolean frame_matched;
2630 frame_matched = FALSE;
2631 buf_len = fdata->pkt_len;
2632 for (i = 0; i < buf_len; i++) {
2635 c_char = toupper(c_char);
2636 if (c_char == ascii_text[c_match]) {
2638 if (c_match == textlen) {
2639 frame_matched = TRUE;
2645 return frame_matched;
2649 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2651 cbs_t *info = criterion;
2652 const char *ascii_text = info->data;
2653 size_t textlen = info->data_len;
2654 gboolean frame_matched;
2660 frame_matched = FALSE;
2661 buf_len = fdata->pkt_len;
2662 for (i = 0; i < buf_len; i++) {
2665 c_char = toupper(c_char);
2666 if (c_char == ascii_text[c_match]) {
2669 if (c_match == textlen) {
2670 frame_matched = TRUE;
2676 return frame_matched;
2680 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
2682 cbs_t *info = criterion;
2683 const guint8 *binary_data = info->data;
2684 size_t datalen = info->data_len;
2685 gboolean frame_matched;
2690 frame_matched = FALSE;
2691 buf_len = fdata->pkt_len;
2692 for (i = 0; i < buf_len; i++) {
2693 if (cf->pd[i] == binary_data[c_match]) {
2695 if (c_match == datalen) {
2696 frame_matched = TRUE;
2702 return frame_matched;
2706 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
2708 return find_packet(cf, match_dfilter, sfcode);
2712 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
2714 dfilter_t *sfcode = criterion;
2715 epan_dissect_t *edt;
2716 gboolean frame_matched;
2718 edt = epan_dissect_new(TRUE, FALSE);
2719 epan_dissect_prime_dfilter(edt, sfcode);
2720 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2721 frame_matched = dfilter_apply_edt(sfcode, edt);
2722 epan_dissect_free(edt);
2723 return frame_matched;
2727 find_packet(capture_file *cf,
2728 gboolean (*match_function)(capture_file *, frame_data *, void *),
2731 frame_data *start_fd;
2733 frame_data *new_fd = NULL;
2734 progdlg_t *progbar = NULL;
2741 GTimeVal start_time;
2742 gchar status_str[100];
2743 int progbar_nextstep;
2744 int progbar_quantum;
2747 start_fd = cf->current_frame;
2748 if (start_fd != NULL) {
2749 /* Iterate through the list of packets, starting at the packet we've
2750 picked, calling a routine to run the filter on the packet, see if
2751 it matches, and stop if so. */
2755 /* Update the progress bar when it gets to this value. */
2756 progbar_nextstep = 0;
2757 /* When we reach the value that triggers a progress bar update,
2758 bump that value by this amount. */
2759 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2760 /* Progress so far. */
2764 g_get_current_time(&start_time);
2767 title = cf->sfilter?cf->sfilter:"";
2769 /* Create the progress bar if necessary.
2770 We check on every iteration of the loop, so that it takes no
2771 longer than the standard time to create it (otherwise, for a
2772 large file, we might take considerably longer than that standard
2773 time in order to get to the next progress bar step). */
2774 if (progbar == NULL)
2775 progbar = delayed_create_progress_dlg("Searching", title,
2776 FALSE, &stop_flag, &start_time, progbar_val);
2778 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2779 when we update it, we have to run the GTK+ main loop to get it
2780 to repaint what's pending, and doing so may involve an "ioctl()"
2781 to see if there's any pending input from an X server, and doing
2782 that for every packet can be costly, especially on a big file. */
2783 if (count >= progbar_nextstep) {
2784 /* let's not divide by zero. I should never be started
2785 * with count == 0, so let's assert that
2787 g_assert(cf->count > 0);
2789 progbar_val = (gfloat) count / cf->count;
2791 if (progbar != NULL) {
2792 g_snprintf(status_str, sizeof(status_str),
2793 "%4u of %u packets", count, cf->count);
2794 update_progress_dlg(progbar, progbar_val, status_str);
2797 progbar_nextstep += progbar_quantum;
2801 /* Well, the user decided to abort the search. Go back to the
2802 frame where we started. */
2807 /* Go past the current frame. */
2808 if (cf->sbackward) {
2809 /* Go on to the previous frame. */
2810 fdata = fdata->prev;
2811 if (fdata == NULL) {
2813 * XXX - other apps have a bit more of a detailed message
2814 * for this, and instead of offering "OK" and "Cancel",
2815 * they offer things such as "Continue" and "Cancel";
2816 * we need an API for popping up alert boxes with
2817 * {Verb} and "Cancel".
2820 if (prefs.gui_find_wrap)
2822 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2823 "%sBeginning of capture exceeded!%s\n\n"
2824 "Search is continued from the end of the capture.",
2825 simple_dialog_primary_start(), simple_dialog_primary_end());
2826 fdata = cf->plist_end; /* wrap around */
2830 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2831 "%sBeginning of capture exceeded!%s\n\n"
2832 "Try searching forwards.",
2833 simple_dialog_primary_start(), simple_dialog_primary_end());
2834 fdata = start_fd; /* stay on previous packet */
2838 /* Go on to the next frame. */
2839 fdata = fdata->next;
2840 if (fdata == NULL) {
2841 if (prefs.gui_find_wrap)
2843 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2844 "%sEnd of capture exceeded!%s\n\n"
2845 "Search is continued from the start of the capture.",
2846 simple_dialog_primary_start(), simple_dialog_primary_end());
2847 fdata = cf->plist; /* wrap around */
2851 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2852 "%sEnd of capture exceeded!%s\n\n"
2853 "Try searching backwards.",
2854 simple_dialog_primary_start(), simple_dialog_primary_end());
2855 fdata = start_fd; /* stay on previous packet */
2862 /* Is this packet in the display? */
2863 if (fdata->flags.passed_dfilter) {
2864 /* Yes. Load its data. */
2865 if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
2866 cf->pd, fdata->cap_len, &err, &err_info)) {
2867 /* Read error. Report the error, and go back to the frame
2868 where we started. */
2869 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2870 cf_read_error_message(err, err_info), cf->filename);
2875 /* Does it match the search criterion? */
2876 if ((*match_function)(cf, fdata, criterion)) {
2878 break; /* found it! */
2882 if (fdata == start_fd) {
2883 /* We're back to the frame we were on originally, and that frame
2884 doesn't match the search filter. The search failed. */
2889 /* We're done scanning the packets; destroy the progress bar if it
2891 if (progbar != NULL)
2892 destroy_progress_dlg(progbar);
2895 if (new_fd != NULL) {
2896 /* We found a frame. Find what row it's in. */
2897 row = packet_list_find_row_from_data(new_fd);
2898 g_assert(row != -1);
2900 /* Select that row, make it the focus row, and make it visible. */
2901 packet_list_set_selected_row(row);
2902 return TRUE; /* success */
2904 return FALSE; /* failure */
2908 cf_goto_frame(capture_file *cf, guint fnumber)
2913 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
2916 if (fdata == NULL) {
2917 /* we didn't find a packet with that packet number */
2918 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2919 "There is no packet with the packet number %u.", fnumber);
2920 return FALSE; /* we failed to go to that packet */
2922 if (!fdata->flags.passed_dfilter) {
2923 /* that packet currently isn't displayed */
2924 /* XXX - add it to the set of displayed packets? */
2925 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2926 "The packet number %u isn't currently being displayed.", fnumber);
2927 return FALSE; /* we failed to go to that packet */
2930 /* We found that packet, and it's currently being displayed.
2931 Find what row it's in. */
2932 row = packet_list_find_row_from_data(fdata);
2933 g_assert(row != -1);
2935 /* Select that row, make it the focus row, and make it visible. */
2936 packet_list_set_selected_row(row);
2937 return TRUE; /* we got to that packet */
2941 cf_goto_top_frame(capture_file *cf)
2945 frame_data *lowest_fdata = NULL;
2947 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2948 if (fdata->flags.passed_dfilter) {
2949 lowest_fdata = fdata;
2954 if (lowest_fdata == NULL) {
2958 /* We found that packet, and it's currently being displayed.
2959 Find what row it's in. */
2960 row = packet_list_find_row_from_data(lowest_fdata);
2961 g_assert(row != -1);
2963 /* Select that row, make it the focus row, and make it visible. */
2964 packet_list_set_selected_row(row);
2965 return TRUE; /* we got to that packet */
2969 cf_goto_bottom_frame(capture_file *cf)
2973 frame_data *highest_fdata = NULL;
2975 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2976 if (fdata->flags.passed_dfilter) {
2977 highest_fdata = fdata;
2981 if (highest_fdata == NULL) {
2985 /* We found that packet, and it's currently being displayed.
2986 Find what row it's in. */
2987 row = packet_list_find_row_from_data(highest_fdata);
2988 g_assert(row != -1);
2990 /* Select that row, make it the focus row, and make it visible. */
2991 packet_list_set_selected_row(row);
2992 return TRUE; /* we got to that packet */
2996 * Go to frame specified by currently selected protocol tree item.
2999 cf_goto_framenum(capture_file *cf)
3001 header_field_info *hfinfo;
3004 if (cf->finfo_selected) {
3005 hfinfo = cf->finfo_selected->hfinfo;
3007 if (hfinfo->type == FT_FRAMENUM) {
3008 framenum = fvalue_get_integer(&cf->finfo_selected->value);
3010 return cf_goto_frame(cf, framenum);
3017 /* Select the packet on a given row. */
3019 cf_select_packet(capture_file *cf, int row)
3025 /* Get the frame data struct pointer for this frame */
3026 fdata = (frame_data *)packet_list_get_row_data(row);
3028 if (fdata == NULL) {
3029 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3030 the first entry is added to it by "real_insert_row()", that row
3031 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
3032 our version and the vanilla GTK+ version).
3034 This means that a "select-row" signal is emitted; this causes
3035 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3038 "cf_select_packet()" fetches, above, the data associated with the
3039 row that was selected; however, as "gtk_clist_append()", which
3040 called "real_insert_row()", hasn't yet returned, we haven't yet
3041 associated any data with that row, so we get back a null pointer.
3043 We can't assume that there's only one frame in the frame list,
3044 either, as we may be filtering the display.
3046 We therefore assume that, if "row" is 0, i.e. the first row
3047 is being selected, and "cf->first_displayed" equals
3048 "cf->last_displayed", i.e. there's only one frame being
3049 displayed, that frame is the frame we want.
3051 This means we have to set "cf->first_displayed" and
3052 "cf->last_displayed" before adding the row to the
3053 GtkCList; see the comment in "add_packet_to_packet_list()". */
3055 if (row == 0 && cf->first_displayed == cf->last_displayed)
3056 fdata = cf->first_displayed;
3059 /* Get the data in that frame. */
3060 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
3061 cf->pd, fdata->cap_len, &err, &err_info)) {
3062 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3063 cf_read_error_message(err, err_info), cf->filename);
3067 /* Record that this frame is the current frame. */
3068 cf->current_frame = fdata;
3070 /* Create the logical protocol tree. */
3071 if (cf->edt != NULL) {
3072 epan_dissect_free(cf->edt);
3075 /* We don't need the columns here. */
3076 cf->edt = epan_dissect_new(TRUE, TRUE);
3077 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3080 cf_callback_invoke(cf_cb_packet_selected, cf);
3083 /* Unselect the selected packet, if any. */
3085 cf_unselect_packet(capture_file *cf)
3087 /* Destroy the epan_dissect_t for the unselected packet. */
3088 if (cf->edt != NULL) {
3089 epan_dissect_free(cf->edt);
3093 /* No packet is selected. */
3094 cf->current_frame = NULL;
3096 cf_callback_invoke(cf_cb_packet_unselected, cf);
3098 /* No protocol tree means no selected field. */
3099 cf_unselect_field(cf);
3102 /* Unset the selected protocol tree field, if any. */
3104 cf_unselect_field(capture_file *cf)
3106 cf->finfo_selected = NULL;
3108 cf_callback_invoke(cf_cb_field_unselected, cf);
3112 * Mark a particular frame.
3115 cf_mark_frame(capture_file *cf, frame_data *frame)
3117 if (! frame->flags.marked) {
3118 frame->flags.marked = TRUE;
3119 if (cf->count > cf->marked_count)
3125 * Unmark a particular frame.
3128 cf_unmark_frame(capture_file *cf, frame_data *frame)
3130 if (frame->flags.marked) {
3131 frame->flags.marked = FALSE;
3132 if (cf->marked_count > 0)
3140 } save_callback_args_t;
3143 * Save a capture to a file, in a particular format, saving either
3144 * all packets, all currently-displayed packets, or all marked packets.
3146 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3147 * up a message box for the failure.
3150 save_packet(capture_file *cf _U_, frame_data *fdata,
3151 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3154 save_callback_args_t *args = argsp;
3155 struct wtap_pkthdr hdr;
3158 /* init the wtap header for saving */
3159 hdr.ts = *(struct wtap_nstime *) &fdata->abs_ts;
3160 hdr.caplen = fdata->cap_len;
3161 hdr.len = fdata->pkt_len;
3162 hdr.pkt_encap = fdata->lnk_t;
3164 /* and save the packet */
3165 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3166 cf_write_failure_alert_box(args->fname, err);
3173 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3175 gchar *from_filename;
3179 save_callback_args_t callback_args;
3181 cf_callback_invoke(cf_cb_file_safe_started, (gpointer) fname);
3183 /* don't write over an existing file. */
3184 /* this should've been already checked by our caller, just to be sure... */
3185 if (file_exists(fname)) {
3186 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3187 "%sCapture file: \"%s\" already exists!%s\n\n"
3188 "Please choose a different filename.",
3189 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3193 packet_range_process_init(range);
3196 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3197 /* We're not filtering packets, and we're saving it in the format
3198 it's already in, so we can just move or copy the raw data. */
3200 if (cf->is_tempfile) {
3201 /* The file being saved is a temporary file from a live
3202 capture, so it doesn't need to stay around under that name;
3203 first, try renaming the capture buffer file to the new name. */
3205 if (eth_rename(cf->filename, fname) == 0) {
3206 /* That succeeded - there's no need to copy the source file. */
3207 from_filename = NULL;
3210 if (errno == EXDEV) {
3211 /* They're on different file systems, so we have to copy the
3214 from_filename = cf->filename;
3216 /* The rename failed, but not because they're on different
3217 file systems - put up an error message. (Or should we
3218 just punt and try to copy? The only reason why I'd
3219 expect the rename to fail and the copy to succeed would
3220 be if we didn't have permission to remove the file from
3221 the temporary directory, and that might be fixable - but
3222 is it worth requiring the user to go off and fix it?) */
3223 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3224 file_rename_error_message(errno), fname);
3230 from_filename = cf->filename;
3233 /* It's a permanent file, so we should copy it, and not remove the
3236 from_filename = cf->filename;
3240 /* Copy the file, if we haven't moved it. */
3241 if (!copy_binary_file(from_filename, fname))
3245 /* Either we're filtering packets, or we're saving in a different
3246 format; we can't do that by copying or moving the capture file,
3247 we have to do it by writing the packets out in Wiretap. */
3248 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
3251 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3255 /* XXX - we let the user save a subset of the packets.
3257 If we do that, should we make that file the current file? If so,
3258 it means we can no longer get at the other packets. What does
3261 /* Iterate through the list of packets, processing the packets we were
3264 XXX - we've already called "packet_range_process_init(range)", but
3265 "process_specified_packets()" will do it again. Fortunately,
3266 that's harmless in this case, as we haven't done anything to
3267 "range" since we initialized it. */
3268 callback_args.pdh = pdh;
3269 callback_args.fname = fname;
3270 switch (process_specified_packets(cf, range, "Saving", "selected packets",
3271 TRUE, save_packet, &callback_args)) {
3274 /* Completed successfully. */
3278 /* The user decided to abort the saving.
3279 XXX - remove the output file? */
3283 /* Error while saving. */
3284 wtap_dump_close(pdh, &err);
3288 if (!wtap_dump_close(pdh, &err)) {
3289 cf_close_failure_alert_box(fname, err);
3294 cf_callback_invoke(cf_cb_file_safe_finished, NULL);
3296 if (packet_range_process_all(range)) {
3297 /* We saved the entire capture, not just some packets from it.
3298 Open and read the file we saved it to.
3300 XXX - this is somewhat of a waste; we already have the
3301 packets, all this gets us is updated file type information
3302 (which we could just stuff into "cf"), and having the new
3303 file be the one we have opened and from which we're reading
3304 the data, and it means we have to spend time opening and
3305 reading the file, which could be a significant amount of
3306 time if the file is large. */
3307 cf->user_saved = TRUE;
3309 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3310 /* XXX - report errors if this fails?
3311 What should we return if it fails or is aborted? */
3312 switch (cf_read(cf)) {
3316 /* Just because we got an error, that doesn't mean we were unable
3317 to read any of the file; we handle what we could get from the
3321 case CF_READ_ABORTED:
3322 /* The user bailed out of re-reading the capture file; the
3323 capture file has been closed - just return (without
3324 changing any menu settings; "cf_close()" set them
3325 correctly for the "no capture file open" state). */
3328 cf_callback_invoke(cf_cb_file_safe_reload_finished, NULL);
3334 cf_callback_invoke(cf_cb_file_safe_failed, NULL);
3339 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3340 gboolean for_writing, int file_type)
3343 /* Wiretap error. */
3346 case WTAP_ERR_NOT_REGULAR_FILE:
3347 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3348 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3352 case WTAP_ERR_RANDOM_OPEN_PIPE:
3353 /* Seen only when opening a capture file for reading. */
3354 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3355 "The file \"%s\" is a pipe or FIFO; Ethereal can't read pipe or FIFO files.",
3359 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3360 /* Seen only when opening a capture file for reading. */
3361 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3362 "The file \"%s\" isn't a capture file in a format Ethereal understands.",
3366 case WTAP_ERR_UNSUPPORTED:
3367 /* Seen only when opening a capture file for reading. */
3368 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3369 "The file \"%s\" isn't a capture file in a format Ethereal understands.\n"
3371 filename, err_info);
3375 case WTAP_ERR_CANT_WRITE_TO_PIPE:
3376 /* Seen only when opening a capture file for writing. */
3377 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3378 "The file \"%s\" is a pipe, and %s capture files can't be "
3379 "written to a pipe.",
3380 filename, wtap_file_type_string(file_type));
3383 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3384 /* Seen only when opening a capture file for writing. */
3385 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3386 "Ethereal doesn't support writing capture files in that format.");
3389 case WTAP_ERR_UNSUPPORTED_ENCAP:
3391 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3392 "Ethereal can't save this capture in that format.");
3394 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3395 "The file \"%s\" is a capture for a network type that Ethereal doesn't support.\n"
3397 filename, err_info);
3402 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3404 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3405 "Ethereal can't save this capture in that format.");
3407 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3408 "The file \"%s\" is a capture for a network type that Ethereal doesn't support.",
3413 case WTAP_ERR_BAD_RECORD:
3414 /* Seen only when opening a capture file for reading. */
3415 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3416 "The file \"%s\" appears to be damaged or corrupt.\n"
3418 filename, err_info);
3422 case WTAP_ERR_CANT_OPEN:
3424 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3425 "The file \"%s\" could not be created for some unknown reason.",
3428 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3429 "The file \"%s\" could not be opened for some unknown reason.",
3434 case WTAP_ERR_SHORT_READ:
3435 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3436 "The file \"%s\" appears to have been cut short"
3437 " in the middle of a packet or other data.",
3441 case WTAP_ERR_SHORT_WRITE:
3442 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3443 "A full header couldn't be written to the file \"%s\".",
3447 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
3448 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3449 "Gzip compression not supported by this file type.");
3453 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3454 "The file \"%s\" could not be %s: %s.",
3456 for_writing ? "created" : "opened",
3457 wtap_strerror(err));
3462 open_failure_alert_box(filename, err, for_writing);
3467 file_rename_error_message(int err)
3470 static char errmsg_errno[1024+1];
3475 errmsg = "The path to the file \"%s\" doesn't exist.";
3479 errmsg = "You don't have permission to move the capture file to \"%s\".";
3483 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3484 "The file \"%%s\" could not be moved: %s.",
3485 wtap_strerror(err));
3486 errmsg = errmsg_errno;
3493 cf_read_error_message(int err, const gchar *err_info)
3495 static char errmsg_errno[1024+1];
3499 case WTAP_ERR_UNSUPPORTED_ENCAP:
3500 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3501 "The file \"%%s\" has a packet with a network type that Ethereal doesn't support.\n(%s)",
3505 case WTAP_ERR_BAD_RECORD:
3506 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3507 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
3508 wtap_strerror(err), err_info);
3512 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3513 "An error occurred while reading from the file \"%%s\": %s.",
3514 wtap_strerror(err));
3517 return errmsg_errno;
3521 cf_write_failure_alert_box(const char *filename, int err)
3524 /* Wiretap error. */
3525 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3526 "An error occurred while writing to the file \"%s\": %s.",
3527 filename, wtap_strerror(err));
3530 write_failure_alert_box(filename, err);
3534 /* Check for write errors - if the file is being written to an NFS server,
3535 a write error may not show up until the file is closed, as NFS clients
3536 might not send writes to the server until the "write()" call finishes,
3537 so that the write may fail on the server but the "write()" may succeed. */
3539 cf_close_failure_alert_box(const char *filename, int err)
3542 /* Wiretap error. */
3545 case WTAP_ERR_CANT_CLOSE:
3546 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3547 "The file \"%s\" couldn't be closed for some unknown reason.",
3551 case WTAP_ERR_SHORT_WRITE:
3552 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3553 "Not all the packets could be written to the file \"%s\".",
3558 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3559 "An error occurred while closing the file \"%s\": %s.",
3560 filename, wtap_strerror(err));
3565 We assume that a close error from the OS is really a write error. */
3566 write_failure_alert_box(filename, err);
3570 /* Reload the current capture file. */
3572 cf_reload(capture_file *cf) {
3574 gboolean is_tempfile;
3577 /* If the file could be opened, "cf_open()" calls "cf_close()"
3578 to get rid of state for the old capture file before filling in state
3579 for the new capture file. "cf_close()" will remove the file if
3580 it's a temporary file; we don't want that to happen (for one thing,
3581 it'd prevent subsequent reopens from working). Remember whether it's
3582 a temporary file, mark it as not being a temporary file, and then
3583 reopen it as the type of file it was.
3585 Also, "cf_close()" will free "cf->filename", so we must make
3586 a copy of it first. */
3587 filename = g_strdup(cf->filename);
3588 is_tempfile = cf->is_tempfile;
3589 cf->is_tempfile = FALSE;
3590 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
3591 switch (cf_read(cf)) {
3595 /* Just because we got an error, that doesn't mean we were unable
3596 to read any of the file; we handle what we could get from the
3600 case CF_READ_ABORTED:
3601 /* The user bailed out of re-reading the capture file; the
3602 capture file has been closed - just free the capture file name
3603 string and return (without changing the last containing
3609 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
3610 Instead, the file was left open, so we should restore "cf->is_tempfile"
3613 XXX - change the menu? Presumably "cf_open()" will do that;
3614 make sure it does! */
3615 cf->is_tempfile = is_tempfile;
3617 /* "cf_open()" made a copy of the file name we handed it, so
3618 we should free up our copy. */
3622 /* Copies a file in binary mode, for those operating systems that care about
3624 * Returns TRUE on success, FALSE on failure. If a failure, it also
3625 * displays a simple dialog window with the error message.
3628 copy_binary_file(const char *from_filename, const char *to_filename)
3630 int from_fd, to_fd, nread, nwritten, err;
3633 /* Copy the raw bytes of the file. */
3634 from_fd = eth_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
3636 open_failure_alert_box(from_filename, errno, FALSE);
3640 /* Use open() instead of creat() so that we can pass the O_BINARY
3641 flag, which is relevant on Win32; it appears that "creat()"
3642 may open the file in text mode, not binary mode, but we want
3643 to copy the raw bytes of the file, so we need the output file
3644 to be open in binary mode. */
3645 to_fd = eth_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
3647 open_failure_alert_box(to_filename, errno, TRUE);
3652 while ((nread = eth_read(from_fd, pd, sizeof pd)) > 0) {
3653 nwritten = eth_write(to_fd, pd, nread);
3654 if (nwritten < nread) {
3658 err = WTAP_ERR_SHORT_WRITE;
3659 write_failure_alert_box(to_filename, err);
3667 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3668 "An error occurred while reading from the file \"%s\": %s.",
3669 from_filename, strerror(err));
3675 if (eth_close(to_fd) < 0) {
3676 write_failure_alert_box(to_filename, errno);