6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
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) {
350 color_filters_cleanup();
354 cleanup_dissection();
357 cf_callback_invoke(cf_cb_file_closed, cf);
361 cf_read(capture_file *cf)
365 const gchar *name_ptr;
367 char errmsg_errno[1024+1];
368 gchar err_str[2048+1];
370 progdlg_t *progbar = NULL;
372 gint64 size, file_pos;
375 gchar status_str[100];
376 gint64 progbar_nextstep;
377 gint64 progbar_quantum;
381 reset_tap_listeners();
382 tap_dfilter_dlg_update();
384 cf_callback_invoke(cf_cb_file_read_start, cf);
386 name_ptr = get_basename(cf->filename);
388 /* Find the size of the file. */
389 size = wtap_file_size(cf->wth, NULL);
391 /* Update the progress bar when it gets to this value. */
392 progbar_nextstep = 0;
393 /* When we reach the value that triggers a progress bar update,
394 bump that value by this amount. */
396 progbar_quantum = size/N_PROGBAR_UPDATES;
399 /* Progress so far. */
402 packet_list_freeze();
405 g_get_current_time(&start_time);
407 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
409 /* Create the progress bar if necessary.
410 We check on every iteration of the loop, so that it takes no
411 longer than the standard time to create it (otherwise, for a
412 large file, we might take considerably longer than that standard
413 time in order to get to the next progress bar step). */
414 if (progbar == NULL) {
415 progbar = delayed_create_progress_dlg("Loading", name_ptr,
416 TRUE, &stop_flag, &start_time, progbar_val);
419 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
420 when we update it, we have to run the GTK+ main loop to get it
421 to repaint what's pending, and doing so may involve an "ioctl()"
422 to see if there's any pending input from an X server, and doing
423 that for every packet can be costly, especially on a big file. */
424 if (data_offset >= progbar_nextstep) {
425 file_pos = wtap_read_so_far(cf->wth, NULL);
426 progbar_val = (gfloat) file_pos / (gfloat) size;
427 if (progbar_val > 1.0) {
428 /* The file probably grew while we were reading it.
429 Update file size, and try again. */
430 size = wtap_file_size(cf->wth, NULL);
432 progbar_val = (gfloat) file_pos / (gfloat) size;
433 /* If it's still > 1, either "wtap_file_size()" failed (in which
434 case there's not much we can do about it), or the file
435 *shrank* (in which case there's not much we can do about
436 it); just clip the progress value at 1.0. */
437 if (progbar_val > 1.0)
440 if (progbar != NULL) {
441 g_snprintf(status_str, sizeof(status_str),
442 "%" PRId64 "KB of %" PRId64 "KB",
443 file_pos / 1024, size / 1024);
444 update_progress_dlg(progbar, progbar_val, status_str);
446 progbar_nextstep += progbar_quantum;
451 /* Well, the user decided to abort the read. He/She will be warned and
452 it might be enough for him/her to work with the already loaded
454 This is especially true for very large capture files, where you don't
455 want to wait loading the whole file (which may last minutes or even
456 hours even on fast machines) just to see that it was the wrong file. */
459 read_packet(cf, data_offset);
462 /* We're done reading the file; destroy the progress bar if it was created. */
464 destroy_progress_dlg(progbar);
466 /* We're done reading sequentially through the file. */
467 cf->state = FILE_READ_DONE;
469 /* Close the sequential I/O side, to free up memory it requires. */
470 wtap_sequential_close(cf->wth);
472 /* Allow the protocol dissectors to free up memory that they
473 * don't need after the sequential run-through of the packets. */
474 postseq_cleanup_all_protocols();
476 /* Set the file encapsulation type now; we don't know what it is until
477 we've looked at all the packets, as we don't know until then whether
478 there's more than one type (and thus whether it's
479 WTAP_ENCAP_PER_PACKET). */
480 cf->lnk_t = wtap_file_encap(cf->wth);
482 cf->current_frame = cf->first_displayed;
485 cf_callback_invoke(cf_cb_file_read_finished, cf);
487 /* If we have any displayed packets to select, select the first of those
488 packets by making the first row the selected row. */
489 if (cf->first_displayed != NULL)
490 packet_list_select_row(0);
493 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
494 "%sFile loading was cancelled!%s\n"
496 "The remaining packets in the file were discarded.\n"
498 "As a lot of packets from the original file will be missing,\n"
499 "remember to be careful when saving the current content to a file.\n",
500 simple_dialog_primary_start(), simple_dialog_primary_end());
501 return CF_READ_ERROR;
505 /* Put up a message box noting that the read failed somewhere along
506 the line. Don't throw out the stuff we managed to read, though,
510 case WTAP_ERR_UNSUPPORTED_ENCAP:
511 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
512 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
515 errmsg = errmsg_errno;
518 case WTAP_ERR_CANT_READ:
519 errmsg = "An attempt to read from the capture file failed for"
520 " some unknown reason.";
523 case WTAP_ERR_SHORT_READ:
524 errmsg = "The capture file appears to have been cut short"
525 " in the middle of a packet.";
528 case WTAP_ERR_BAD_RECORD:
529 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
530 "The capture file appears to be damaged or corrupt.\n(%s)",
533 errmsg = errmsg_errno;
537 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
538 "An error occurred while reading the"
539 " capture file: %s.", wtap_strerror(err));
540 errmsg = errmsg_errno;
543 g_snprintf(err_str, sizeof err_str, errmsg);
544 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
545 return CF_READ_ERROR;
552 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
554 cf_status_t cf_status;
556 cf_status = cf_open(cf, fname, is_tempfile, err);
561 cf_continue_tail(capture_file *cf, int to_read, int *err)
563 long data_offset = 0;
568 packet_list_freeze();
570 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
572 while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
573 if (cf->state == FILE_READ_ABORTED) {
574 /* Well, the user decided to exit Wireshark. Break out of the
575 loop, and let the code below (which is called even if there
576 aren't any packets left to read) exit. */
579 read_packet(cf, data_offset);
583 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
584 cf->count, cf->state, *err);*/
588 /* moving to the end of the packet list - if the user requested so.
589 this doesn't seem to work well with a frozen GTK_Clist, so do this after
590 packet_list_thaw() is done, see bugzilla 1188 */
591 /* XXX - this cheats and looks inside the packet list to find the final
593 if (auto_scroll_live && cf->plist_end != NULL)
594 packet_list_moveto_end();
596 if (cf->state == FILE_READ_ABORTED) {
597 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
598 so that our caller can kill off the capture child process;
599 this will cause an EOF on the pipe from the child, so
600 "cf_finish_tail()" will be called, and it will clean up
602 return CF_READ_ABORTED;
603 } else if (*err != 0) {
604 /* We got an error reading the capture file.
605 XXX - pop up a dialog box instead? */
606 g_warning("Error \"%s\" while reading: \"%s\"\n",
607 wtap_strerror(*err), cf->filename);
609 return CF_READ_ERROR;
615 cf_finish_tail(capture_file *cf, int *err)
620 if(cf->wth == NULL) {
622 return CF_READ_ERROR;
625 packet_list_freeze();
627 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
628 if (cf->state == FILE_READ_ABORTED) {
629 /* Well, the user decided to abort the read. Break out of the
630 loop, and let the code below (which is called even if there
631 aren't any packets left to read) exit. */
634 read_packet(cf, data_offset);
639 if (cf->state == FILE_READ_ABORTED) {
640 /* Well, the user decided to abort the read. We're only called
641 when the child capture process closes the pipe to us (meaning
642 it's probably exited), so we can just close the capture
643 file; we return CF_READ_ABORTED so our caller can do whatever
644 is appropriate when that happens. */
646 return CF_READ_ABORTED;
649 if (auto_scroll_live && cf->plist_end != NULL)
650 /* XXX - this cheats and looks inside the packet list to find the final
652 packet_list_moveto_end();
654 /* We're done reading sequentially through the file. */
655 cf->state = FILE_READ_DONE;
657 /* We're done reading sequentially through the file; close the
658 sequential I/O side, to free up memory it requires. */
659 wtap_sequential_close(cf->wth);
661 /* Allow the protocol dissectors to free up memory that they
662 * don't need after the sequential run-through of the packets. */
663 postseq_cleanup_all_protocols();
665 /* Set the file encapsulation type now; we don't know what it is until
666 we've looked at all the packets, as we don't know until then whether
667 there's more than one type (and thus whether it's
668 WTAP_ENCAP_PER_PACKET). */
669 cf->lnk_t = wtap_file_encap(cf->wth);
672 /* We got an error reading the capture file.
673 XXX - pop up a dialog box? */
674 return CF_READ_ERROR;
679 #endif /* HAVE_LIBPCAP */
682 cf_get_display_name(capture_file *cf)
684 const gchar *displayname;
686 /* Return a name to use in displays */
687 if (!cf->is_tempfile) {
688 /* Get the last component of the file name, and use that. */
690 displayname = get_basename(cf->filename);
692 displayname="(No file)";
695 /* The file we read is a temporary file from a live capture;
696 we don't mention its name. */
697 displayname = "(Untitled)";
702 /* XXX - use a macro instead? */
704 cf_get_packet_count(capture_file *cf)
709 /* XXX - use a macro instead? */
711 cf_set_packet_count(capture_file *cf, int packet_count)
713 cf->count = packet_count;
716 /* XXX - use a macro instead? */
718 cf_is_tempfile(capture_file *cf)
720 return cf->is_tempfile;
723 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
725 cf->is_tempfile = is_tempfile;
729 /* XXX - use a macro instead? */
730 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
732 cf->drops_known = drops_known;
735 /* XXX - use a macro instead? */
736 void cf_set_drops(capture_file *cf, guint32 drops)
741 /* XXX - use a macro instead? */
742 gboolean cf_get_drops_known(capture_file *cf)
744 return cf->drops_known;
747 /* XXX - use a macro instead? */
748 guint32 cf_get_drops(capture_file *cf)
753 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
759 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
760 union wtap_pseudo_header *pseudo_header, const guchar *buf,
764 gboolean create_proto_tree = FALSE;
767 /* just add some value here until we know if it is being displayed or not */
768 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
770 /* If we don't have the time stamp of the first packet in the
771 capture, it's because this is the first packet. Save the time
772 stamp of this packet as the time stamp of the first packet. */
773 if (nstime_is_zero(&first_ts)) {
774 first_ts = fdata->abs_ts;
776 /* if this frames is marked as a reference time frame, reset
777 firstsec and firstusec to this frame */
778 if(fdata->flags.ref_time){
779 first_ts = fdata->abs_ts;
782 /* If we don't have the time stamp of the previous displayed packet,
783 it's because this is the first displayed packet. Save the time
784 stamp of this packet as the time stamp of the previous displayed
786 if (nstime_is_zero(&prev_ts)) {
787 prev_ts = fdata->abs_ts;
790 /* Get the time elapsed between the first packet and this packet. */
791 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
793 /* If it's greater than the current elapsed time, set the elapsed time
794 to it (we check for "greater than" so as not to be confused by
795 time moving backwards). */
796 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
797 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
798 cf->elapsed_time = fdata->rel_ts;
801 /* Get the time elapsed between the previous displayed packet and
803 nstime_delta(&fdata->del_ts, &fdata->abs_ts, &prev_ts);
807 we have a display filter and are re-applying it;
809 we have a list of color filters;
811 we have tap listeners;
813 allocate a protocol tree root node, so that we'll construct
814 a protocol tree against which a filter expression can be
816 if ((cf->dfcode != NULL && refilter) || color_filters_used()
817 || num_tap_filters != 0)
818 create_proto_tree = TRUE;
820 /* Dissect the frame. */
821 edt = epan_dissect_new(create_proto_tree, FALSE);
823 if (cf->dfcode != NULL && refilter) {
824 epan_dissect_prime_dfilter(edt, cf->dfcode);
826 /* prepare color filters */
827 if (color_filters_used()) {
828 color_filters_prime_edt(edt);
831 epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
832 tap_push_tapped_queue(edt);
834 /* If we have a display filter, apply it if we're refiltering, otherwise
835 leave the "passed_dfilter" flag alone.
837 If we don't have a display filter, set "passed_dfilter" to 1. */
838 if (cf->dfcode != NULL) {
840 fdata->flags.passed_dfilter = dfilter_apply_edt(cf->dfcode, edt) ? 1 : 0;
843 fdata->flags.passed_dfilter = 1;
845 if( (fdata->flags.passed_dfilter)
846 || (edt->pi.fd->flags.ref_time) ){
847 /* This frame either passed the display filter list or is marked as
848 a time reference frame. All time reference frames are displayed
849 even if they dont pass the display filter */
850 /* if this was a TIME REF frame we should reset the cul bytes field */
851 if(edt->pi.fd->flags.ref_time){
852 cum_bytes = fdata->pkt_len;
853 fdata->cum_bytes = cum_bytes;
856 /* increase cum_bytes with this packets length */
857 cum_bytes += fdata->pkt_len;
859 epan_dissect_fill_in_columns(edt);
861 /* If we haven't yet seen the first frame, this is it.
863 XXX - we must do this before we add the row to the display,
864 as, if the display's GtkCList's selection mode is
865 GTK_SELECTION_BROWSE, when the first entry is added to it,
866 "cf_select_packet()" will be called, and it will fetch the row
867 data for the 0th row, and will get a null pointer rather than
868 "fdata", as "gtk_clist_append()" won't yet have returned and
869 thus "gtk_clist_set_row_data()" won't yet have been called.
871 We thus need to leave behind bread crumbs so that
872 "cf_select_packet()" can find this frame. See the comment
873 in "cf_select_packet()". */
874 if (cf->first_displayed == NULL)
875 cf->first_displayed = fdata;
877 /* This is the last frame we've seen so far. */
878 cf->last_displayed = fdata;
880 row = packet_list_append(cf->cinfo.col_data, fdata);
882 /* colorize packet: if packet is marked, use preferences,
883 otherwise try to apply color filters */
884 if (fdata->flags.marked) {
885 fdata->color_filter = NULL;
886 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
888 fdata->color_filter = color_filters_colorize_packet(row, edt);
891 /* Set the time of the previous displayed frame to the time of this
893 prev_ts = fdata->abs_ts;
895 cf->displayed_count++;
897 /* This frame didn't pass the display filter, so it's not being added
898 to the clist, and thus has no row. */
901 epan_dissect_free(edt);
906 read_packet(capture_file *cf, long offset)
908 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
909 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
910 const guchar *buf = wtap_buf_ptr(cf->wth);
913 frame_data *plist_end;
916 /* Allocate the next list entry, and add it to the list. */
917 fdata = g_mem_chunk_alloc(cf->plist_chunk);
923 fdata->pkt_len = phdr->len;
924 fdata->cap_len = phdr->caplen;
925 fdata->file_off = offset;
926 fdata->lnk_t = phdr->pkt_encap;
927 fdata->flags.encoding = CHAR_ASCII;
928 fdata->flags.visited = 0;
929 fdata->flags.marked = 0;
930 fdata->flags.ref_time = 0;
931 fdata->color_filter = NULL;
933 fdata->abs_ts = *((nstime_t *) &phdr->ts);
937 edt = epan_dissect_new(TRUE, FALSE);
938 epan_dissect_prime_dfilter(edt, cf->rfcode);
939 epan_dissect_run(edt, pseudo_header, buf, fdata, NULL);
940 passed = dfilter_apply_edt(cf->rfcode, edt);
941 epan_dissect_free(edt);
944 plist_end = cf->plist_end;
945 fdata->prev = plist_end;
946 if (plist_end != NULL)
947 plist_end->next = fdata;
950 cf->plist_end = fdata;
953 cf->f_datalen = offset + phdr->caplen;
954 fdata->num = cf->count;
955 add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE);
957 /* XXX - if we didn't have read filters, or if we could avoid
958 allocating the "frame_data" structure until we knew whether
959 the frame passed the read filter, we could use a G_ALLOC_ONLY
962 ...but, at least in one test I did, where I just made the chunk
963 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
964 seem to save a noticeable amount of time or space. */
965 g_mem_chunk_free(cf->plist_chunk, fdata);
970 cf_merge_files(char **out_filenamep, int in_file_count,
971 char *const *in_filenames, int file_type, gboolean do_append)
973 merge_in_file_t *in_files;
979 int open_err, read_err, write_err, close_err;
983 char errmsg_errno[1024+1];
984 gchar err_str[2048+1];
986 gboolean got_read_error = FALSE, got_write_error = FALSE;
988 progdlg_t *progbar = NULL;
990 gint64 f_len, file_pos;
993 gchar status_str[100];
994 gint64 progbar_nextstep;
995 gint64 progbar_quantum;
997 /* open the input files */
998 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
999 &open_err, &err_info, &err_fileno)) {
1001 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1006 if (*out_filenamep != NULL) {
1007 out_filename = *out_filenamep;
1008 out_fd = eth_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1012 out_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
1015 out_filename = g_strdup(tmpname);
1016 *out_filenamep = out_filename;
1020 merge_close_in_files(in_file_count, in_files);
1022 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1026 pdh = wtap_dump_fdopen(out_fd, file_type,
1027 merge_select_frame_type(in_file_count, in_files),
1028 merge_max_snapshot_length(in_file_count, in_files),
1029 FALSE /* compressed */, &open_err);
1032 merge_close_in_files(in_file_count, in_files);
1034 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1039 /* Get the sum of the sizes of all the files. */
1041 for (i = 0; i < in_file_count; i++)
1042 f_len += in_files[i].size;
1044 /* Update the progress bar when it gets to this value. */
1045 progbar_nextstep = 0;
1046 /* When we reach the value that triggers a progress bar update,
1047 bump that value by this amount. */
1048 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1049 /* Progress so far. */
1053 g_get_current_time(&start_time);
1055 /* do the merge (or append) */
1058 wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1061 wth = merge_read_packet(in_file_count, in_files, &read_err,
1065 got_read_error = TRUE;
1069 /* Get the sum of the data offsets in all of the files. */
1071 for (i = 0; i < in_file_count; i++)
1072 data_offset += in_files[i].data_offset;
1074 /* Create the progress bar if necessary.
1075 We check on every iteration of the loop, so that it takes no
1076 longer than the standard time to create it (otherwise, for a
1077 large file, we might take considerably longer than that standard
1078 time in order to get to the next progress bar step). */
1079 if (progbar == NULL) {
1080 progbar = delayed_create_progress_dlg("Merging", "files",
1081 FALSE, &stop_flag, &start_time, progbar_val);
1084 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1085 when we update it, we have to run the GTK+ main loop to get it
1086 to repaint what's pending, and doing so may involve an "ioctl()"
1087 to see if there's any pending input from an X server, and doing
1088 that for every packet can be costly, especially on a big file. */
1089 if (data_offset >= progbar_nextstep) {
1090 /* Get the sum of the seek positions in all of the files. */
1092 for (i = 0; i < in_file_count; i++)
1093 file_pos += wtap_read_so_far(in_files[i].wth, NULL);
1094 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1095 if (progbar_val > 1.0) {
1096 /* Some file probably grew while we were reading it.
1097 That "shouldn't happen", so we'll just clip the progress
1101 if (progbar != NULL) {
1102 g_snprintf(status_str, sizeof(status_str),
1103 "%" PRId64 "KB of %" PRId64 "KB",
1104 file_pos / 1024, f_len / 1024);
1105 update_progress_dlg(progbar, progbar_val, status_str);
1107 progbar_nextstep += progbar_quantum;
1111 /* Well, the user decided to abort the merge. */
1115 if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1116 wtap_buf_ptr(wth), &write_err)) {
1117 got_write_error = TRUE;
1122 /* We're done merging the files; destroy the progress bar if it was created. */
1123 if (progbar != NULL)
1124 destroy_progress_dlg(progbar);
1126 merge_close_in_files(in_file_count, in_files);
1127 if (!got_read_error && !got_write_error) {
1128 if (!wtap_dump_close(pdh, &write_err))
1129 got_write_error = TRUE;
1131 wtap_dump_close(pdh, &close_err);
1133 if (got_read_error) {
1135 * Find the file on which we got the error, and report the error.
1137 for (i = 0; i < in_file_count; i++) {
1138 if (in_files[i].state == GOT_ERROR) {
1139 /* Put up a message box noting that a read failed somewhere along
1143 case WTAP_ERR_UNSUPPORTED_ENCAP:
1144 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1145 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1148 errmsg = errmsg_errno;
1151 case WTAP_ERR_CANT_READ:
1152 errmsg = "An attempt to read from the capture file %s failed for"
1153 " some unknown reason.";
1156 case WTAP_ERR_SHORT_READ:
1157 errmsg = "The capture file %s appears to have been cut short"
1158 " in the middle of a packet.";
1161 case WTAP_ERR_BAD_RECORD:
1162 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1163 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1166 errmsg = errmsg_errno;
1170 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1171 "An error occurred while reading the"
1172 " capture file %%s: %s.", wtap_strerror(read_err));
1173 errmsg = errmsg_errno;
1176 g_snprintf(err_str, sizeof err_str, errmsg, in_files[i].filename);
1177 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
1182 if (got_write_error) {
1183 /* Put up an alert box for the write error. */
1184 cf_write_failure_alert_box(out_filename, write_err);
1187 if (got_read_error || got_write_error || stop_flag) {
1188 /* Callers aren't expected to treat an error or an explicit abort
1189 differently - we put up error dialogs ourselves, so they don't
1197 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1200 const char *filter_new = dftext ? dftext : "";
1201 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1203 /* if new filter equals old one, do nothing unless told to do so */
1204 if (!force && strcmp(filter_new, filter_old) == 0) {
1208 if (dftext == NULL) {
1209 /* The new filter is an empty filter (i.e., display all packets). */
1213 * We have a filter; make a copy of it (as we'll be saving it),
1214 * and try to compile it.
1216 dftext = g_strdup(dftext);
1217 if (!dfilter_compile(dftext, &dfcode)) {
1218 /* The attempt failed; report an error. */
1219 gchar *safe_dftext = simple_dialog_format_message(dftext);
1220 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1222 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1225 "The following display filter isn't a valid display filter:\n%s\n"
1226 "See the help for a description of the display filter syntax.",
1227 simple_dialog_primary_start(), safe_dfilter_error_msg,
1228 simple_dialog_primary_end(), safe_dftext);
1229 g_free(safe_dfilter_error_msg);
1230 g_free(safe_dftext);
1236 if (dfcode == NULL) {
1237 /* Yes - free the filter text, and set it to null. */
1243 /* We have a valid filter. Replace the current filter. */
1244 if (cf->dfilter != NULL)
1245 g_free(cf->dfilter);
1246 cf->dfilter = dftext;
1247 if (cf->dfcode != NULL)
1248 dfilter_free(cf->dfcode);
1249 cf->dfcode = dfcode;
1251 /* Now rescan the packet list, applying the new filter, but not
1252 throwing away information constructed on a previous pass. */
1253 if (dftext == NULL) {
1254 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1256 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1262 cf_colorize_packets(capture_file *cf)
1264 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1268 cf_reftime_packets(capture_file *cf)
1270 rescan_packets(cf, "Updating Reftime", "all packets", FALSE, FALSE);
1274 cf_redissect_packets(capture_file *cf)
1276 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1279 /* Rescan the list of packets, reconstructing the CList.
1281 "action" describes why we're doing this; it's used in the progress
1284 "action_item" describes what we're doing; it's used in the progress
1287 "refilter" is TRUE if we need to re-evaluate the filter expression.
1289 "redissect" is TRUE if we need to make the dissectors reconstruct
1290 any state information they have (because a preference that affects
1291 some dissector has changed, meaning some dissector might construct
1292 its state differently from the way it was constructed the last time). */
1294 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1295 gboolean refilter, gboolean redissect)
1298 progdlg_t *progbar = NULL;
1303 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1304 int selected_row, prev_row, preceding_row, following_row;
1305 gboolean selected_frame_seen;
1308 GTimeVal start_time;
1309 gchar status_str[100];
1310 int progbar_nextstep;
1311 int progbar_quantum;
1314 reset_tap_listeners();
1315 /* Which frame, if any, is the currently selected frame?
1316 XXX - should the selected frame or the focus frame be the "current"
1317 frame, that frame being the one from which "Find Frame" searches
1319 selected_frame = cf->current_frame;
1321 /* We don't yet know what row that frame will be on, if any, after we
1322 rebuild the clist, however. */
1326 /* We need to re-initialize all the state information that protocols
1327 keep, because some preference that controls a dissector has changed,
1328 which might cause the state information to be constructed differently
1329 by that dissector. */
1331 /* Initialize all data structures used for dissection. */
1335 /* Freeze the packet list while we redo it, so we don't get any
1336 screen updates while it happens. */
1337 packet_list_freeze();
1340 packet_list_clear();
1342 /* We don't yet know which will be the first and last frames displayed. */
1343 cf->first_displayed = NULL;
1344 cf->last_displayed = NULL;
1346 /* We currently don't display any packets */
1347 cf->displayed_count = 0;
1349 /* Iterate through the list of frames. Call a routine for each frame
1350 to check whether it should be displayed and, if so, add it to
1351 the display list. */
1352 nstime_set_zero(&first_ts);
1353 nstime_set_zero(&prev_ts);
1355 /* Update the progress bar when it gets to this value. */
1356 progbar_nextstep = 0;
1357 /* When we reach the value that triggers a progress bar update,
1358 bump that value by this amount. */
1359 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1360 /* Count of packets at which we've looked. */
1362 /* Progress so far. */
1366 g_get_current_time(&start_time);
1368 row = -1; /* no previous row yet */
1373 preceding_frame = NULL;
1375 following_frame = NULL;
1377 selected_frame_seen = FALSE;
1379 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1380 /* Create the progress bar if necessary.
1381 We check on every iteration of the loop, so that it takes no
1382 longer than the standard time to create it (otherwise, for a
1383 large file, we might take considerably longer than that standard
1384 time in order to get to the next progress bar step). */
1385 if (progbar == NULL)
1386 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1387 &stop_flag, &start_time,
1390 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1391 when we update it, we have to run the GTK+ main loop to get it
1392 to repaint what's pending, and doing so may involve an "ioctl()"
1393 to see if there's any pending input from an X server, and doing
1394 that for every packet can be costly, especially on a big file. */
1395 if (count >= progbar_nextstep) {
1396 /* let's not divide by zero. I should never be started
1397 * with count == 0, so let's assert that
1399 g_assert(cf->count > 0);
1400 progbar_val = (gfloat) count / cf->count;
1402 if (progbar != NULL) {
1403 g_snprintf(status_str, sizeof(status_str),
1404 "%4u of %u frames", count, cf->count);
1405 update_progress_dlg(progbar, progbar_val, status_str);
1408 progbar_nextstep += progbar_quantum;
1412 /* Well, the user decided to abort the filtering. Just stop.
1414 XXX - go back to the previous filter? Users probably just
1415 want not to wait for a filtering operation to finish;
1416 unless we cancel by having no filter, reverting to the
1417 previous filter will probably be even more expensive than
1418 continuing the filtering, as it involves going back to the
1419 beginning and filtering, and even with no filter we currently
1420 have to re-generate the entire clist, which is also expensive.
1422 I'm not sure what Network Monitor does, but it doesn't appear
1423 to give you an unfiltered display if you cancel. */
1430 /* Since all state for the frame was destroyed, mark the frame
1431 * as not visited, free the GSList referring to the state
1432 * data (the per-frame data itself was freed by
1433 * "init_dissection()"), and null out the GSList pointer. */
1434 fdata->flags.visited = 0;
1436 g_slist_free(fdata->pfd);
1441 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1442 cf->pd, fdata->cap_len, &err, &err_info)) {
1443 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1444 cf_read_error_message(err, err_info), cf->filename);
1448 /* If the previous frame is displayed, and we haven't yet seen the
1449 selected frame, remember that frame - it's the closest one we've
1450 yet seen before the selected frame. */
1451 if (prev_row != -1 && !selected_frame_seen) {
1452 preceding_row = prev_row;
1453 preceding_frame = prev_frame;
1455 row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
1458 /* If this frame is displayed, and this is the first frame we've
1459 seen displayed after the selected frame, remember this frame -
1460 it's the closest one we've yet seen at or after the selected
1462 if (row != -1 && selected_frame_seen && following_row == -1) {
1463 following_row = row;
1464 following_frame = fdata;
1466 if (fdata == selected_frame) {
1468 selected_frame_seen = TRUE;
1471 /* Remember this row/frame - it'll be the previous row/frame
1472 on the next pass through the loop. */
1478 /* Clear out what remains of the visited flags and per-frame data
1481 XXX - that may cause various forms of bogosity when dissecting
1482 these frames, as they won't have been seen by this sequential
1483 pass, but the only alternative I see is to keep scanning them
1484 even though the user requested that the scan stop, and that
1485 would leave the user stuck with an Wireshark grinding on
1486 until it finishes. Should we just stick them with that? */
1487 for (; fdata != NULL; fdata = fdata->next) {
1488 fdata->flags.visited = 0;
1490 g_slist_free(fdata->pfd);
1496 /* We're done filtering the packets; destroy the progress bar if it
1498 if (progbar != NULL)
1499 destroy_progress_dlg(progbar);
1501 /* Unfreeze the packet list. */
1504 if (selected_row == -1) {
1505 /* The selected frame didn't pass the filter. */
1506 if (selected_frame == NULL) {
1507 /* That's because there *was* no selected frame. Make the first
1508 displayed frame the current frame. */
1511 /* Find the nearest displayed frame to the selected frame (whether
1512 it's before or after that frame) and make that the current frame.
1513 If the next and previous displayed frames are equidistant from the
1514 selected frame, choose the next one. */
1515 g_assert(following_frame == NULL ||
1516 following_frame->num >= selected_frame->num);
1517 g_assert(preceding_frame == NULL ||
1518 preceding_frame->num <= selected_frame->num);
1519 if (following_frame == NULL) {
1520 /* No frame after the selected frame passed the filter, so we
1521 have to select the last displayed frame before the selected
1523 selected_row = preceding_row;
1524 } else if (preceding_frame == NULL) {
1525 /* No frame before the selected frame passed the filter, so we
1526 have to select the first displayed frame after the selected
1528 selected_row = following_row;
1533 if (selected_row == -1) {
1534 /* There are no frames displayed at all. */
1535 cf_unselect_packet(cf);
1537 /* Either the frame that was selected passed the filter, or we've
1538 found the nearest displayed frame to that frame. Select it, make
1539 it the focus row, and make it visible. */
1540 packet_list_set_selected_row(selected_row);
1551 process_specified_packets(capture_file *cf, packet_range_t *range,
1552 const char *string1, const char *string2, gboolean terminate_is_stop,
1553 gboolean (*callback)(capture_file *, frame_data *,
1554 union wtap_pseudo_header *, const guint8 *, void *),
1555 void *callback_args)
1560 union wtap_pseudo_header pseudo_header;
1561 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
1562 psp_return_t ret = PSP_FINISHED;
1564 progdlg_t *progbar = NULL;
1567 gboolean progbar_stop_flag;
1568 GTimeVal progbar_start_time;
1569 gchar progbar_status_str[100];
1570 int progbar_nextstep;
1571 int progbar_quantum;
1572 range_process_e process_this;
1574 /* Update the progress bar when it gets to this value. */
1575 progbar_nextstep = 0;
1576 /* When we reach the value that triggers a progress bar update,
1577 bump that value by this amount. */
1578 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1579 /* Count of packets at which we've looked. */
1581 /* Progress so far. */
1584 progbar_stop_flag = FALSE;
1585 g_get_current_time(&progbar_start_time);
1587 packet_range_process_init(range);
1589 /* Iterate through the list of packets, printing the packets that
1590 were selected by the current display filter. */
1591 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1592 /* Create the progress bar if necessary.
1593 We check on every iteration of the loop, so that it takes no
1594 longer than the standard time to create it (otherwise, for a
1595 large file, we might take considerably longer than that standard
1596 time in order to get to the next progress bar step). */
1597 if (progbar == NULL)
1598 progbar = delayed_create_progress_dlg(string1, string2,
1601 &progbar_start_time,
1604 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1605 when we update it, we have to run the GTK+ main loop to get it
1606 to repaint what's pending, and doing so may involve an "ioctl()"
1607 to see if there's any pending input from an X server, and doing
1608 that for every packet can be costly, especially on a big file. */
1609 if (progbar_count >= progbar_nextstep) {
1610 /* let's not divide by zero. I should never be started
1611 * with count == 0, so let's assert that
1613 g_assert(cf->count > 0);
1614 progbar_val = (gfloat) progbar_count / cf->count;
1616 if (progbar != NULL) {
1617 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
1618 "%4u of %u packets", progbar_count, cf->count);
1619 update_progress_dlg(progbar, progbar_val, progbar_status_str);
1622 progbar_nextstep += progbar_quantum;
1625 if (progbar_stop_flag) {
1626 /* Well, the user decided to abort the operation. Just stop,
1627 and arrange to return PSP_STOPPED to our caller, so they know
1628 it was stopped explicitly. */
1635 /* do we have to process this packet? */
1636 process_this = packet_range_process_packet(range, fdata);
1637 if (process_this == range_process_next) {
1638 /* this packet uninteresting, continue with next one */
1640 } else if (process_this == range_processing_finished) {
1641 /* all interesting packets processed, stop the loop */
1645 /* Get the packet */
1646 if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1647 pd, fdata->cap_len, &err, &err_info)) {
1648 /* Attempt to get the packet failed. */
1649 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1650 cf_read_error_message(err, err_info), cf->filename);
1654 /* Process the packet */
1655 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
1656 /* Callback failed. We assume it reported the error appropriately. */
1662 /* We're done printing the packets; destroy the progress bar if
1664 if (progbar != NULL)
1665 destroy_progress_dlg(progbar);
1671 retap_packet(capture_file *cf _U_, frame_data *fdata,
1672 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1675 column_info *cinfo = argsp;
1676 epan_dissect_t *edt;
1678 /* If we have tap listeners, allocate a protocol tree root node, so that
1679 we'll construct a protocol tree against which a filter expression can
1681 edt = epan_dissect_new(num_tap_filters != 0, FALSE);
1682 tap_queue_init(edt);
1683 epan_dissect_run(edt, pseudo_header, pd, fdata, cinfo);
1684 tap_push_tapped_queue(edt);
1685 epan_dissect_free(edt);
1691 cf_retap_packets(capture_file *cf, gboolean do_columns)
1693 packet_range_t range;
1695 /* Reset the tap listeners. */
1696 reset_tap_listeners();
1698 /* Iterate through the list of packets, dissecting all packets and
1699 re-running the taps. */
1700 packet_range_init(&range);
1701 packet_range_process_init(&range);
1702 switch (process_specified_packets(cf, &range, "Refiltering statistics on",
1703 "all packets", TRUE, retap_packet,
1704 do_columns ? &cf->cinfo : NULL)) {
1706 /* Completed successfully. */
1710 /* Well, the user decided to abort the refiltering.
1711 Return CF_READ_ABORTED so our caller knows they did that. */
1712 return CF_READ_ABORTED;
1715 /* Error while retapping. */
1716 return CF_READ_ERROR;
1719 g_assert_not_reached();
1724 print_args_t *print_args;
1725 gboolean print_header_line;
1726 char *header_line_buf;
1727 int header_line_buf_len;
1728 gboolean print_formfeed;
1729 gboolean print_separator;
1733 } print_callback_args_t;
1736 print_packet(capture_file *cf, frame_data *fdata,
1737 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1740 print_callback_args_t *args = argsp;
1741 epan_dissect_t *edt;
1747 gboolean proto_tree_needed;
1748 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
1749 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
1751 /* Create the protocol tree, and make it visible, if we're printing
1752 the dissection or the hex data.
1753 XXX - do we need it if we're just printing the hex data? */
1755 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex;
1756 edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
1758 /* Fill in the column information if we're printing the summary
1760 if (args->print_args->print_summary) {
1761 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
1762 epan_dissect_fill_in_columns(edt);
1764 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1766 if (args->print_formfeed) {
1767 if (!new_page(args->print_args->stream))
1770 if (args->print_separator) {
1771 if (!print_line(args->print_args->stream, 0, ""))
1777 * We generate bookmarks, if the output format supports them.
1778 * The name is "__frameN__".
1780 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
1782 if (args->print_args->print_summary) {
1783 if (args->print_header_line) {
1784 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
1786 args->print_header_line = FALSE; /* we might not need to print any more */
1788 cp = &args->line_buf[0];
1790 for (i = 0; i < cf->cinfo.num_cols; i++) {
1791 /* Find the length of the string for this column. */
1792 column_len = strlen(cf->cinfo.col_data[i]);
1793 if (args->col_widths[i] > column_len)
1794 column_len = args->col_widths[i];
1796 /* Make sure there's room in the line buffer for the column; if not,
1797 double its length. */
1798 line_len += column_len + 1; /* "+1" for space */
1799 if (line_len > args->line_buf_len) {
1800 cp_off = cp - args->line_buf;
1801 args->line_buf_len = 2 * line_len;
1802 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
1803 cp = args->line_buf + cp_off;
1806 /* Right-justify the packet number column. */
1807 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1808 sprintf(cp, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
1810 sprintf(cp, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
1812 if (i != cf->cinfo.num_cols - 1)
1818 * Generate a bookmark, using the summary line as the title.
1820 if (!print_bookmark(args->print_args->stream, bookmark_name,
1824 if (!print_line(args->print_args->stream, 0, args->line_buf))
1828 * Generate a bookmark, using "Frame N" as the title, as we're not
1829 * printing the summary line.
1831 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
1832 if (!print_bookmark(args->print_args->stream, bookmark_name,
1835 } /* if (print_summary) */
1837 if (args->print_args->print_dissections != print_dissections_none) {
1838 if (args->print_args->print_summary) {
1839 /* Separate the summary line from the tree with a blank line. */
1840 if (!print_line(args->print_args->stream, 0, ""))
1844 /* Print the information in that tree. */
1845 if (!proto_tree_print(args->print_args, edt, args->print_args->stream))
1848 /* Print a blank line if we print anything after this (aka more than one packet). */
1849 args->print_separator = TRUE;
1851 /* Print a header line if we print any more packet summaries */
1852 args->print_header_line = TRUE;
1855 if (args->print_args->print_hex) {
1856 /* Print the full packet data as hex. */
1857 if (!print_hex_data(args->print_args->stream, edt))
1860 /* Print a blank line if we print anything after this (aka more than one packet). */
1861 args->print_separator = TRUE;
1863 /* Print a header line if we print any more packet summaries */
1864 args->print_header_line = TRUE;
1865 } /* if (args->print_args->print_dissections != print_dissections_none) */
1867 epan_dissect_free(edt);
1869 /* do we want to have a formfeed between each packet from now on? */
1870 if(args->print_args->print_formfeed) {
1871 args->print_formfeed = TRUE;
1877 epan_dissect_free(edt);
1882 cf_print_packets(capture_file *cf, print_args_t *print_args)
1885 print_callback_args_t callback_args;
1893 callback_args.print_args = print_args;
1894 callback_args.print_header_line = TRUE;
1895 callback_args.header_line_buf = NULL;
1896 callback_args.header_line_buf_len = 256;
1897 callback_args.print_formfeed = FALSE;
1898 callback_args.print_separator = FALSE;
1899 callback_args.line_buf = NULL;
1900 callback_args.line_buf_len = 256;
1901 callback_args.col_widths = NULL;
1903 if (!print_preamble(print_args->stream, cf->filename)) {
1904 destroy_print_stream(print_args->stream);
1905 return CF_PRINT_WRITE_ERROR;
1908 if (print_args->print_summary) {
1909 /* We're printing packet summaries. Allocate the header line buffer
1910 and get the column widths. */
1911 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
1913 /* Find the widths for each of the columns - maximum of the
1914 width of the title and the width of the data - and construct
1915 a buffer with a line containing the column titles. */
1916 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1917 cp = &callback_args.header_line_buf[0];
1919 for (i = 0; i < cf->cinfo.num_cols; i++) {
1920 /* Don't pad the last column. */
1921 if (i == cf->cinfo.num_cols - 1)
1922 callback_args.col_widths[i] = 0;
1924 callback_args.col_widths[i] = strlen(cf->cinfo.col_title[i]);
1925 data_width = get_column_char_width(get_column_format(i));
1926 if (data_width > callback_args.col_widths[i])
1927 callback_args.col_widths[i] = data_width;
1930 /* Find the length of the string for this column. */
1931 column_len = strlen(cf->cinfo.col_title[i]);
1932 if (callback_args.col_widths[i] > column_len)
1933 column_len = callback_args.col_widths[i];
1935 /* Make sure there's room in the line buffer for the column; if not,
1936 double its length. */
1937 line_len += column_len + 1; /* "+1" for space */
1938 if (line_len > callback_args.header_line_buf_len) {
1939 cp_off = cp - callback_args.header_line_buf;
1940 callback_args.header_line_buf_len = 2 * line_len;
1941 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
1942 callback_args.header_line_buf_len + 1);
1943 cp = callback_args.header_line_buf + cp_off;
1946 /* Right-justify the packet number column. */
1947 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1948 sprintf(cp, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1950 sprintf(cp, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1952 if (i != cf->cinfo.num_cols - 1)
1957 /* Now start out the main line buffer with the same length as the
1958 header line buffer. */
1959 callback_args.line_buf_len = callback_args.header_line_buf_len;
1960 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
1961 } /* if (print_summary) */
1963 /* Iterate through the list of packets, printing the packets we were
1965 ret = process_specified_packets(cf, &print_args->range, "Printing",
1966 "selected packets", TRUE, print_packet,
1969 if (callback_args.header_line_buf != NULL)
1970 g_free(callback_args.header_line_buf);
1971 if (callback_args.line_buf != NULL)
1972 g_free(callback_args.line_buf);
1973 if (callback_args.col_widths != NULL)
1974 g_free(callback_args.col_widths);
1979 /* Completed successfully. */
1983 /* Well, the user decided to abort the printing.
1985 XXX - note that what got generated before they did that
1986 will get printed if we're piping to a print program; we'd
1987 have to write to a file and then hand that to the print
1988 program to make it actually not print anything. */
1992 /* Error while printing.
1994 XXX - note that what got generated before they did that
1995 will get printed if we're piping to a print program; we'd
1996 have to write to a file and then hand that to the print
1997 program to make it actually not print anything. */
1998 destroy_print_stream(print_args->stream);
1999 return CF_PRINT_WRITE_ERROR;
2002 if (!print_finale(print_args->stream)) {
2003 destroy_print_stream(print_args->stream);
2004 return CF_PRINT_WRITE_ERROR;
2007 if (!destroy_print_stream(print_args->stream))
2008 return CF_PRINT_WRITE_ERROR;
2014 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2015 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2019 epan_dissect_t *edt;
2021 /* Create the protocol tree, but don't fill in the column information. */
2022 edt = epan_dissect_new(TRUE, TRUE);
2023 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
2025 /* Write out the information in that tree. */
2026 proto_tree_write_pdml(edt, fh);
2028 epan_dissect_free(edt);
2034 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2039 fh = eth_fopen(print_args->file, "w");
2041 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2043 write_pdml_preamble(fh);
2046 return CF_PRINT_WRITE_ERROR;
2049 /* Iterate through the list of packets, printing the packets we were
2051 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2052 "selected packets", TRUE,
2053 write_pdml_packet, fh);
2058 /* Completed successfully. */
2062 /* Well, the user decided to abort the printing. */
2066 /* Error while printing. */
2068 return CF_PRINT_WRITE_ERROR;
2071 write_pdml_finale(fh);
2074 return CF_PRINT_WRITE_ERROR;
2077 /* XXX - check for an error */
2084 write_psml_packet(capture_file *cf, frame_data *fdata,
2085 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2089 epan_dissect_t *edt;
2091 /* Fill in the column information, but don't create the protocol tree. */
2092 edt = epan_dissect_new(FALSE, FALSE);
2093 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2094 epan_dissect_fill_in_columns(edt);
2096 /* Write out the information in that tree. */
2097 proto_tree_write_psml(edt, fh);
2099 epan_dissect_free(edt);
2105 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2110 fh = eth_fopen(print_args->file, "w");
2112 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2114 write_psml_preamble(fh);
2117 return CF_PRINT_WRITE_ERROR;
2120 /* Iterate through the list of packets, printing the packets we were
2122 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2123 "selected packets", TRUE,
2124 write_psml_packet, fh);
2129 /* Completed successfully. */
2133 /* Well, the user decided to abort the printing. */
2137 /* Error while printing. */
2139 return CF_PRINT_WRITE_ERROR;
2142 write_psml_finale(fh);
2145 return CF_PRINT_WRITE_ERROR;
2148 /* XXX - check for an error */
2155 write_csv_packet(capture_file *cf, frame_data *fdata,
2156 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2160 epan_dissect_t *edt;
2162 /* Fill in the column information, but don't create the protocol tree. */
2163 edt = epan_dissect_new(FALSE, FALSE);
2164 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2165 epan_dissect_fill_in_columns(edt);
2167 /* Write out the information in that tree. */
2168 proto_tree_write_csv(edt, fh);
2170 epan_dissect_free(edt);
2176 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2181 fh = eth_fopen(print_args->file, "w");
2183 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2185 write_csv_preamble(fh);
2188 return CF_PRINT_WRITE_ERROR;
2191 /* Iterate through the list of packets, printing the packets we were
2193 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2194 "selected packets", TRUE,
2195 write_csv_packet, fh);
2200 /* Completed successfully. */
2204 /* Well, the user decided to abort the printing. */
2208 /* Error while printing. */
2210 return CF_PRINT_WRITE_ERROR;
2213 write_csv_finale(fh);
2216 return CF_PRINT_WRITE_ERROR;
2219 /* XXX - check for an error */
2225 /* Scan through the packet list and change all columns that use the
2226 "command-line-specified" time stamp format to use the current
2227 value of that format. */
2229 cf_change_time_formats(capture_file *cf)
2232 progdlg_t *progbar = NULL;
2238 GTimeVal start_time;
2239 gchar status_str[100];
2240 int progbar_nextstep;
2241 int progbar_quantum;
2243 gboolean sorted_by_frame_column;
2246 /* adjust timestamp precision if auto is selected */
2247 cf_timestamp_auto_precision(cf);
2249 /* Are there any columns with time stamps in the "command-line-specified"
2252 XXX - we have to force the "column is writable" flag on, as it
2253 might be off from the last frame that was dissected. */
2254 col_set_writable(&cf->cinfo, TRUE);
2255 if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
2256 /* No, there aren't any columns in that format, so we have no work
2260 first = cf->cinfo.col_first[COL_CLS_TIME];
2261 g_assert(first >= 0);
2262 last = cf->cinfo.col_last[COL_CLS_TIME];
2264 /* Freeze the packet list while we redo it, so we don't get any
2265 screen updates while it happens. */
2266 packet_list_freeze();
2268 /* Update the progress bar when it gets to this value. */
2269 progbar_nextstep = 0;
2270 /* When we reach the value that triggers a progress bar update,
2271 bump that value by this amount. */
2272 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2273 /* Count of packets at which we've looked. */
2275 /* Progress so far. */
2278 /* If the rows are currently sorted by the frame column then we know
2279 * the row number of each packet: it's the row number of the previously
2280 * displayed packet + 1.
2282 * Otherwise, if the display is sorted by a different column then we have
2283 * to use the O(N) packet_list_find_row_from_data() (thus making the job
2284 * of changing the time display format O(N**2)).
2286 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
2287 * the row number and walks that many elements down the clist to find
2288 * the appropriate element.)
2290 sorted_by_frame_column = FALSE;
2291 for (i = 0; i < cf->cinfo.num_cols; i++) {
2292 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2294 sorted_by_frame_column = (i == packet_list_get_sort_column());
2300 g_get_current_time(&start_time);
2302 /* Iterate through the list of packets, checking whether the packet
2303 is in a row of the summary list and, if so, whether there are
2304 any columns that show the time in the "command-line-specified"
2305 format and, if so, update that row. */
2306 for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
2307 /* Create the progress bar if necessary.
2308 We check on every iteration of the loop, so that it takes no
2309 longer than the standard time to create it (otherwise, for a
2310 large file, we might take considerably longer than that standard
2311 time in order to get to the next progress bar step). */
2312 if (progbar == NULL)
2313 progbar = delayed_create_progress_dlg("Changing", "time display",
2314 TRUE, &stop_flag, &start_time, progbar_val);
2316 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2317 when we update it, we have to run the GTK+ main loop to get it
2318 to repaint what's pending, and doing so may involve an "ioctl()"
2319 to see if there's any pending input from an X server, and doing
2320 that for every packet can be costly, especially on a big file. */
2321 if (count >= progbar_nextstep) {
2322 /* let's not divide by zero. I should never be started
2323 * with count == 0, so let's assert that
2325 g_assert(cf->count > 0);
2327 progbar_val = (gfloat) count / cf->count;
2329 if (progbar != NULL) {
2330 g_snprintf(status_str, sizeof(status_str),
2331 "%4u of %u packets", count, cf->count);
2332 update_progress_dlg(progbar, progbar_val, status_str);
2335 progbar_nextstep += progbar_quantum;
2339 /* Well, the user decided to abort the redisplay. Just stop.
2341 XXX - this leaves the time field in the old format in
2342 frames we haven't yet processed. So it goes; should we
2343 simply not offer them the option of stopping? */
2349 /* Find what row this packet is in. */
2350 if (!sorted_by_frame_column) {
2351 /* This function is O(N), so we try to avoid using it... */
2352 row = packet_list_find_row_from_data(fdata);
2354 /* ...which we do by maintaining a count of packets that are
2355 being displayed (i.e., that have passed the display filter),
2356 and using the current value of that count as the row number
2357 (which is why we can only do it when the display is sorted
2358 by the frame number). */
2359 if (fdata->flags.passed_dfilter)
2366 /* This packet is in the summary list, on row "row". */
2368 for (i = first; i <= last; i++) {
2369 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2370 /* This is one of the columns that shows the time in
2371 "command-line-specified" format; update it. */
2372 cf->cinfo.col_buf[i][0] = '\0';
2373 col_set_cls_time(fdata, &cf->cinfo, i);
2374 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
2380 /* We're done redisplaying the packets; destroy the progress bar if it
2382 if (progbar != NULL)
2383 destroy_progress_dlg(progbar);
2385 /* Set the column widths of those columns that show the time in
2386 "command-line-specified" format. */
2387 for (i = first; i <= last; i++) {
2388 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2389 packet_list_set_cls_time_width(i);
2393 /* Unfreeze the packet list. */
2401 gboolean frame_matched;
2405 cf_find_packet_protocol_tree(capture_file *cf, const char *string)
2409 mdata.string = string;
2410 mdata.string_len = strlen(string);
2411 return find_packet(cf, match_protocol_tree, &mdata);
2415 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2417 match_data *mdata = criterion;
2418 epan_dissect_t *edt;
2420 /* Construct the protocol tree, including the displayed text */
2421 edt = epan_dissect_new(TRUE, TRUE);
2422 /* We don't need the column information */
2423 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2425 /* Iterate through all the nodes, seeing if they have text that matches. */
2427 mdata->frame_matched = FALSE;
2428 proto_tree_children_foreach(edt->tree, match_subtree_text, mdata);
2429 epan_dissect_free(edt);
2430 return mdata->frame_matched;
2434 match_subtree_text(proto_node *node, gpointer data)
2436 match_data *mdata = (match_data*) data;
2437 const gchar *string = mdata->string;
2438 size_t string_len = mdata->string_len;
2439 capture_file *cf = mdata->cf;
2440 field_info *fi = PITEM_FINFO(node);
2441 gchar label_str[ITEM_LABEL_LENGTH];
2448 if (mdata->frame_matched) {
2449 /* We already had a match; don't bother doing any more work. */
2453 /* Don't match invisible entries. */
2454 if (PROTO_ITEM_IS_HIDDEN(node))
2457 /* was a free format label produced? */
2459 label_ptr = fi->rep->representation;
2461 /* no, make a generic label */
2462 label_ptr = label_str;
2463 proto_item_fill_label(fi, label_str);
2466 /* Does that label match? */
2467 label_len = strlen(label_ptr);
2468 for (i = 0; i < label_len; i++) {
2469 c_char = label_ptr[i];
2471 c_char = toupper(c_char);
2472 if (c_char == string[c_match]) {
2474 if (c_match == string_len) {
2475 /* No need to look further; we have a match */
2476 mdata->frame_matched = TRUE;
2483 /* Recurse into the subtree, if it exists */
2484 if (node->first_child != NULL)
2485 proto_tree_children_foreach(node, match_subtree_text, mdata);
2489 cf_find_packet_summary_line(capture_file *cf, const char *string)
2493 mdata.string = string;
2494 mdata.string_len = strlen(string);
2495 return find_packet(cf, match_summary_line, &mdata);
2499 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2501 match_data *mdata = criterion;
2502 const gchar *string = mdata->string;
2503 size_t string_len = mdata->string_len;
2504 epan_dissect_t *edt;
2505 const char *info_column;
2506 size_t info_column_len;
2507 gboolean frame_matched = FALSE;
2513 /* Don't bother constructing the protocol tree */
2514 edt = epan_dissect_new(FALSE, FALSE);
2515 /* Get the column information */
2516 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2518 /* Find the Info column */
2519 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2520 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2521 /* Found it. See if we match. */
2522 info_column = edt->pi.cinfo->col_data[colx];
2523 info_column_len = strlen(info_column);
2524 for (i = 0; i < info_column_len; i++) {
2525 c_char = info_column[i];
2527 c_char = toupper(c_char);
2528 if (c_char == string[c_match]) {
2530 if (c_match == string_len) {
2531 frame_matched = TRUE;
2540 epan_dissect_free(edt);
2541 return frame_matched;
2547 } cbs_t; /* "Counted byte string" */
2550 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
2555 info.data_len = string_size;
2557 /* String or hex search? */
2559 /* String search - what type of string? */
2560 switch (cf->scs_type) {
2562 case SCS_ASCII_AND_UNICODE:
2563 return find_packet(cf, match_ascii_and_unicode, &info);
2566 return find_packet(cf, match_ascii, &info);
2569 return find_packet(cf, match_unicode, &info);
2572 g_assert_not_reached();
2576 return find_packet(cf, match_binary, &info);
2580 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2582 cbs_t *info = criterion;
2583 const char *ascii_text = info->data;
2584 size_t textlen = info->data_len;
2585 gboolean frame_matched;
2591 frame_matched = FALSE;
2592 buf_len = fdata->pkt_len;
2593 for (i = 0; i < buf_len; i++) {
2596 c_char = toupper(c_char);
2598 if (c_char == ascii_text[c_match]) {
2600 if (c_match == textlen) {
2601 frame_matched = TRUE;
2608 return frame_matched;
2612 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2614 cbs_t *info = criterion;
2615 const char *ascii_text = info->data;
2616 size_t textlen = info->data_len;
2617 gboolean frame_matched;
2623 frame_matched = FALSE;
2624 buf_len = fdata->pkt_len;
2625 for (i = 0; i < buf_len; i++) {
2628 c_char = toupper(c_char);
2629 if (c_char == ascii_text[c_match]) {
2631 if (c_match == textlen) {
2632 frame_matched = TRUE;
2638 return frame_matched;
2642 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2644 cbs_t *info = criterion;
2645 const char *ascii_text = info->data;
2646 size_t textlen = info->data_len;
2647 gboolean frame_matched;
2653 frame_matched = FALSE;
2654 buf_len = fdata->pkt_len;
2655 for (i = 0; i < buf_len; i++) {
2658 c_char = toupper(c_char);
2659 if (c_char == ascii_text[c_match]) {
2662 if (c_match == textlen) {
2663 frame_matched = TRUE;
2669 return frame_matched;
2673 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
2675 cbs_t *info = criterion;
2676 const guint8 *binary_data = info->data;
2677 size_t datalen = info->data_len;
2678 gboolean frame_matched;
2683 frame_matched = FALSE;
2684 buf_len = fdata->pkt_len;
2685 for (i = 0; i < buf_len; i++) {
2686 if (cf->pd[i] == binary_data[c_match]) {
2688 if (c_match == datalen) {
2689 frame_matched = TRUE;
2695 return frame_matched;
2699 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
2701 return find_packet(cf, match_dfilter, sfcode);
2705 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
2707 dfilter_t *sfcode = criterion;
2708 epan_dissect_t *edt;
2709 gboolean frame_matched;
2711 edt = epan_dissect_new(TRUE, FALSE);
2712 epan_dissect_prime_dfilter(edt, sfcode);
2713 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2714 frame_matched = dfilter_apply_edt(sfcode, edt);
2715 epan_dissect_free(edt);
2716 return frame_matched;
2720 find_packet(capture_file *cf,
2721 gboolean (*match_function)(capture_file *, frame_data *, void *),
2724 frame_data *start_fd;
2726 frame_data *new_fd = NULL;
2727 progdlg_t *progbar = NULL;
2734 GTimeVal start_time;
2735 gchar status_str[100];
2736 int progbar_nextstep;
2737 int progbar_quantum;
2740 start_fd = cf->current_frame;
2741 if (start_fd != NULL) {
2742 /* Iterate through the list of packets, starting at the packet we've
2743 picked, calling a routine to run the filter on the packet, see if
2744 it matches, and stop if so. */
2748 /* Update the progress bar when it gets to this value. */
2749 progbar_nextstep = 0;
2750 /* When we reach the value that triggers a progress bar update,
2751 bump that value by this amount. */
2752 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2753 /* Progress so far. */
2757 g_get_current_time(&start_time);
2760 title = cf->sfilter?cf->sfilter:"";
2762 /* Create the progress bar if necessary.
2763 We check on every iteration of the loop, so that it takes no
2764 longer than the standard time to create it (otherwise, for a
2765 large file, we might take considerably longer than that standard
2766 time in order to get to the next progress bar step). */
2767 if (progbar == NULL)
2768 progbar = delayed_create_progress_dlg("Searching", title,
2769 FALSE, &stop_flag, &start_time, progbar_val);
2771 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2772 when we update it, we have to run the GTK+ main loop to get it
2773 to repaint what's pending, and doing so may involve an "ioctl()"
2774 to see if there's any pending input from an X server, and doing
2775 that for every packet can be costly, especially on a big file. */
2776 if (count >= progbar_nextstep) {
2777 /* let's not divide by zero. I should never be started
2778 * with count == 0, so let's assert that
2780 g_assert(cf->count > 0);
2782 progbar_val = (gfloat) count / cf->count;
2784 if (progbar != NULL) {
2785 g_snprintf(status_str, sizeof(status_str),
2786 "%4u of %u packets", count, cf->count);
2787 update_progress_dlg(progbar, progbar_val, status_str);
2790 progbar_nextstep += progbar_quantum;
2794 /* Well, the user decided to abort the search. Go back to the
2795 frame where we started. */
2800 /* Go past the current frame. */
2801 if (cf->sbackward) {
2802 /* Go on to the previous frame. */
2803 fdata = fdata->prev;
2804 if (fdata == NULL) {
2806 * XXX - other apps have a bit more of a detailed message
2807 * for this, and instead of offering "OK" and "Cancel",
2808 * they offer things such as "Continue" and "Cancel";
2809 * we need an API for popping up alert boxes with
2810 * {Verb} and "Cancel".
2813 if (prefs.gui_find_wrap)
2815 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2816 "%sBeginning of capture exceeded!%s\n\n"
2817 "Search is continued from the end of the capture.",
2818 simple_dialog_primary_start(), simple_dialog_primary_end());
2819 fdata = cf->plist_end; /* wrap around */
2823 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2824 "%sBeginning of capture exceeded!%s\n\n"
2825 "Try searching forwards.",
2826 simple_dialog_primary_start(), simple_dialog_primary_end());
2827 fdata = start_fd; /* stay on previous packet */
2831 /* Go on to the next frame. */
2832 fdata = fdata->next;
2833 if (fdata == NULL) {
2834 if (prefs.gui_find_wrap)
2836 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2837 "%sEnd of capture exceeded!%s\n\n"
2838 "Search is continued from the start of the capture.",
2839 simple_dialog_primary_start(), simple_dialog_primary_end());
2840 fdata = cf->plist; /* wrap around */
2844 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2845 "%sEnd of capture exceeded!%s\n\n"
2846 "Try searching backwards.",
2847 simple_dialog_primary_start(), simple_dialog_primary_end());
2848 fdata = start_fd; /* stay on previous packet */
2855 /* Is this packet in the display? */
2856 if (fdata->flags.passed_dfilter) {
2857 /* Yes. Load its data. */
2858 if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
2859 cf->pd, fdata->cap_len, &err, &err_info)) {
2860 /* Read error. Report the error, and go back to the frame
2861 where we started. */
2862 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2863 cf_read_error_message(err, err_info), cf->filename);
2868 /* Does it match the search criterion? */
2869 if ((*match_function)(cf, fdata, criterion)) {
2871 break; /* found it! */
2875 if (fdata == start_fd) {
2876 /* We're back to the frame we were on originally, and that frame
2877 doesn't match the search filter. The search failed. */
2882 /* We're done scanning the packets; destroy the progress bar if it
2884 if (progbar != NULL)
2885 destroy_progress_dlg(progbar);
2888 if (new_fd != NULL) {
2889 /* We found a frame. Find what row it's in. */
2890 row = packet_list_find_row_from_data(new_fd);
2891 g_assert(row != -1);
2893 /* Select that row, make it the focus row, and make it visible. */
2894 packet_list_set_selected_row(row);
2895 return TRUE; /* success */
2897 return FALSE; /* failure */
2901 cf_goto_frame(capture_file *cf, guint fnumber)
2906 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
2909 if (fdata == NULL) {
2910 /* we didn't find a packet with that packet number */
2911 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2912 "There is no packet with the packet number %u.", fnumber);
2913 return FALSE; /* we failed to go to that packet */
2915 if (!fdata->flags.passed_dfilter) {
2916 /* that packet currently isn't displayed */
2917 /* XXX - add it to the set of displayed packets? */
2918 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2919 "The packet number %u isn't currently being displayed.", fnumber);
2920 return FALSE; /* we failed to go to that packet */
2923 /* We found that packet, and it's currently being displayed.
2924 Find what row it's in. */
2925 row = packet_list_find_row_from_data(fdata);
2926 g_assert(row != -1);
2928 /* Select that row, make it the focus row, and make it visible. */
2929 packet_list_set_selected_row(row);
2930 return TRUE; /* we got to that packet */
2934 cf_goto_top_frame(capture_file *cf)
2938 frame_data *lowest_fdata = NULL;
2940 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2941 if (fdata->flags.passed_dfilter) {
2942 lowest_fdata = fdata;
2947 if (lowest_fdata == NULL) {
2951 /* We found that packet, and it's currently being displayed.
2952 Find what row it's in. */
2953 row = packet_list_find_row_from_data(lowest_fdata);
2954 g_assert(row != -1);
2956 /* Select that row, make it the focus row, and make it visible. */
2957 packet_list_set_selected_row(row);
2958 return TRUE; /* we got to that packet */
2962 cf_goto_bottom_frame(capture_file *cf)
2966 frame_data *highest_fdata = NULL;
2968 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2969 if (fdata->flags.passed_dfilter) {
2970 highest_fdata = fdata;
2974 if (highest_fdata == NULL) {
2978 /* We found that packet, and it's currently being displayed.
2979 Find what row it's in. */
2980 row = packet_list_find_row_from_data(highest_fdata);
2981 g_assert(row != -1);
2983 /* Select that row, make it the focus row, and make it visible. */
2984 packet_list_set_selected_row(row);
2985 return TRUE; /* we got to that packet */
2989 * Go to frame specified by currently selected protocol tree item.
2992 cf_goto_framenum(capture_file *cf)
2994 header_field_info *hfinfo;
2997 if (cf->finfo_selected) {
2998 hfinfo = cf->finfo_selected->hfinfo;
3000 if (hfinfo->type == FT_FRAMENUM) {
3001 framenum = fvalue_get_integer(&cf->finfo_selected->value);
3003 return cf_goto_frame(cf, framenum);
3010 /* Select the packet on a given row. */
3012 cf_select_packet(capture_file *cf, int row)
3018 /* Get the frame data struct pointer for this frame */
3019 fdata = (frame_data *)packet_list_get_row_data(row);
3021 if (fdata == NULL) {
3022 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3023 the first entry is added to it by "real_insert_row()", that row
3024 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
3025 our version and the vanilla GTK+ version).
3027 This means that a "select-row" signal is emitted; this causes
3028 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3031 "cf_select_packet()" fetches, above, the data associated with the
3032 row that was selected; however, as "gtk_clist_append()", which
3033 called "real_insert_row()", hasn't yet returned, we haven't yet
3034 associated any data with that row, so we get back a null pointer.
3036 We can't assume that there's only one frame in the frame list,
3037 either, as we may be filtering the display.
3039 We therefore assume that, if "row" is 0, i.e. the first row
3040 is being selected, and "cf->first_displayed" equals
3041 "cf->last_displayed", i.e. there's only one frame being
3042 displayed, that frame is the frame we want.
3044 This means we have to set "cf->first_displayed" and
3045 "cf->last_displayed" before adding the row to the
3046 GtkCList; see the comment in "add_packet_to_packet_list()". */
3048 if (row == 0 && cf->first_displayed == cf->last_displayed)
3049 fdata = cf->first_displayed;
3052 /* If fdata _still_ isn't set simply give up. */
3053 if (fdata == NULL) {
3057 /* Get the data in that frame. */
3058 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
3059 cf->pd, fdata->cap_len, &err, &err_info)) {
3060 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3061 cf_read_error_message(err, err_info), cf->filename);
3065 /* Record that this frame is the current frame. */
3066 cf->current_frame = fdata;
3068 /* Create the logical protocol tree. */
3069 if (cf->edt != NULL) {
3070 epan_dissect_free(cf->edt);
3073 /* We don't need the columns here. */
3074 cf->edt = epan_dissect_new(TRUE, TRUE);
3076 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3079 cf_callback_invoke(cf_cb_packet_selected, cf);
3082 /* Unselect the selected packet, if any. */
3084 cf_unselect_packet(capture_file *cf)
3086 /* Destroy the epan_dissect_t for the unselected packet. */
3087 if (cf->edt != NULL) {
3088 epan_dissect_free(cf->edt);
3092 /* No packet is selected. */
3093 cf->current_frame = NULL;
3095 cf_callback_invoke(cf_cb_packet_unselected, cf);
3097 /* No protocol tree means no selected field. */
3098 cf_unselect_field(cf);
3101 /* Unset the selected protocol tree field, if any. */
3103 cf_unselect_field(capture_file *cf)
3105 cf->finfo_selected = NULL;
3107 cf_callback_invoke(cf_cb_field_unselected, cf);
3111 * Mark a particular frame.
3114 cf_mark_frame(capture_file *cf, frame_data *frame)
3116 if (! frame->flags.marked) {
3117 frame->flags.marked = TRUE;
3118 if (cf->count > cf->marked_count)
3124 * Unmark a particular frame.
3127 cf_unmark_frame(capture_file *cf, frame_data *frame)
3129 if (frame->flags.marked) {
3130 frame->flags.marked = FALSE;
3131 if (cf->marked_count > 0)
3139 } save_callback_args_t;
3142 * Save a capture to a file, in a particular format, saving either
3143 * all packets, all currently-displayed packets, or all marked packets.
3145 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3146 * up a message box for the failure.
3149 save_packet(capture_file *cf _U_, frame_data *fdata,
3150 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3153 save_callback_args_t *args = argsp;
3154 struct wtap_pkthdr hdr;
3157 /* init the wtap header for saving */
3158 hdr.ts = *(struct wtap_nstime *) &fdata->abs_ts;
3159 hdr.caplen = fdata->cap_len;
3160 hdr.len = fdata->pkt_len;
3161 hdr.pkt_encap = fdata->lnk_t;
3163 /* and save the packet */
3164 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3165 cf_write_failure_alert_box(args->fname, err);
3172 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3174 gchar *from_filename;
3178 save_callback_args_t callback_args;
3180 cf_callback_invoke(cf_cb_file_safe_started, (gpointer) fname);
3182 /* don't write over an existing file. */
3183 /* this should've been already checked by our caller, just to be sure... */
3184 if (file_exists(fname)) {
3185 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3186 "%sCapture file: \"%s\" already exists!%s\n\n"
3187 "Please choose a different filename.",
3188 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3192 packet_range_process_init(range);
3195 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3196 /* We're not filtering packets, and we're saving it in the format
3197 it's already in, so we can just move or copy the raw data. */
3199 if (cf->is_tempfile) {
3200 /* The file being saved is a temporary file from a live
3201 capture, so it doesn't need to stay around under that name;
3202 first, try renaming the capture buffer file to the new name. */
3204 if (eth_rename(cf->filename, fname) == 0) {
3205 /* That succeeded - there's no need to copy the source file. */
3206 from_filename = NULL;
3209 if (errno == EXDEV) {
3210 /* They're on different file systems, so we have to copy the
3213 from_filename = cf->filename;
3215 /* The rename failed, but not because they're on different
3216 file systems - put up an error message. (Or should we
3217 just punt and try to copy? The only reason why I'd
3218 expect the rename to fail and the copy to succeed would
3219 be if we didn't have permission to remove the file from
3220 the temporary directory, and that might be fixable - but
3221 is it worth requiring the user to go off and fix it?) */
3222 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3223 file_rename_error_message(errno), fname);
3229 from_filename = cf->filename;
3232 /* It's a permanent file, so we should copy it, and not remove the
3235 from_filename = cf->filename;
3239 /* Copy the file, if we haven't moved it. */
3240 if (!copy_binary_file(from_filename, fname))
3244 /* Either we're filtering packets, or we're saving in a different
3245 format; we can't do that by copying or moving the capture file,
3246 we have to do it by writing the packets out in Wiretap. */
3247 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
3250 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3254 /* XXX - we let the user save a subset of the packets.
3256 If we do that, should we make that file the current file? If so,
3257 it means we can no longer get at the other packets. What does
3260 /* Iterate through the list of packets, processing the packets we were
3263 XXX - we've already called "packet_range_process_init(range)", but
3264 "process_specified_packets()" will do it again. Fortunately,
3265 that's harmless in this case, as we haven't done anything to
3266 "range" since we initialized it. */
3267 callback_args.pdh = pdh;
3268 callback_args.fname = fname;
3269 switch (process_specified_packets(cf, range, "Saving", "selected packets",
3270 TRUE, save_packet, &callback_args)) {
3273 /* Completed successfully. */
3277 /* The user decided to abort the saving.
3278 XXX - remove the output file? */
3282 /* Error while saving. */
3283 wtap_dump_close(pdh, &err);
3287 if (!wtap_dump_close(pdh, &err)) {
3288 cf_close_failure_alert_box(fname, err);
3293 cf_callback_invoke(cf_cb_file_safe_finished, NULL);
3295 if (packet_range_process_all(range)) {
3296 /* We saved the entire capture, not just some packets from it.
3297 Open and read the file we saved it to.
3299 XXX - this is somewhat of a waste; we already have the
3300 packets, all this gets us is updated file type information
3301 (which we could just stuff into "cf"), and having the new
3302 file be the one we have opened and from which we're reading
3303 the data, and it means we have to spend time opening and
3304 reading the file, which could be a significant amount of
3305 time if the file is large. */
3306 cf->user_saved = TRUE;
3308 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3309 /* XXX - report errors if this fails?
3310 What should we return if it fails or is aborted? */
3311 switch (cf_read(cf)) {
3315 /* Just because we got an error, that doesn't mean we were unable
3316 to read any of the file; we handle what we could get from the
3320 case CF_READ_ABORTED:
3321 /* The user bailed out of re-reading the capture file; the
3322 capture file has been closed - just return (without
3323 changing any menu settings; "cf_close()" set them
3324 correctly for the "no capture file open" state). */
3327 cf_callback_invoke(cf_cb_file_safe_reload_finished, NULL);
3333 cf_callback_invoke(cf_cb_file_safe_failed, NULL);
3338 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3339 gboolean for_writing, int file_type)
3342 /* Wiretap error. */
3345 case WTAP_ERR_NOT_REGULAR_FILE:
3346 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3347 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3351 case WTAP_ERR_RANDOM_OPEN_PIPE:
3352 /* Seen only when opening a capture file for reading. */
3353 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3354 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
3358 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3359 /* Seen only when opening a capture file for reading. */
3360 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3361 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
3365 case WTAP_ERR_UNSUPPORTED:
3366 /* Seen only when opening a capture file for reading. */
3367 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3368 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
3370 filename, err_info);
3374 case WTAP_ERR_CANT_WRITE_TO_PIPE:
3375 /* Seen only when opening a capture file for writing. */
3376 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3377 "The file \"%s\" is a pipe, and %s capture files can't be "
3378 "written to a pipe.",
3379 filename, wtap_file_type_string(file_type));
3382 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3383 /* Seen only when opening a capture file for writing. */
3384 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3385 "Wireshark doesn't support writing capture files in that format.");
3388 case WTAP_ERR_UNSUPPORTED_ENCAP:
3390 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3391 "Wireshark can't save this capture in that format.");
3393 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3394 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
3396 filename, err_info);
3401 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3403 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3404 "Wireshark can't save this capture in that format.");
3406 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3407 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
3412 case WTAP_ERR_BAD_RECORD:
3413 /* Seen only when opening a capture file for reading. */
3414 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3415 "The file \"%s\" appears to be damaged or corrupt.\n"
3417 filename, err_info);
3421 case WTAP_ERR_CANT_OPEN:
3423 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3424 "The file \"%s\" could not be created for some unknown reason.",
3427 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3428 "The file \"%s\" could not be opened for some unknown reason.",
3433 case WTAP_ERR_SHORT_READ:
3434 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3435 "The file \"%s\" appears to have been cut short"
3436 " in the middle of a packet or other data.",
3440 case WTAP_ERR_SHORT_WRITE:
3441 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3442 "A full header couldn't be written to the file \"%s\".",
3446 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
3447 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3448 "Gzip compression not supported by this file type.");
3452 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3453 "The file \"%s\" could not be %s: %s.",
3455 for_writing ? "created" : "opened",
3456 wtap_strerror(err));
3461 open_failure_alert_box(filename, err, for_writing);
3466 file_rename_error_message(int err)
3469 static char errmsg_errno[1024+1];
3474 errmsg = "The path to the file \"%s\" doesn't exist.";
3478 errmsg = "You don't have permission to move the capture file to \"%s\".";
3482 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3483 "The file \"%%s\" could not be moved: %s.",
3484 wtap_strerror(err));
3485 errmsg = errmsg_errno;
3492 cf_read_error_message(int err, const gchar *err_info)
3494 static char errmsg_errno[1024+1];
3498 case WTAP_ERR_UNSUPPORTED_ENCAP:
3499 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3500 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
3504 case WTAP_ERR_BAD_RECORD:
3505 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3506 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
3507 wtap_strerror(err), err_info);
3511 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3512 "An error occurred while reading from the file \"%%s\": %s.",
3513 wtap_strerror(err));
3516 return errmsg_errno;
3520 cf_write_failure_alert_box(const char *filename, int err)
3523 /* Wiretap error. */
3524 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3525 "An error occurred while writing to the file \"%s\": %s.",
3526 filename, wtap_strerror(err));
3529 write_failure_alert_box(filename, err);
3533 /* Check for write errors - if the file is being written to an NFS server,
3534 a write error may not show up until the file is closed, as NFS clients
3535 might not send writes to the server until the "write()" call finishes,
3536 so that the write may fail on the server but the "write()" may succeed. */
3538 cf_close_failure_alert_box(const char *filename, int err)
3541 /* Wiretap error. */
3544 case WTAP_ERR_CANT_CLOSE:
3545 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3546 "The file \"%s\" couldn't be closed for some unknown reason.",
3550 case WTAP_ERR_SHORT_WRITE:
3551 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3552 "Not all the packets could be written to the file \"%s\".",
3557 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3558 "An error occurred while closing the file \"%s\": %s.",
3559 filename, wtap_strerror(err));
3564 We assume that a close error from the OS is really a write error. */
3565 write_failure_alert_box(filename, err);
3569 /* Reload the current capture file. */
3571 cf_reload(capture_file *cf) {
3573 gboolean is_tempfile;
3576 /* If the file could be opened, "cf_open()" calls "cf_close()"
3577 to get rid of state for the old capture file before filling in state
3578 for the new capture file. "cf_close()" will remove the file if
3579 it's a temporary file; we don't want that to happen (for one thing,
3580 it'd prevent subsequent reopens from working). Remember whether it's
3581 a temporary file, mark it as not being a temporary file, and then
3582 reopen it as the type of file it was.
3584 Also, "cf_close()" will free "cf->filename", so we must make
3585 a copy of it first. */
3586 filename = g_strdup(cf->filename);
3587 is_tempfile = cf->is_tempfile;
3588 cf->is_tempfile = FALSE;
3589 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
3590 switch (cf_read(cf)) {
3594 /* Just because we got an error, that doesn't mean we were unable
3595 to read any of the file; we handle what we could get from the
3599 case CF_READ_ABORTED:
3600 /* The user bailed out of re-reading the capture file; the
3601 capture file has been closed - just free the capture file name
3602 string and return (without changing the last containing
3608 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
3609 Instead, the file was left open, so we should restore "cf->is_tempfile"
3612 XXX - change the menu? Presumably "cf_open()" will do that;
3613 make sure it does! */
3614 cf->is_tempfile = is_tempfile;
3616 /* "cf_open()" made a copy of the file name we handed it, so
3617 we should free up our copy. */
3621 /* Copies a file in binary mode, for those operating systems that care about
3623 * Returns TRUE on success, FALSE on failure. If a failure, it also
3624 * displays a simple dialog window with the error message.
3627 copy_binary_file(const char *from_filename, const char *to_filename)
3629 int from_fd, to_fd, nread, nwritten, err;
3632 /* Copy the raw bytes of the file. */
3633 from_fd = eth_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
3635 open_failure_alert_box(from_filename, errno, FALSE);
3639 /* Use open() instead of creat() so that we can pass the O_BINARY
3640 flag, which is relevant on Win32; it appears that "creat()"
3641 may open the file in text mode, not binary mode, but we want
3642 to copy the raw bytes of the file, so we need the output file
3643 to be open in binary mode. */
3644 to_fd = eth_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
3646 open_failure_alert_box(to_filename, errno, TRUE);
3651 while ((nread = eth_read(from_fd, pd, sizeof pd)) > 0) {
3652 nwritten = eth_write(to_fd, pd, nread);
3653 if (nwritten < nread) {
3657 err = WTAP_ERR_SHORT_WRITE;
3658 write_failure_alert_box(to_filename, err);
3666 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3667 "An error occurred while reading from the file \"%s\": %s.",
3668 from_filename, strerror(err));
3674 if (eth_close(to_fd) < 0) {
3675 write_failure_alert_box(to_filename, errno);