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) {
352 cleanup_dissection();
355 cf_callback_invoke(cf_cb_file_closed, cf);
359 cf_read(capture_file *cf)
363 const gchar *name_ptr;
365 char errmsg_errno[1024+1];
366 gchar err_str[2048+1];
368 progdlg_t *progbar = NULL;
370 gint64 size, file_pos;
373 gchar status_str[100];
374 gint64 progbar_nextstep;
375 gint64 progbar_quantum;
379 reset_tap_listeners();
380 tap_dfilter_dlg_update();
382 cf_callback_invoke(cf_cb_file_read_start, cf);
384 name_ptr = get_basename(cf->filename);
386 /* Find the size of the file. */
387 size = wtap_file_size(cf->wth, NULL);
389 /* Update the progress bar when it gets to this value. */
390 progbar_nextstep = 0;
391 /* When we reach the value that triggers a progress bar update,
392 bump that value by this amount. */
394 progbar_quantum = size/N_PROGBAR_UPDATES;
397 /* Progress so far. */
400 packet_list_freeze();
403 g_get_current_time(&start_time);
405 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
407 /* Create the progress bar if necessary.
408 We check on every iteration of the loop, so that it takes no
409 longer than the standard time to create it (otherwise, for a
410 large file, we might take considerably longer than that standard
411 time in order to get to the next progress bar step). */
412 if (progbar == NULL) {
413 progbar = delayed_create_progress_dlg("Loading", name_ptr,
414 TRUE, &stop_flag, &start_time, progbar_val);
417 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
418 when we update it, we have to run the GTK+ main loop to get it
419 to repaint what's pending, and doing so may involve an "ioctl()"
420 to see if there's any pending input from an X server, and doing
421 that for every packet can be costly, especially on a big file. */
422 if (data_offset >= progbar_nextstep) {
423 file_pos = wtap_read_so_far(cf->wth, NULL);
424 progbar_val = (gfloat) file_pos / (gfloat) size;
425 if (progbar_val > 1.0) {
426 /* The file probably grew while we were reading it.
427 Update file size, and try again. */
428 size = wtap_file_size(cf->wth, NULL);
430 progbar_val = (gfloat) file_pos / (gfloat) size;
431 /* If it's still > 1, either "wtap_file_size()" failed (in which
432 case there's not much we can do about it), or the file
433 *shrank* (in which case there's not much we can do about
434 it); just clip the progress value at 1.0. */
435 if (progbar_val > 1.0)
438 if (progbar != NULL) {
439 g_snprintf(status_str, sizeof(status_str),
440 "%" PRId64 "KB of %" PRId64 "KB",
441 file_pos / 1024, size / 1024);
442 update_progress_dlg(progbar, progbar_val, status_str);
444 progbar_nextstep += progbar_quantum;
449 /* Well, the user decided to abort the read. He/She will be warned and
450 it might be enough for him/her to work with the already loaded
452 This is especially true for very large capture files, where you don't
453 want to wait loading the whole file (which may last minutes or even
454 hours even on fast machines) just to see that it was the wrong file. */
457 read_packet(cf, data_offset);
460 /* We're done reading the file; destroy the progress bar if it was created. */
462 destroy_progress_dlg(progbar);
464 /* We're done reading sequentially through the file. */
465 cf->state = FILE_READ_DONE;
467 /* Close the sequential I/O side, to free up memory it requires. */
468 wtap_sequential_close(cf->wth);
470 /* Allow the protocol dissectors to free up memory that they
471 * don't need after the sequential run-through of the packets. */
472 postseq_cleanup_all_protocols();
474 /* Set the file encapsulation type now; we don't know what it is until
475 we've looked at all the packets, as we don't know until then whether
476 there's more than one type (and thus whether it's
477 WTAP_ENCAP_PER_PACKET). */
478 cf->lnk_t = wtap_file_encap(cf->wth);
480 cf->current_frame = cf->first_displayed;
483 cf_callback_invoke(cf_cb_file_read_finished, cf);
485 /* If we have any displayed packets to select, select the first of those
486 packets by making the first row the selected row. */
487 if (cf->first_displayed != NULL)
488 packet_list_select_row(0);
491 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
492 "%sFile loading was cancelled!%s\n"
494 "The remaining packets in the file were discarded.\n"
496 "As a lot of packets from the original file will be missing,\n"
497 "remember to be careful when saving the current content to a file.\n",
498 simple_dialog_primary_start(), simple_dialog_primary_end());
499 return CF_READ_ERROR;
503 /* Put up a message box noting that the read failed somewhere along
504 the line. Don't throw out the stuff we managed to read, though,
508 case WTAP_ERR_UNSUPPORTED_ENCAP:
509 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
510 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
513 errmsg = errmsg_errno;
516 case WTAP_ERR_CANT_READ:
517 errmsg = "An attempt to read from the capture file failed for"
518 " some unknown reason.";
521 case WTAP_ERR_SHORT_READ:
522 errmsg = "The capture file appears to have been cut short"
523 " in the middle of a packet.";
526 case WTAP_ERR_BAD_RECORD:
527 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
528 "The capture file appears to be damaged or corrupt.\n(%s)",
531 errmsg = errmsg_errno;
535 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
536 "An error occurred while reading the"
537 " capture file: %s.", wtap_strerror(err));
538 errmsg = errmsg_errno;
541 g_snprintf(err_str, sizeof err_str, errmsg);
542 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
543 return CF_READ_ERROR;
550 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
552 cf_status_t cf_status;
554 cf_status = cf_open(cf, fname, is_tempfile, err);
559 cf_continue_tail(capture_file *cf, int to_read, int *err)
561 long data_offset = 0;
566 packet_list_freeze();
568 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
570 while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
571 if (cf->state == FILE_READ_ABORTED) {
572 /* Well, the user decided to exit Wireshark. Break out of the
573 loop, and let the code below (which is called even if there
574 aren't any packets left to read) exit. */
577 read_packet(cf, data_offset);
581 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
582 cf->count, cf->state, *err);*/
584 /* XXX - this cheats and looks inside the packet list to find the final
586 if (auto_scroll_live && cf->plist_end != NULL)
587 packet_list_moveto_end();
591 if (cf->state == FILE_READ_ABORTED) {
592 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
593 so that our caller can kill off the capture child process;
594 this will cause an EOF on the pipe from the child, so
595 "cf_finish_tail()" will be called, and it will clean up
597 return CF_READ_ABORTED;
598 } else if (*err != 0) {
599 /* We got an error reading the capture file.
600 XXX - pop up a dialog box instead? */
601 g_warning("Error \"%s\" while reading: \"%s\"\n",
602 wtap_strerror(*err), cf->filename);
604 return CF_READ_ERROR;
610 cf_finish_tail(capture_file *cf, int *err)
615 if(cf->wth == NULL) {
617 return CF_READ_ERROR;
620 packet_list_freeze();
622 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
623 if (cf->state == FILE_READ_ABORTED) {
624 /* Well, the user decided to abort the read. Break out of the
625 loop, and let the code below (which is called even if there
626 aren't any packets left to read) exit. */
629 read_packet(cf, data_offset);
634 if (cf->state == FILE_READ_ABORTED) {
635 /* Well, the user decided to abort the read. We're only called
636 when the child capture process closes the pipe to us (meaning
637 it's probably exited), so we can just close the capture
638 file; we return CF_READ_ABORTED so our caller can do whatever
639 is appropriate when that happens. */
641 return CF_READ_ABORTED;
644 if (auto_scroll_live && cf->plist_end != NULL)
645 /* XXX - this cheats and looks inside the packet list to find the final
647 packet_list_moveto_end();
649 /* We're done reading sequentially through the file. */
650 cf->state = FILE_READ_DONE;
652 /* We're done reading sequentially through the file; close the
653 sequential I/O side, to free up memory it requires. */
654 wtap_sequential_close(cf->wth);
656 /* Allow the protocol dissectors to free up memory that they
657 * don't need after the sequential run-through of the packets. */
658 postseq_cleanup_all_protocols();
660 /* Set the file encapsulation type now; we don't know what it is until
661 we've looked at all the packets, as we don't know until then whether
662 there's more than one type (and thus whether it's
663 WTAP_ENCAP_PER_PACKET). */
664 cf->lnk_t = wtap_file_encap(cf->wth);
667 /* We got an error reading the capture file.
668 XXX - pop up a dialog box? */
669 return CF_READ_ERROR;
674 #endif /* HAVE_LIBPCAP */
677 cf_get_display_name(capture_file *cf)
679 const gchar *displayname;
681 /* Return a name to use in displays */
682 if (!cf->is_tempfile) {
683 /* Get the last component of the file name, and use that. */
685 displayname = get_basename(cf->filename);
687 displayname="(No file)";
690 /* The file we read is a temporary file from a live capture;
691 we don't mention its name. */
692 displayname = "(Untitled)";
697 /* XXX - use a macro instead? */
699 cf_get_packet_count(capture_file *cf)
704 /* XXX - use a macro instead? */
706 cf_set_packet_count(capture_file *cf, int packet_count)
708 cf->count = packet_count;
711 /* XXX - use a macro instead? */
713 cf_is_tempfile(capture_file *cf)
715 return cf->is_tempfile;
718 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
720 cf->is_tempfile = is_tempfile;
724 /* XXX - use a macro instead? */
725 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
727 cf->drops_known = drops_known;
730 /* XXX - use a macro instead? */
731 void cf_set_drops(capture_file *cf, guint32 drops)
736 /* XXX - use a macro instead? */
737 gboolean cf_get_drops_known(capture_file *cf)
739 return cf->drops_known;
742 /* XXX - use a macro instead? */
743 guint32 cf_get_drops(capture_file *cf)
748 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
754 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
755 union wtap_pseudo_header *pseudo_header, const guchar *buf,
759 gboolean create_proto_tree = FALSE;
762 /* just add some value here until we know if it is being displayed or not */
763 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
765 /* If we don't have the time stamp of the first packet in the
766 capture, it's because this is the first packet. Save the time
767 stamp of this packet as the time stamp of the first packet. */
768 if (nstime_is_zero(&first_ts)) {
769 first_ts = fdata->abs_ts;
771 /* if this frames is marked as a reference time frame, reset
772 firstsec and firstusec to this frame */
773 if(fdata->flags.ref_time){
774 first_ts = fdata->abs_ts;
777 /* If we don't have the time stamp of the previous displayed packet,
778 it's because this is the first displayed packet. Save the time
779 stamp of this packet as the time stamp of the previous displayed
781 if (nstime_is_zero(&prev_ts)) {
782 prev_ts = fdata->abs_ts;
785 /* Get the time elapsed between the first packet and this packet. */
786 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
788 /* If it's greater than the current elapsed time, set the elapsed time
789 to it (we check for "greater than" so as not to be confused by
790 time moving backwards). */
791 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
792 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
793 cf->elapsed_time = fdata->rel_ts;
796 /* Get the time elapsed between the previous displayed packet and
798 nstime_delta(&fdata->del_ts, &fdata->abs_ts, &prev_ts);
802 we have a display filter and are re-applying it;
804 we have a list of color filters;
806 we have tap listeners;
808 allocate a protocol tree root node, so that we'll construct
809 a protocol tree against which a filter expression can be
811 if ((cf->dfcode != NULL && refilter) || color_filters_used()
812 || num_tap_filters != 0)
813 create_proto_tree = TRUE;
815 /* Dissect the frame. */
816 edt = epan_dissect_new(create_proto_tree, FALSE);
818 if (cf->dfcode != NULL && refilter) {
819 epan_dissect_prime_dfilter(edt, cf->dfcode);
821 if (color_filters_used()) {
822 color_filters_prime_edt(edt);
825 epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
826 tap_push_tapped_queue(edt);
828 /* If we have a display filter, apply it if we're refiltering, otherwise
829 leave the "passed_dfilter" flag alone.
831 If we don't have a display filter, set "passed_dfilter" to 1. */
832 if (cf->dfcode != NULL) {
834 fdata->flags.passed_dfilter = dfilter_apply_edt(cf->dfcode, edt) ? 1 : 0;
837 fdata->flags.passed_dfilter = 1;
839 if( (fdata->flags.passed_dfilter)
840 || (edt->pi.fd->flags.ref_time) ){
841 /* This frame either passed the display filter list or is marked as
842 a time reference frame. All time reference frames are displayed
843 even if they dont pass the display filter */
844 /* if this was a TIME REF frame we should reset the cul bytes field */
845 if(edt->pi.fd->flags.ref_time){
846 cum_bytes = fdata->pkt_len;
847 fdata->cum_bytes = cum_bytes;
850 /* increase cum_bytes with this packets length */
851 cum_bytes += fdata->pkt_len;
853 epan_dissect_fill_in_columns(edt);
855 /* If we haven't yet seen the first frame, this is it.
857 XXX - we must do this before we add the row to the display,
858 as, if the display's GtkCList's selection mode is
859 GTK_SELECTION_BROWSE, when the first entry is added to it,
860 "cf_select_packet()" will be called, and it will fetch the row
861 data for the 0th row, and will get a null pointer rather than
862 "fdata", as "gtk_clist_append()" won't yet have returned and
863 thus "gtk_clist_set_row_data()" won't yet have been called.
865 We thus need to leave behind bread crumbs so that
866 "cf_select_packet()" can find this frame. See the comment
867 in "cf_select_packet()". */
868 if (cf->first_displayed == NULL)
869 cf->first_displayed = fdata;
871 /* This is the last frame we've seen so far. */
872 cf->last_displayed = fdata;
874 row = packet_list_append(cf->cinfo.col_data, fdata);
876 /* colorize packet: if packet is marked, use preferences,
877 otherwise try to apply color filters */
878 if (fdata->flags.marked) {
879 fdata->color_filter = NULL;
880 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
882 fdata->color_filter = color_filters_colorize_packet(row, edt);
885 /* Set the time of the previous displayed frame to the time of this
887 prev_ts = fdata->abs_ts;
889 cf->displayed_count++;
891 /* This frame didn't pass the display filter, so it's not being added
892 to the clist, and thus has no row. */
895 epan_dissect_free(edt);
900 read_packet(capture_file *cf, long offset)
902 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
903 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
904 const guchar *buf = wtap_buf_ptr(cf->wth);
907 frame_data *plist_end;
910 /* Allocate the next list entry, and add it to the list. */
911 fdata = g_mem_chunk_alloc(cf->plist_chunk);
917 fdata->pkt_len = phdr->len;
918 fdata->cap_len = phdr->caplen;
919 fdata->file_off = offset;
920 fdata->lnk_t = phdr->pkt_encap;
921 fdata->flags.encoding = CHAR_ASCII;
922 fdata->flags.visited = 0;
923 fdata->flags.marked = 0;
924 fdata->flags.ref_time = 0;
925 fdata->color_filter = NULL;
927 fdata->abs_ts = *((nstime_t *) &phdr->ts);
931 edt = epan_dissect_new(TRUE, FALSE);
932 epan_dissect_prime_dfilter(edt, cf->rfcode);
933 epan_dissect_run(edt, pseudo_header, buf, fdata, NULL);
934 passed = dfilter_apply_edt(cf->rfcode, edt);
935 epan_dissect_free(edt);
938 plist_end = cf->plist_end;
939 fdata->prev = plist_end;
940 if (plist_end != NULL)
941 plist_end->next = fdata;
944 cf->plist_end = fdata;
947 cf->f_datalen = offset + phdr->caplen;
948 fdata->num = cf->count;
949 add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE);
951 /* XXX - if we didn't have read filters, or if we could avoid
952 allocating the "frame_data" structure until we knew whether
953 the frame passed the read filter, we could use a G_ALLOC_ONLY
956 ...but, at least in one test I did, where I just made the chunk
957 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
958 seem to save a noticeable amount of time or space. */
959 g_mem_chunk_free(cf->plist_chunk, fdata);
964 cf_merge_files(char **out_filenamep, int in_file_count,
965 char *const *in_filenames, int file_type, gboolean do_append)
967 merge_in_file_t *in_files;
973 int open_err, read_err, write_err, close_err;
977 char errmsg_errno[1024+1];
978 gchar err_str[2048+1];
980 gboolean got_read_error = FALSE, got_write_error = FALSE;
982 progdlg_t *progbar = NULL;
984 gint64 f_len, file_pos;
987 gchar status_str[100];
988 gint64 progbar_nextstep;
989 gint64 progbar_quantum;
991 /* open the input files */
992 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
993 &open_err, &err_info, &err_fileno)) {
995 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1000 if (*out_filenamep != NULL) {
1001 out_filename = *out_filenamep;
1002 out_fd = eth_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1006 out_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
1009 out_filename = g_strdup(tmpname);
1010 *out_filenamep = out_filename;
1014 merge_close_in_files(in_file_count, in_files);
1016 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1020 pdh = wtap_dump_fdopen(out_fd, file_type,
1021 merge_select_frame_type(in_file_count, in_files),
1022 merge_max_snapshot_length(in_file_count, in_files),
1023 FALSE /* compressed */, &open_err);
1026 merge_close_in_files(in_file_count, in_files);
1028 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1033 /* Get the sum of the sizes of all the files. */
1035 for (i = 0; i < in_file_count; i++)
1036 f_len += in_files[i].size;
1038 /* Update the progress bar when it gets to this value. */
1039 progbar_nextstep = 0;
1040 /* When we reach the value that triggers a progress bar update,
1041 bump that value by this amount. */
1042 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1043 /* Progress so far. */
1047 g_get_current_time(&start_time);
1049 /* do the merge (or append) */
1052 wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1055 wth = merge_read_packet(in_file_count, in_files, &read_err,
1059 got_read_error = TRUE;
1063 /* Get the sum of the data offsets in all of the files. */
1065 for (i = 0; i < in_file_count; i++)
1066 data_offset += in_files[i].data_offset;
1068 /* Create the progress bar if necessary.
1069 We check on every iteration of the loop, so that it takes no
1070 longer than the standard time to create it (otherwise, for a
1071 large file, we might take considerably longer than that standard
1072 time in order to get to the next progress bar step). */
1073 if (progbar == NULL) {
1074 progbar = delayed_create_progress_dlg("Merging", "files",
1075 FALSE, &stop_flag, &start_time, progbar_val);
1078 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1079 when we update it, we have to run the GTK+ main loop to get it
1080 to repaint what's pending, and doing so may involve an "ioctl()"
1081 to see if there's any pending input from an X server, and doing
1082 that for every packet can be costly, especially on a big file. */
1083 if (data_offset >= progbar_nextstep) {
1084 /* Get the sum of the seek positions in all of the files. */
1086 for (i = 0; i < in_file_count; i++)
1087 file_pos += wtap_read_so_far(in_files[i].wth, NULL);
1088 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1089 if (progbar_val > 1.0) {
1090 /* Some file probably grew while we were reading it.
1091 That "shouldn't happen", so we'll just clip the progress
1095 if (progbar != NULL) {
1096 g_snprintf(status_str, sizeof(status_str),
1097 "%" PRId64 "KB of %" PRId64 "KB",
1098 file_pos / 1024, f_len / 1024);
1099 update_progress_dlg(progbar, progbar_val, status_str);
1101 progbar_nextstep += progbar_quantum;
1105 /* Well, the user decided to abort the merge. */
1109 if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1110 wtap_buf_ptr(wth), &write_err)) {
1111 got_write_error = TRUE;
1116 /* We're done merging the files; destroy the progress bar if it was created. */
1117 if (progbar != NULL)
1118 destroy_progress_dlg(progbar);
1120 merge_close_in_files(in_file_count, in_files);
1121 if (!got_read_error && !got_write_error) {
1122 if (!wtap_dump_close(pdh, &write_err))
1123 got_write_error = TRUE;
1125 wtap_dump_close(pdh, &close_err);
1127 if (got_read_error) {
1129 * Find the file on which we got the error, and report the error.
1131 for (i = 0; i < in_file_count; i++) {
1132 if (in_files[i].state == GOT_ERROR) {
1133 /* Put up a message box noting that a read failed somewhere along
1137 case WTAP_ERR_UNSUPPORTED_ENCAP:
1138 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1139 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1142 errmsg = errmsg_errno;
1145 case WTAP_ERR_CANT_READ:
1146 errmsg = "An attempt to read from the capture file %s failed for"
1147 " some unknown reason.";
1150 case WTAP_ERR_SHORT_READ:
1151 errmsg = "The capture file %s appears to have been cut short"
1152 " in the middle of a packet.";
1155 case WTAP_ERR_BAD_RECORD:
1156 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1157 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1160 errmsg = errmsg_errno;
1164 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1165 "An error occurred while reading the"
1166 " capture file %%s: %s.", wtap_strerror(read_err));
1167 errmsg = errmsg_errno;
1170 g_snprintf(err_str, sizeof err_str, errmsg, in_files[i].filename);
1171 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
1176 if (got_write_error) {
1177 /* Put up an alert box for the write error. */
1178 cf_write_failure_alert_box(out_filename, write_err);
1181 if (got_read_error || got_write_error || stop_flag) {
1182 /* Callers aren't expected to treat an error or an explicit abort
1183 differently - we put up error dialogs ourselves, so they don't
1191 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1194 const char *filter_new = dftext ? dftext : "";
1195 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1197 /* if new filter equals old one, do nothing unless told to do so */
1198 if (!force && strcmp(filter_new, filter_old) == 0) {
1202 if (dftext == NULL) {
1203 /* The new filter is an empty filter (i.e., display all packets). */
1207 * We have a filter; make a copy of it (as we'll be saving it),
1208 * and try to compile it.
1210 dftext = g_strdup(dftext);
1211 if (!dfilter_compile(dftext, &dfcode)) {
1212 /* The attempt failed; report an error. */
1213 gchar *safe_dftext = simple_dialog_format_message(dftext);
1214 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1216 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1219 "The following display filter isn't a valid display filter:\n%s\n"
1220 "See the help for a description of the display filter syntax.",
1221 simple_dialog_primary_start(), safe_dfilter_error_msg,
1222 simple_dialog_primary_end(), safe_dftext);
1223 g_free(safe_dfilter_error_msg);
1224 g_free(safe_dftext);
1230 if (dfcode == NULL) {
1231 /* Yes - free the filter text, and set it to null. */
1237 /* We have a valid filter. Replace the current filter. */
1238 if (cf->dfilter != NULL)
1239 g_free(cf->dfilter);
1240 cf->dfilter = dftext;
1241 if (cf->dfcode != NULL)
1242 dfilter_free(cf->dfcode);
1243 cf->dfcode = dfcode;
1245 /* Now rescan the packet list, applying the new filter, but not
1246 throwing away information constructed on a previous pass. */
1247 if (dftext == NULL) {
1248 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1250 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1256 cf_colorize_packets(capture_file *cf)
1258 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1262 cf_reftime_packets(capture_file *cf)
1264 rescan_packets(cf, "Updating Reftime", "all packets", FALSE, FALSE);
1268 cf_redissect_packets(capture_file *cf)
1270 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1273 /* Rescan the list of packets, reconstructing the CList.
1275 "action" describes why we're doing this; it's used in the progress
1278 "action_item" describes what we're doing; it's used in the progress
1281 "refilter" is TRUE if we need to re-evaluate the filter expression.
1283 "redissect" is TRUE if we need to make the dissectors reconstruct
1284 any state information they have (because a preference that affects
1285 some dissector has changed, meaning some dissector might construct
1286 its state differently from the way it was constructed the last time). */
1288 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1289 gboolean refilter, gboolean redissect)
1292 progdlg_t *progbar = NULL;
1297 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1298 int selected_row, prev_row, preceding_row, following_row;
1299 gboolean selected_frame_seen;
1302 GTimeVal start_time;
1303 gchar status_str[100];
1304 int progbar_nextstep;
1305 int progbar_quantum;
1308 reset_tap_listeners();
1309 /* Which frame, if any, is the currently selected frame?
1310 XXX - should the selected frame or the focus frame be the "current"
1311 frame, that frame being the one from which "Find Frame" searches
1313 selected_frame = cf->current_frame;
1315 /* We don't yet know what row that frame will be on, if any, after we
1316 rebuild the clist, however. */
1320 /* We need to re-initialize all the state information that protocols
1321 keep, because some preference that controls a dissector has changed,
1322 which might cause the state information to be constructed differently
1323 by that dissector. */
1325 /* Initialize all data structures used for dissection. */
1329 /* Freeze the packet list while we redo it, so we don't get any
1330 screen updates while it happens. */
1331 packet_list_freeze();
1334 packet_list_clear();
1336 /* We don't yet know which will be the first and last frames displayed. */
1337 cf->first_displayed = NULL;
1338 cf->last_displayed = NULL;
1340 /* We currently don't display any packets */
1341 cf->displayed_count = 0;
1343 /* Iterate through the list of frames. Call a routine for each frame
1344 to check whether it should be displayed and, if so, add it to
1345 the display list. */
1346 nstime_set_zero(&first_ts);
1347 nstime_set_zero(&prev_ts);
1349 /* Update the progress bar when it gets to this value. */
1350 progbar_nextstep = 0;
1351 /* When we reach the value that triggers a progress bar update,
1352 bump that value by this amount. */
1353 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1354 /* Count of packets at which we've looked. */
1356 /* Progress so far. */
1360 g_get_current_time(&start_time);
1362 row = -1; /* no previous row yet */
1367 preceding_frame = NULL;
1369 following_frame = NULL;
1371 selected_frame_seen = FALSE;
1373 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1374 /* Create the progress bar if necessary.
1375 We check on every iteration of the loop, so that it takes no
1376 longer than the standard time to create it (otherwise, for a
1377 large file, we might take considerably longer than that standard
1378 time in order to get to the next progress bar step). */
1379 if (progbar == NULL)
1380 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1381 &stop_flag, &start_time,
1384 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1385 when we update it, we have to run the GTK+ main loop to get it
1386 to repaint what's pending, and doing so may involve an "ioctl()"
1387 to see if there's any pending input from an X server, and doing
1388 that for every packet can be costly, especially on a big file. */
1389 if (count >= progbar_nextstep) {
1390 /* let's not divide by zero. I should never be started
1391 * with count == 0, so let's assert that
1393 g_assert(cf->count > 0);
1394 progbar_val = (gfloat) count / cf->count;
1396 if (progbar != NULL) {
1397 g_snprintf(status_str, sizeof(status_str),
1398 "%4u of %u frames", count, cf->count);
1399 update_progress_dlg(progbar, progbar_val, status_str);
1402 progbar_nextstep += progbar_quantum;
1406 /* Well, the user decided to abort the filtering. Just stop.
1408 XXX - go back to the previous filter? Users probably just
1409 want not to wait for a filtering operation to finish;
1410 unless we cancel by having no filter, reverting to the
1411 previous filter will probably be even more expensive than
1412 continuing the filtering, as it involves going back to the
1413 beginning and filtering, and even with no filter we currently
1414 have to re-generate the entire clist, which is also expensive.
1416 I'm not sure what Network Monitor does, but it doesn't appear
1417 to give you an unfiltered display if you cancel. */
1424 /* Since all state for the frame was destroyed, mark the frame
1425 * as not visited, free the GSList referring to the state
1426 * data (the per-frame data itself was freed by
1427 * "init_dissection()"), and null out the GSList pointer. */
1428 fdata->flags.visited = 0;
1430 g_slist_free(fdata->pfd);
1435 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1436 cf->pd, fdata->cap_len, &err, &err_info)) {
1437 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1438 cf_read_error_message(err, err_info), cf->filename);
1442 /* If the previous frame is displayed, and we haven't yet seen the
1443 selected frame, remember that frame - it's the closest one we've
1444 yet seen before the selected frame. */
1445 if (prev_row != -1 && !selected_frame_seen) {
1446 preceding_row = prev_row;
1447 preceding_frame = prev_frame;
1449 row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
1452 /* If this frame is displayed, and this is the first frame we've
1453 seen displayed after the selected frame, remember this frame -
1454 it's the closest one we've yet seen at or after the selected
1456 if (row != -1 && selected_frame_seen && following_row == -1) {
1457 following_row = row;
1458 following_frame = fdata;
1460 if (fdata == selected_frame) {
1462 selected_frame_seen = TRUE;
1465 /* Remember this row/frame - it'll be the previous row/frame
1466 on the next pass through the loop. */
1472 /* Clear out what remains of the visited flags and per-frame data
1475 XXX - that may cause various forms of bogosity when dissecting
1476 these frames, as they won't have been seen by this sequential
1477 pass, but the only alternative I see is to keep scanning them
1478 even though the user requested that the scan stop, and that
1479 would leave the user stuck with an Wireshark grinding on
1480 until it finishes. Should we just stick them with that? */
1481 for (; fdata != NULL; fdata = fdata->next) {
1482 fdata->flags.visited = 0;
1484 g_slist_free(fdata->pfd);
1490 /* We're done filtering the packets; destroy the progress bar if it
1492 if (progbar != NULL)
1493 destroy_progress_dlg(progbar);
1495 /* Unfreeze the packet list. */
1498 if (selected_row == -1) {
1499 /* The selected frame didn't pass the filter. */
1500 if (selected_frame == NULL) {
1501 /* That's because there *was* no selected frame. Make the first
1502 displayed frame the current frame. */
1505 /* Find the nearest displayed frame to the selected frame (whether
1506 it's before or after that frame) and make that the current frame.
1507 If the next and previous displayed frames are equidistant from the
1508 selected frame, choose the next one. */
1509 g_assert(following_frame == NULL ||
1510 following_frame->num >= selected_frame->num);
1511 g_assert(preceding_frame == NULL ||
1512 preceding_frame->num <= selected_frame->num);
1513 if (following_frame == NULL) {
1514 /* No frame after the selected frame passed the filter, so we
1515 have to select the last displayed frame before the selected
1517 selected_row = preceding_row;
1518 } else if (preceding_frame == NULL) {
1519 /* No frame before the selected frame passed the filter, so we
1520 have to select the first displayed frame after the selected
1522 selected_row = following_row;
1527 if (selected_row == -1) {
1528 /* There are no frames displayed at all. */
1529 cf_unselect_packet(cf);
1531 /* Either the frame that was selected passed the filter, or we've
1532 found the nearest displayed frame to that frame. Select it, make
1533 it the focus row, and make it visible. */
1534 packet_list_set_selected_row(selected_row);
1545 process_specified_packets(capture_file *cf, packet_range_t *range,
1546 const char *string1, const char *string2, gboolean terminate_is_stop,
1547 gboolean (*callback)(capture_file *, frame_data *,
1548 union wtap_pseudo_header *, const guint8 *, void *),
1549 void *callback_args)
1554 union wtap_pseudo_header pseudo_header;
1555 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
1556 psp_return_t ret = PSP_FINISHED;
1558 progdlg_t *progbar = NULL;
1561 gboolean progbar_stop_flag;
1562 GTimeVal progbar_start_time;
1563 gchar progbar_status_str[100];
1564 int progbar_nextstep;
1565 int progbar_quantum;
1566 range_process_e process_this;
1568 /* Update the progress bar when it gets to this value. */
1569 progbar_nextstep = 0;
1570 /* When we reach the value that triggers a progress bar update,
1571 bump that value by this amount. */
1572 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1573 /* Count of packets at which we've looked. */
1575 /* Progress so far. */
1578 progbar_stop_flag = FALSE;
1579 g_get_current_time(&progbar_start_time);
1581 packet_range_process_init(range);
1583 /* Iterate through the list of packets, printing the packets that
1584 were selected by the current display filter. */
1585 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1586 /* Create the progress bar if necessary.
1587 We check on every iteration of the loop, so that it takes no
1588 longer than the standard time to create it (otherwise, for a
1589 large file, we might take considerably longer than that standard
1590 time in order to get to the next progress bar step). */
1591 if (progbar == NULL)
1592 progbar = delayed_create_progress_dlg(string1, string2,
1595 &progbar_start_time,
1598 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1599 when we update it, we have to run the GTK+ main loop to get it
1600 to repaint what's pending, and doing so may involve an "ioctl()"
1601 to see if there's any pending input from an X server, and doing
1602 that for every packet can be costly, especially on a big file. */
1603 if (progbar_count >= progbar_nextstep) {
1604 /* let's not divide by zero. I should never be started
1605 * with count == 0, so let's assert that
1607 g_assert(cf->count > 0);
1608 progbar_val = (gfloat) progbar_count / cf->count;
1610 if (progbar != NULL) {
1611 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
1612 "%4u of %u packets", progbar_count, cf->count);
1613 update_progress_dlg(progbar, progbar_val, progbar_status_str);
1616 progbar_nextstep += progbar_quantum;
1619 if (progbar_stop_flag) {
1620 /* Well, the user decided to abort the operation. Just stop,
1621 and arrange to return PSP_STOPPED to our caller, so they know
1622 it was stopped explicitly. */
1629 /* do we have to process this packet? */
1630 process_this = packet_range_process_packet(range, fdata);
1631 if (process_this == range_process_next) {
1632 /* this packet uninteresting, continue with next one */
1634 } else if (process_this == range_processing_finished) {
1635 /* all interesting packets processed, stop the loop */
1639 /* Get the packet */
1640 if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1641 pd, fdata->cap_len, &err, &err_info)) {
1642 /* Attempt to get the packet failed. */
1643 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1644 cf_read_error_message(err, err_info), cf->filename);
1648 /* Process the packet */
1649 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
1650 /* Callback failed. We assume it reported the error appropriately. */
1656 /* We're done printing the packets; destroy the progress bar if
1658 if (progbar != NULL)
1659 destroy_progress_dlg(progbar);
1665 retap_packet(capture_file *cf _U_, frame_data *fdata,
1666 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1669 column_info *cinfo = argsp;
1670 epan_dissect_t *edt;
1672 /* If we have tap listeners, allocate a protocol tree root node, so that
1673 we'll construct a protocol tree against which a filter expression can
1675 edt = epan_dissect_new(num_tap_filters != 0, FALSE);
1676 tap_queue_init(edt);
1677 epan_dissect_run(edt, pseudo_header, pd, fdata, cinfo);
1678 tap_push_tapped_queue(edt);
1679 epan_dissect_free(edt);
1685 cf_retap_packets(capture_file *cf, gboolean do_columns)
1687 packet_range_t range;
1689 /* Reset the tap listeners. */
1690 reset_tap_listeners();
1692 /* Iterate through the list of packets, dissecting all packets and
1693 re-running the taps. */
1694 packet_range_init(&range);
1695 packet_range_process_init(&range);
1696 switch (process_specified_packets(cf, &range, "Refiltering statistics on",
1697 "all packets", TRUE, retap_packet,
1698 do_columns ? &cf->cinfo : NULL)) {
1700 /* Completed successfully. */
1704 /* Well, the user decided to abort the refiltering.
1705 Return CF_READ_ABORTED so our caller knows they did that. */
1706 return CF_READ_ABORTED;
1709 /* Error while retapping. */
1710 return CF_READ_ERROR;
1713 g_assert_not_reached();
1718 print_args_t *print_args;
1719 gboolean print_header_line;
1720 char *header_line_buf;
1721 int header_line_buf_len;
1722 gboolean print_formfeed;
1723 gboolean print_separator;
1727 } print_callback_args_t;
1730 print_packet(capture_file *cf, frame_data *fdata,
1731 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1734 print_callback_args_t *args = argsp;
1735 epan_dissect_t *edt;
1741 gboolean proto_tree_needed;
1742 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
1743 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
1745 /* Create the protocol tree, and make it visible, if we're printing
1746 the dissection or the hex data.
1747 XXX - do we need it if we're just printing the hex data? */
1749 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex;
1750 edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
1752 /* Fill in the column information if we're printing the summary
1754 if (args->print_args->print_summary) {
1755 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
1756 epan_dissect_fill_in_columns(edt);
1758 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1760 if (args->print_formfeed) {
1761 if (!new_page(args->print_args->stream))
1764 if (args->print_separator) {
1765 if (!print_line(args->print_args->stream, 0, ""))
1771 * We generate bookmarks, if the output format supports them.
1772 * The name is "__frameN__".
1774 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
1776 if (args->print_args->print_summary) {
1777 if (args->print_header_line) {
1778 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
1780 args->print_header_line = FALSE; /* we might not need to print any more */
1782 cp = &args->line_buf[0];
1784 for (i = 0; i < cf->cinfo.num_cols; i++) {
1785 /* Find the length of the string for this column. */
1786 column_len = strlen(cf->cinfo.col_data[i]);
1787 if (args->col_widths[i] > column_len)
1788 column_len = args->col_widths[i];
1790 /* Make sure there's room in the line buffer for the column; if not,
1791 double its length. */
1792 line_len += column_len + 1; /* "+1" for space */
1793 if (line_len > args->line_buf_len) {
1794 cp_off = cp - args->line_buf;
1795 args->line_buf_len = 2 * line_len;
1796 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
1797 cp = args->line_buf + cp_off;
1800 /* Right-justify the packet number column. */
1801 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1802 sprintf(cp, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
1804 sprintf(cp, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
1806 if (i != cf->cinfo.num_cols - 1)
1812 * Generate a bookmark, using the summary line as the title.
1814 if (!print_bookmark(args->print_args->stream, bookmark_name,
1818 if (!print_line(args->print_args->stream, 0, args->line_buf))
1822 * Generate a bookmark, using "Frame N" as the title, as we're not
1823 * printing the summary line.
1825 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
1826 if (!print_bookmark(args->print_args->stream, bookmark_name,
1829 } /* if (print_summary) */
1831 if (args->print_args->print_dissections != print_dissections_none) {
1832 if (args->print_args->print_summary) {
1833 /* Separate the summary line from the tree with a blank line. */
1834 if (!print_line(args->print_args->stream, 0, ""))
1838 /* Print the information in that tree. */
1839 if (!proto_tree_print(args->print_args, edt, args->print_args->stream))
1842 /* Print a blank line if we print anything after this (aka more than one packet). */
1843 args->print_separator = TRUE;
1845 /* Print a header line if we print any more packet summaries */
1846 args->print_header_line = TRUE;
1849 if (args->print_args->print_hex) {
1850 /* Print the full packet data as hex. */
1851 if (!print_hex_data(args->print_args->stream, edt))
1854 /* Print a blank line if we print anything after this (aka more than one packet). */
1855 args->print_separator = TRUE;
1857 /* Print a header line if we print any more packet summaries */
1858 args->print_header_line = TRUE;
1859 } /* if (args->print_args->print_dissections != print_dissections_none) */
1861 epan_dissect_free(edt);
1863 /* do we want to have a formfeed between each packet from now on? */
1864 if(args->print_args->print_formfeed) {
1865 args->print_formfeed = TRUE;
1871 epan_dissect_free(edt);
1876 cf_print_packets(capture_file *cf, print_args_t *print_args)
1879 print_callback_args_t callback_args;
1887 callback_args.print_args = print_args;
1888 callback_args.print_header_line = TRUE;
1889 callback_args.header_line_buf = NULL;
1890 callback_args.header_line_buf_len = 256;
1891 callback_args.print_formfeed = FALSE;
1892 callback_args.print_separator = FALSE;
1893 callback_args.line_buf = NULL;
1894 callback_args.line_buf_len = 256;
1895 callback_args.col_widths = NULL;
1897 if (!print_preamble(print_args->stream, cf->filename)) {
1898 destroy_print_stream(print_args->stream);
1899 return CF_PRINT_WRITE_ERROR;
1902 if (print_args->print_summary) {
1903 /* We're printing packet summaries. Allocate the header line buffer
1904 and get the column widths. */
1905 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
1907 /* Find the widths for each of the columns - maximum of the
1908 width of the title and the width of the data - and construct
1909 a buffer with a line containing the column titles. */
1910 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1911 cp = &callback_args.header_line_buf[0];
1913 for (i = 0; i < cf->cinfo.num_cols; i++) {
1914 /* Don't pad the last column. */
1915 if (i == cf->cinfo.num_cols - 1)
1916 callback_args.col_widths[i] = 0;
1918 callback_args.col_widths[i] = strlen(cf->cinfo.col_title[i]);
1919 data_width = get_column_char_width(get_column_format(i));
1920 if (data_width > callback_args.col_widths[i])
1921 callback_args.col_widths[i] = data_width;
1924 /* Find the length of the string for this column. */
1925 column_len = strlen(cf->cinfo.col_title[i]);
1926 if (callback_args.col_widths[i] > column_len)
1927 column_len = callback_args.col_widths[i];
1929 /* Make sure there's room in the line buffer for the column; if not,
1930 double its length. */
1931 line_len += column_len + 1; /* "+1" for space */
1932 if (line_len > callback_args.header_line_buf_len) {
1933 cp_off = cp - callback_args.header_line_buf;
1934 callback_args.header_line_buf_len = 2 * line_len;
1935 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
1936 callback_args.header_line_buf_len + 1);
1937 cp = callback_args.header_line_buf + cp_off;
1940 /* Right-justify the packet number column. */
1941 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1942 sprintf(cp, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1944 sprintf(cp, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1946 if (i != cf->cinfo.num_cols - 1)
1951 /* Now start out the main line buffer with the same length as the
1952 header line buffer. */
1953 callback_args.line_buf_len = callback_args.header_line_buf_len;
1954 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
1955 } /* if (print_summary) */
1957 /* Iterate through the list of packets, printing the packets we were
1959 ret = process_specified_packets(cf, &print_args->range, "Printing",
1960 "selected packets", TRUE, print_packet,
1963 if (callback_args.header_line_buf != NULL)
1964 g_free(callback_args.header_line_buf);
1965 if (callback_args.line_buf != NULL)
1966 g_free(callback_args.line_buf);
1967 if (callback_args.col_widths != NULL)
1968 g_free(callback_args.col_widths);
1973 /* Completed successfully. */
1977 /* Well, the user decided to abort the printing.
1979 XXX - note that what got generated before they did that
1980 will get printed if we're piping to a print program; we'd
1981 have to write to a file and then hand that to the print
1982 program to make it actually not print anything. */
1986 /* Error while printing.
1988 XXX - note that what got generated before they did that
1989 will get printed if we're piping to a print program; we'd
1990 have to write to a file and then hand that to the print
1991 program to make it actually not print anything. */
1992 destroy_print_stream(print_args->stream);
1993 return CF_PRINT_WRITE_ERROR;
1996 if (!print_finale(print_args->stream)) {
1997 destroy_print_stream(print_args->stream);
1998 return CF_PRINT_WRITE_ERROR;
2001 if (!destroy_print_stream(print_args->stream))
2002 return CF_PRINT_WRITE_ERROR;
2008 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2009 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2013 epan_dissect_t *edt;
2015 /* Create the protocol tree, but don't fill in the column information. */
2016 edt = epan_dissect_new(TRUE, TRUE);
2017 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
2019 /* Write out the information in that tree. */
2020 proto_tree_write_pdml(edt, fh);
2022 epan_dissect_free(edt);
2028 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2033 fh = eth_fopen(print_args->file, "w");
2035 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2037 write_pdml_preamble(fh);
2040 return CF_PRINT_WRITE_ERROR;
2043 /* Iterate through the list of packets, printing the packets we were
2045 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2046 "selected packets", TRUE,
2047 write_pdml_packet, fh);
2052 /* Completed successfully. */
2056 /* Well, the user decided to abort the printing. */
2060 /* Error while printing. */
2062 return CF_PRINT_WRITE_ERROR;
2065 write_pdml_finale(fh);
2068 return CF_PRINT_WRITE_ERROR;
2071 /* XXX - check for an error */
2078 write_psml_packet(capture_file *cf, frame_data *fdata,
2079 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2083 epan_dissect_t *edt;
2085 /* Fill in the column information, but don't create the protocol tree. */
2086 edt = epan_dissect_new(FALSE, FALSE);
2087 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2088 epan_dissect_fill_in_columns(edt);
2090 /* Write out the information in that tree. */
2091 proto_tree_write_psml(edt, fh);
2093 epan_dissect_free(edt);
2099 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2104 fh = eth_fopen(print_args->file, "w");
2106 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2108 write_psml_preamble(fh);
2111 return CF_PRINT_WRITE_ERROR;
2114 /* Iterate through the list of packets, printing the packets we were
2116 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2117 "selected packets", TRUE,
2118 write_psml_packet, fh);
2123 /* Completed successfully. */
2127 /* Well, the user decided to abort the printing. */
2131 /* Error while printing. */
2133 return CF_PRINT_WRITE_ERROR;
2136 write_psml_finale(fh);
2139 return CF_PRINT_WRITE_ERROR;
2142 /* XXX - check for an error */
2149 write_csv_packet(capture_file *cf, frame_data *fdata,
2150 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2154 epan_dissect_t *edt;
2156 /* Fill in the column information, but don't create the protocol tree. */
2157 edt = epan_dissect_new(FALSE, FALSE);
2158 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2159 epan_dissect_fill_in_columns(edt);
2161 /* Write out the information in that tree. */
2162 proto_tree_write_csv(edt, fh);
2164 epan_dissect_free(edt);
2170 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2175 fh = eth_fopen(print_args->file, "w");
2177 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2179 write_csv_preamble(fh);
2182 return CF_PRINT_WRITE_ERROR;
2185 /* Iterate through the list of packets, printing the packets we were
2187 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2188 "selected packets", TRUE,
2189 write_csv_packet, fh);
2194 /* Completed successfully. */
2198 /* Well, the user decided to abort the printing. */
2202 /* Error while printing. */
2204 return CF_PRINT_WRITE_ERROR;
2207 write_csv_finale(fh);
2210 return CF_PRINT_WRITE_ERROR;
2213 /* XXX - check for an error */
2219 /* Scan through the packet list and change all columns that use the
2220 "command-line-specified" time stamp format to use the current
2221 value of that format. */
2223 cf_change_time_formats(capture_file *cf)
2226 progdlg_t *progbar = NULL;
2232 GTimeVal start_time;
2233 gchar status_str[100];
2234 int progbar_nextstep;
2235 int progbar_quantum;
2237 gboolean sorted_by_frame_column;
2240 /* adjust timestamp precision if auto is selected */
2241 cf_timestamp_auto_precision(cf);
2243 /* Are there any columns with time stamps in the "command-line-specified"
2246 XXX - we have to force the "column is writable" flag on, as it
2247 might be off from the last frame that was dissected. */
2248 col_set_writable(&cf->cinfo, TRUE);
2249 if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
2250 /* No, there aren't any columns in that format, so we have no work
2254 first = cf->cinfo.col_first[COL_CLS_TIME];
2255 g_assert(first >= 0);
2256 last = cf->cinfo.col_last[COL_CLS_TIME];
2258 /* Freeze the packet list while we redo it, so we don't get any
2259 screen updates while it happens. */
2260 packet_list_freeze();
2262 /* Update the progress bar when it gets to this value. */
2263 progbar_nextstep = 0;
2264 /* When we reach the value that triggers a progress bar update,
2265 bump that value by this amount. */
2266 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2267 /* Count of packets at which we've looked. */
2269 /* Progress so far. */
2272 /* If the rows are currently sorted by the frame column then we know
2273 * the row number of each packet: it's the row number of the previously
2274 * displayed packet + 1.
2276 * Otherwise, if the display is sorted by a different column then we have
2277 * to use the O(N) packet_list_find_row_from_data() (thus making the job
2278 * of changing the time display format O(N**2)).
2280 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
2281 * the row number and walks that many elements down the clist to find
2282 * the appropriate element.)
2284 sorted_by_frame_column = FALSE;
2285 for (i = 0; i < cf->cinfo.num_cols; i++) {
2286 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2288 sorted_by_frame_column = (i == packet_list_get_sort_column());
2294 g_get_current_time(&start_time);
2296 /* Iterate through the list of packets, checking whether the packet
2297 is in a row of the summary list and, if so, whether there are
2298 any columns that show the time in the "command-line-specified"
2299 format and, if so, update that row. */
2300 for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
2301 /* Create the progress bar if necessary.
2302 We check on every iteration of the loop, so that it takes no
2303 longer than the standard time to create it (otherwise, for a
2304 large file, we might take considerably longer than that standard
2305 time in order to get to the next progress bar step). */
2306 if (progbar == NULL)
2307 progbar = delayed_create_progress_dlg("Changing", "time display",
2308 TRUE, &stop_flag, &start_time, progbar_val);
2310 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2311 when we update it, we have to run the GTK+ main loop to get it
2312 to repaint what's pending, and doing so may involve an "ioctl()"
2313 to see if there's any pending input from an X server, and doing
2314 that for every packet can be costly, especially on a big file. */
2315 if (count >= progbar_nextstep) {
2316 /* let's not divide by zero. I should never be started
2317 * with count == 0, so let's assert that
2319 g_assert(cf->count > 0);
2321 progbar_val = (gfloat) count / cf->count;
2323 if (progbar != NULL) {
2324 g_snprintf(status_str, sizeof(status_str),
2325 "%4u of %u packets", count, cf->count);
2326 update_progress_dlg(progbar, progbar_val, status_str);
2329 progbar_nextstep += progbar_quantum;
2333 /* Well, the user decided to abort the redisplay. Just stop.
2335 XXX - this leaves the time field in the old format in
2336 frames we haven't yet processed. So it goes; should we
2337 simply not offer them the option of stopping? */
2343 /* Find what row this packet is in. */
2344 if (!sorted_by_frame_column) {
2345 /* This function is O(N), so we try to avoid using it... */
2346 row = packet_list_find_row_from_data(fdata);
2348 /* ...which we do by maintaining a count of packets that are
2349 being displayed (i.e., that have passed the display filter),
2350 and using the current value of that count as the row number
2351 (which is why we can only do it when the display is sorted
2352 by the frame number). */
2353 if (fdata->flags.passed_dfilter)
2360 /* This packet is in the summary list, on row "row". */
2362 for (i = first; i <= last; i++) {
2363 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2364 /* This is one of the columns that shows the time in
2365 "command-line-specified" format; update it. */
2366 cf->cinfo.col_buf[i][0] = '\0';
2367 col_set_cls_time(fdata, &cf->cinfo, i);
2368 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
2374 /* We're done redisplaying the packets; destroy the progress bar if it
2376 if (progbar != NULL)
2377 destroy_progress_dlg(progbar);
2379 /* Set the column widths of those columns that show the time in
2380 "command-line-specified" format. */
2381 for (i = first; i <= last; i++) {
2382 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2383 packet_list_set_cls_time_width(i);
2387 /* Unfreeze the packet list. */
2395 gboolean frame_matched;
2399 cf_find_packet_protocol_tree(capture_file *cf, const char *string)
2403 mdata.string = string;
2404 mdata.string_len = strlen(string);
2405 return find_packet(cf, match_protocol_tree, &mdata);
2409 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2411 match_data *mdata = criterion;
2412 epan_dissect_t *edt;
2414 /* Construct the protocol tree, including the displayed text */
2415 edt = epan_dissect_new(TRUE, TRUE);
2416 /* We don't need the column information */
2417 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2419 /* Iterate through all the nodes, seeing if they have text that matches. */
2421 mdata->frame_matched = FALSE;
2422 proto_tree_children_foreach(edt->tree, match_subtree_text, mdata);
2423 epan_dissect_free(edt);
2424 return mdata->frame_matched;
2428 match_subtree_text(proto_node *node, gpointer data)
2430 match_data *mdata = (match_data*) data;
2431 const gchar *string = mdata->string;
2432 size_t string_len = mdata->string_len;
2433 capture_file *cf = mdata->cf;
2434 field_info *fi = PITEM_FINFO(node);
2435 gchar label_str[ITEM_LABEL_LENGTH];
2442 if (mdata->frame_matched) {
2443 /* We already had a match; don't bother doing any more work. */
2447 /* Don't match invisible entries. */
2448 if (PROTO_ITEM_IS_HIDDEN(node))
2451 /* was a free format label produced? */
2453 label_ptr = fi->rep->representation;
2455 /* no, make a generic label */
2456 label_ptr = label_str;
2457 proto_item_fill_label(fi, label_str);
2460 /* Does that label match? */
2461 label_len = strlen(label_ptr);
2462 for (i = 0; i < label_len; i++) {
2463 c_char = label_ptr[i];
2465 c_char = toupper(c_char);
2466 if (c_char == string[c_match]) {
2468 if (c_match == string_len) {
2469 /* No need to look further; we have a match */
2470 mdata->frame_matched = TRUE;
2477 /* Recurse into the subtree, if it exists */
2478 if (node->first_child != NULL)
2479 proto_tree_children_foreach(node, match_subtree_text, mdata);
2483 cf_find_packet_summary_line(capture_file *cf, const char *string)
2487 mdata.string = string;
2488 mdata.string_len = strlen(string);
2489 return find_packet(cf, match_summary_line, &mdata);
2493 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2495 match_data *mdata = criterion;
2496 const gchar *string = mdata->string;
2497 size_t string_len = mdata->string_len;
2498 epan_dissect_t *edt;
2499 const char *info_column;
2500 size_t info_column_len;
2501 gboolean frame_matched = FALSE;
2507 /* Don't bother constructing the protocol tree */
2508 edt = epan_dissect_new(FALSE, FALSE);
2509 /* Get the column information */
2510 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2512 /* Find the Info column */
2513 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2514 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2515 /* Found it. See if we match. */
2516 info_column = edt->pi.cinfo->col_data[colx];
2517 info_column_len = strlen(info_column);
2518 for (i = 0; i < info_column_len; i++) {
2519 c_char = info_column[i];
2521 c_char = toupper(c_char);
2522 if (c_char == string[c_match]) {
2524 if (c_match == string_len) {
2525 frame_matched = TRUE;
2534 epan_dissect_free(edt);
2535 return frame_matched;
2541 } cbs_t; /* "Counted byte string" */
2544 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
2549 info.data_len = string_size;
2551 /* String or hex search? */
2553 /* String search - what type of string? */
2554 switch (cf->scs_type) {
2556 case SCS_ASCII_AND_UNICODE:
2557 return find_packet(cf, match_ascii_and_unicode, &info);
2560 return find_packet(cf, match_ascii, &info);
2563 return find_packet(cf, match_unicode, &info);
2566 g_assert_not_reached();
2570 return find_packet(cf, match_binary, &info);
2574 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2576 cbs_t *info = criterion;
2577 const char *ascii_text = info->data;
2578 size_t textlen = info->data_len;
2579 gboolean frame_matched;
2585 frame_matched = FALSE;
2586 buf_len = fdata->pkt_len;
2587 for (i = 0; i < buf_len; i++) {
2590 c_char = toupper(c_char);
2592 if (c_char == ascii_text[c_match]) {
2594 if (c_match == textlen) {
2595 frame_matched = TRUE;
2602 return frame_matched;
2606 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2608 cbs_t *info = criterion;
2609 const char *ascii_text = info->data;
2610 size_t textlen = info->data_len;
2611 gboolean frame_matched;
2617 frame_matched = FALSE;
2618 buf_len = fdata->pkt_len;
2619 for (i = 0; i < buf_len; i++) {
2622 c_char = toupper(c_char);
2623 if (c_char == ascii_text[c_match]) {
2625 if (c_match == textlen) {
2626 frame_matched = TRUE;
2632 return frame_matched;
2636 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2638 cbs_t *info = criterion;
2639 const char *ascii_text = info->data;
2640 size_t textlen = info->data_len;
2641 gboolean frame_matched;
2647 frame_matched = FALSE;
2648 buf_len = fdata->pkt_len;
2649 for (i = 0; i < buf_len; i++) {
2652 c_char = toupper(c_char);
2653 if (c_char == ascii_text[c_match]) {
2656 if (c_match == textlen) {
2657 frame_matched = TRUE;
2663 return frame_matched;
2667 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
2669 cbs_t *info = criterion;
2670 const guint8 *binary_data = info->data;
2671 size_t datalen = info->data_len;
2672 gboolean frame_matched;
2677 frame_matched = FALSE;
2678 buf_len = fdata->pkt_len;
2679 for (i = 0; i < buf_len; i++) {
2680 if (cf->pd[i] == binary_data[c_match]) {
2682 if (c_match == datalen) {
2683 frame_matched = TRUE;
2689 return frame_matched;
2693 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
2695 return find_packet(cf, match_dfilter, sfcode);
2699 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
2701 dfilter_t *sfcode = criterion;
2702 epan_dissect_t *edt;
2703 gboolean frame_matched;
2705 edt = epan_dissect_new(TRUE, FALSE);
2706 epan_dissect_prime_dfilter(edt, sfcode);
2707 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2708 frame_matched = dfilter_apply_edt(sfcode, edt);
2709 epan_dissect_free(edt);
2710 return frame_matched;
2714 find_packet(capture_file *cf,
2715 gboolean (*match_function)(capture_file *, frame_data *, void *),
2718 frame_data *start_fd;
2720 frame_data *new_fd = NULL;
2721 progdlg_t *progbar = NULL;
2728 GTimeVal start_time;
2729 gchar status_str[100];
2730 int progbar_nextstep;
2731 int progbar_quantum;
2734 start_fd = cf->current_frame;
2735 if (start_fd != NULL) {
2736 /* Iterate through the list of packets, starting at the packet we've
2737 picked, calling a routine to run the filter on the packet, see if
2738 it matches, and stop if so. */
2742 /* Update the progress bar when it gets to this value. */
2743 progbar_nextstep = 0;
2744 /* When we reach the value that triggers a progress bar update,
2745 bump that value by this amount. */
2746 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2747 /* Progress so far. */
2751 g_get_current_time(&start_time);
2754 title = cf->sfilter?cf->sfilter:"";
2756 /* Create the progress bar if necessary.
2757 We check on every iteration of the loop, so that it takes no
2758 longer than the standard time to create it (otherwise, for a
2759 large file, we might take considerably longer than that standard
2760 time in order to get to the next progress bar step). */
2761 if (progbar == NULL)
2762 progbar = delayed_create_progress_dlg("Searching", title,
2763 FALSE, &stop_flag, &start_time, progbar_val);
2765 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2766 when we update it, we have to run the GTK+ main loop to get it
2767 to repaint what's pending, and doing so may involve an "ioctl()"
2768 to see if there's any pending input from an X server, and doing
2769 that for every packet can be costly, especially on a big file. */
2770 if (count >= progbar_nextstep) {
2771 /* let's not divide by zero. I should never be started
2772 * with count == 0, so let's assert that
2774 g_assert(cf->count > 0);
2776 progbar_val = (gfloat) count / cf->count;
2778 if (progbar != NULL) {
2779 g_snprintf(status_str, sizeof(status_str),
2780 "%4u of %u packets", count, cf->count);
2781 update_progress_dlg(progbar, progbar_val, status_str);
2784 progbar_nextstep += progbar_quantum;
2788 /* Well, the user decided to abort the search. Go back to the
2789 frame where we started. */
2794 /* Go past the current frame. */
2795 if (cf->sbackward) {
2796 /* Go on to the previous frame. */
2797 fdata = fdata->prev;
2798 if (fdata == NULL) {
2800 * XXX - other apps have a bit more of a detailed message
2801 * for this, and instead of offering "OK" and "Cancel",
2802 * they offer things such as "Continue" and "Cancel";
2803 * we need an API for popping up alert boxes with
2804 * {Verb} and "Cancel".
2807 if (prefs.gui_find_wrap)
2809 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2810 "%sBeginning of capture exceeded!%s\n\n"
2811 "Search is continued from the end of the capture.",
2812 simple_dialog_primary_start(), simple_dialog_primary_end());
2813 fdata = cf->plist_end; /* wrap around */
2817 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2818 "%sBeginning of capture exceeded!%s\n\n"
2819 "Try searching forwards.",
2820 simple_dialog_primary_start(), simple_dialog_primary_end());
2821 fdata = start_fd; /* stay on previous packet */
2825 /* Go on to the next frame. */
2826 fdata = fdata->next;
2827 if (fdata == NULL) {
2828 if (prefs.gui_find_wrap)
2830 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2831 "%sEnd of capture exceeded!%s\n\n"
2832 "Search is continued from the start of the capture.",
2833 simple_dialog_primary_start(), simple_dialog_primary_end());
2834 fdata = cf->plist; /* wrap around */
2838 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2839 "%sEnd of capture exceeded!%s\n\n"
2840 "Try searching backwards.",
2841 simple_dialog_primary_start(), simple_dialog_primary_end());
2842 fdata = start_fd; /* stay on previous packet */
2849 /* Is this packet in the display? */
2850 if (fdata->flags.passed_dfilter) {
2851 /* Yes. Load its data. */
2852 if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
2853 cf->pd, fdata->cap_len, &err, &err_info)) {
2854 /* Read error. Report the error, and go back to the frame
2855 where we started. */
2856 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2857 cf_read_error_message(err, err_info), cf->filename);
2862 /* Does it match the search criterion? */
2863 if ((*match_function)(cf, fdata, criterion)) {
2865 break; /* found it! */
2869 if (fdata == start_fd) {
2870 /* We're back to the frame we were on originally, and that frame
2871 doesn't match the search filter. The search failed. */
2876 /* We're done scanning the packets; destroy the progress bar if it
2878 if (progbar != NULL)
2879 destroy_progress_dlg(progbar);
2882 if (new_fd != NULL) {
2883 /* We found a frame. Find what row it's in. */
2884 row = packet_list_find_row_from_data(new_fd);
2885 g_assert(row != -1);
2887 /* Select that row, make it the focus row, and make it visible. */
2888 packet_list_set_selected_row(row);
2889 return TRUE; /* success */
2891 return FALSE; /* failure */
2895 cf_goto_frame(capture_file *cf, guint fnumber)
2900 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
2903 if (fdata == NULL) {
2904 /* we didn't find a packet with that packet number */
2905 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2906 "There is no packet with the packet number %u.", fnumber);
2907 return FALSE; /* we failed to go to that packet */
2909 if (!fdata->flags.passed_dfilter) {
2910 /* that packet currently isn't displayed */
2911 /* XXX - add it to the set of displayed packets? */
2912 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2913 "The packet number %u isn't currently being displayed.", fnumber);
2914 return FALSE; /* we failed to go to that packet */
2917 /* We found that packet, and it's currently being displayed.
2918 Find what row it's in. */
2919 row = packet_list_find_row_from_data(fdata);
2920 g_assert(row != -1);
2922 /* Select that row, make it the focus row, and make it visible. */
2923 packet_list_set_selected_row(row);
2924 return TRUE; /* we got to that packet */
2928 cf_goto_top_frame(capture_file *cf)
2932 frame_data *lowest_fdata = NULL;
2934 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2935 if (fdata->flags.passed_dfilter) {
2936 lowest_fdata = fdata;
2941 if (lowest_fdata == NULL) {
2945 /* We found that packet, and it's currently being displayed.
2946 Find what row it's in. */
2947 row = packet_list_find_row_from_data(lowest_fdata);
2948 g_assert(row != -1);
2950 /* Select that row, make it the focus row, and make it visible. */
2951 packet_list_set_selected_row(row);
2952 return TRUE; /* we got to that packet */
2956 cf_goto_bottom_frame(capture_file *cf)
2960 frame_data *highest_fdata = NULL;
2962 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2963 if (fdata->flags.passed_dfilter) {
2964 highest_fdata = fdata;
2968 if (highest_fdata == NULL) {
2972 /* We found that packet, and it's currently being displayed.
2973 Find what row it's in. */
2974 row = packet_list_find_row_from_data(highest_fdata);
2975 g_assert(row != -1);
2977 /* Select that row, make it the focus row, and make it visible. */
2978 packet_list_set_selected_row(row);
2979 return TRUE; /* we got to that packet */
2983 * Go to frame specified by currently selected protocol tree item.
2986 cf_goto_framenum(capture_file *cf)
2988 header_field_info *hfinfo;
2991 if (cf->finfo_selected) {
2992 hfinfo = cf->finfo_selected->hfinfo;
2994 if (hfinfo->type == FT_FRAMENUM) {
2995 framenum = fvalue_get_integer(&cf->finfo_selected->value);
2997 return cf_goto_frame(cf, framenum);
3004 /* Select the packet on a given row. */
3006 cf_select_packet(capture_file *cf, int row)
3012 /* Get the frame data struct pointer for this frame */
3013 fdata = (frame_data *)packet_list_get_row_data(row);
3015 if (fdata == NULL) {
3016 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3017 the first entry is added to it by "real_insert_row()", that row
3018 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
3019 our version and the vanilla GTK+ version).
3021 This means that a "select-row" signal is emitted; this causes
3022 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3025 "cf_select_packet()" fetches, above, the data associated with the
3026 row that was selected; however, as "gtk_clist_append()", which
3027 called "real_insert_row()", hasn't yet returned, we haven't yet
3028 associated any data with that row, so we get back a null pointer.
3030 We can't assume that there's only one frame in the frame list,
3031 either, as we may be filtering the display.
3033 We therefore assume that, if "row" is 0, i.e. the first row
3034 is being selected, and "cf->first_displayed" equals
3035 "cf->last_displayed", i.e. there's only one frame being
3036 displayed, that frame is the frame we want.
3038 This means we have to set "cf->first_displayed" and
3039 "cf->last_displayed" before adding the row to the
3040 GtkCList; see the comment in "add_packet_to_packet_list()". */
3042 if (row == 0 && cf->first_displayed == cf->last_displayed)
3043 fdata = cf->first_displayed;
3046 /* If fdata _still_ isn't set simply give up. */
3047 if (fdata == NULL) {
3051 /* Get the data in that frame. */
3052 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
3053 cf->pd, fdata->cap_len, &err, &err_info)) {
3054 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3055 cf_read_error_message(err, err_info), cf->filename);
3059 /* Record that this frame is the current frame. */
3060 cf->current_frame = fdata;
3062 /* Create the logical protocol tree. */
3063 if (cf->edt != NULL) {
3064 epan_dissect_free(cf->edt);
3067 /* We don't need the columns here. */
3068 cf->edt = epan_dissect_new(TRUE, TRUE);
3069 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3072 cf_callback_invoke(cf_cb_packet_selected, cf);
3075 /* Unselect the selected packet, if any. */
3077 cf_unselect_packet(capture_file *cf)
3079 /* Destroy the epan_dissect_t for the unselected packet. */
3080 if (cf->edt != NULL) {
3081 epan_dissect_free(cf->edt);
3085 /* No packet is selected. */
3086 cf->current_frame = NULL;
3088 cf_callback_invoke(cf_cb_packet_unselected, cf);
3090 /* No protocol tree means no selected field. */
3091 cf_unselect_field(cf);
3094 /* Unset the selected protocol tree field, if any. */
3096 cf_unselect_field(capture_file *cf)
3098 cf->finfo_selected = NULL;
3100 cf_callback_invoke(cf_cb_field_unselected, cf);
3104 * Mark a particular frame.
3107 cf_mark_frame(capture_file *cf, frame_data *frame)
3109 if (! frame->flags.marked) {
3110 frame->flags.marked = TRUE;
3111 if (cf->count > cf->marked_count)
3117 * Unmark a particular frame.
3120 cf_unmark_frame(capture_file *cf, frame_data *frame)
3122 if (frame->flags.marked) {
3123 frame->flags.marked = FALSE;
3124 if (cf->marked_count > 0)
3132 } save_callback_args_t;
3135 * Save a capture to a file, in a particular format, saving either
3136 * all packets, all currently-displayed packets, or all marked packets.
3138 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3139 * up a message box for the failure.
3142 save_packet(capture_file *cf _U_, frame_data *fdata,
3143 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3146 save_callback_args_t *args = argsp;
3147 struct wtap_pkthdr hdr;
3150 /* init the wtap header for saving */
3151 hdr.ts = *(struct wtap_nstime *) &fdata->abs_ts;
3152 hdr.caplen = fdata->cap_len;
3153 hdr.len = fdata->pkt_len;
3154 hdr.pkt_encap = fdata->lnk_t;
3156 /* and save the packet */
3157 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3158 cf_write_failure_alert_box(args->fname, err);
3165 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3167 gchar *from_filename;
3171 save_callback_args_t callback_args;
3173 cf_callback_invoke(cf_cb_file_safe_started, (gpointer) fname);
3175 /* don't write over an existing file. */
3176 /* this should've been already checked by our caller, just to be sure... */
3177 if (file_exists(fname)) {
3178 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3179 "%sCapture file: \"%s\" already exists!%s\n\n"
3180 "Please choose a different filename.",
3181 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3185 packet_range_process_init(range);
3188 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3189 /* We're not filtering packets, and we're saving it in the format
3190 it's already in, so we can just move or copy the raw data. */
3192 if (cf->is_tempfile) {
3193 /* The file being saved is a temporary file from a live
3194 capture, so it doesn't need to stay around under that name;
3195 first, try renaming the capture buffer file to the new name. */
3197 if (eth_rename(cf->filename, fname) == 0) {
3198 /* That succeeded - there's no need to copy the source file. */
3199 from_filename = NULL;
3202 if (errno == EXDEV) {
3203 /* They're on different file systems, so we have to copy the
3206 from_filename = cf->filename;
3208 /* The rename failed, but not because they're on different
3209 file systems - put up an error message. (Or should we
3210 just punt and try to copy? The only reason why I'd
3211 expect the rename to fail and the copy to succeed would
3212 be if we didn't have permission to remove the file from
3213 the temporary directory, and that might be fixable - but
3214 is it worth requiring the user to go off and fix it?) */
3215 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3216 file_rename_error_message(errno), fname);
3222 from_filename = cf->filename;
3225 /* It's a permanent file, so we should copy it, and not remove the
3228 from_filename = cf->filename;
3232 /* Copy the file, if we haven't moved it. */
3233 if (!copy_binary_file(from_filename, fname))
3237 /* Either we're filtering packets, or we're saving in a different
3238 format; we can't do that by copying or moving the capture file,
3239 we have to do it by writing the packets out in Wiretap. */
3240 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
3243 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3247 /* XXX - we let the user save a subset of the packets.
3249 If we do that, should we make that file the current file? If so,
3250 it means we can no longer get at the other packets. What does
3253 /* Iterate through the list of packets, processing the packets we were
3256 XXX - we've already called "packet_range_process_init(range)", but
3257 "process_specified_packets()" will do it again. Fortunately,
3258 that's harmless in this case, as we haven't done anything to
3259 "range" since we initialized it. */
3260 callback_args.pdh = pdh;
3261 callback_args.fname = fname;
3262 switch (process_specified_packets(cf, range, "Saving", "selected packets",
3263 TRUE, save_packet, &callback_args)) {
3266 /* Completed successfully. */
3270 /* The user decided to abort the saving.
3271 XXX - remove the output file? */
3275 /* Error while saving. */
3276 wtap_dump_close(pdh, &err);
3280 if (!wtap_dump_close(pdh, &err)) {
3281 cf_close_failure_alert_box(fname, err);
3286 cf_callback_invoke(cf_cb_file_safe_finished, NULL);
3288 if (packet_range_process_all(range)) {
3289 /* We saved the entire capture, not just some packets from it.
3290 Open and read the file we saved it to.
3292 XXX - this is somewhat of a waste; we already have the
3293 packets, all this gets us is updated file type information
3294 (which we could just stuff into "cf"), and having the new
3295 file be the one we have opened and from which we're reading
3296 the data, and it means we have to spend time opening and
3297 reading the file, which could be a significant amount of
3298 time if the file is large. */
3299 cf->user_saved = TRUE;
3301 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3302 /* XXX - report errors if this fails?
3303 What should we return if it fails or is aborted? */
3304 switch (cf_read(cf)) {
3308 /* Just because we got an error, that doesn't mean we were unable
3309 to read any of the file; we handle what we could get from the
3313 case CF_READ_ABORTED:
3314 /* The user bailed out of re-reading the capture file; the
3315 capture file has been closed - just return (without
3316 changing any menu settings; "cf_close()" set them
3317 correctly for the "no capture file open" state). */
3320 cf_callback_invoke(cf_cb_file_safe_reload_finished, NULL);
3326 cf_callback_invoke(cf_cb_file_safe_failed, NULL);
3331 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3332 gboolean for_writing, int file_type)
3335 /* Wiretap error. */
3338 case WTAP_ERR_NOT_REGULAR_FILE:
3339 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3340 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3344 case WTAP_ERR_RANDOM_OPEN_PIPE:
3345 /* Seen only when opening a capture file for reading. */
3346 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3347 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
3351 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3352 /* Seen only when opening a capture file for reading. */
3353 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3354 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
3358 case WTAP_ERR_UNSUPPORTED:
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.\n"
3363 filename, err_info);
3367 case WTAP_ERR_CANT_WRITE_TO_PIPE:
3368 /* Seen only when opening a capture file for writing. */
3369 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3370 "The file \"%s\" is a pipe, and %s capture files can't be "
3371 "written to a pipe.",
3372 filename, wtap_file_type_string(file_type));
3375 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3376 /* Seen only when opening a capture file for writing. */
3377 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3378 "Wireshark doesn't support writing capture files in that format.");
3381 case WTAP_ERR_UNSUPPORTED_ENCAP:
3383 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3384 "Wireshark can't save this capture in that format.");
3386 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3387 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
3389 filename, err_info);
3394 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3396 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3397 "Wireshark can't save this capture in that format.");
3399 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3400 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
3405 case WTAP_ERR_BAD_RECORD:
3406 /* Seen only when opening a capture file for reading. */
3407 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3408 "The file \"%s\" appears to be damaged or corrupt.\n"
3410 filename, err_info);
3414 case WTAP_ERR_CANT_OPEN:
3416 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3417 "The file \"%s\" could not be created for some unknown reason.",
3420 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3421 "The file \"%s\" could not be opened for some unknown reason.",
3426 case WTAP_ERR_SHORT_READ:
3427 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3428 "The file \"%s\" appears to have been cut short"
3429 " in the middle of a packet or other data.",
3433 case WTAP_ERR_SHORT_WRITE:
3434 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3435 "A full header couldn't be written to the file \"%s\".",
3439 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
3440 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3441 "Gzip compression not supported by this file type.");
3445 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3446 "The file \"%s\" could not be %s: %s.",
3448 for_writing ? "created" : "opened",
3449 wtap_strerror(err));
3454 open_failure_alert_box(filename, err, for_writing);
3459 file_rename_error_message(int err)
3462 static char errmsg_errno[1024+1];
3467 errmsg = "The path to the file \"%s\" doesn't exist.";
3471 errmsg = "You don't have permission to move the capture file to \"%s\".";
3475 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3476 "The file \"%%s\" could not be moved: %s.",
3477 wtap_strerror(err));
3478 errmsg = errmsg_errno;
3485 cf_read_error_message(int err, const gchar *err_info)
3487 static char errmsg_errno[1024+1];
3491 case WTAP_ERR_UNSUPPORTED_ENCAP:
3492 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3493 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
3497 case WTAP_ERR_BAD_RECORD:
3498 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3499 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
3500 wtap_strerror(err), err_info);
3504 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3505 "An error occurred while reading from the file \"%%s\": %s.",
3506 wtap_strerror(err));
3509 return errmsg_errno;
3513 cf_write_failure_alert_box(const char *filename, int err)
3516 /* Wiretap error. */
3517 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3518 "An error occurred while writing to the file \"%s\": %s.",
3519 filename, wtap_strerror(err));
3522 write_failure_alert_box(filename, err);
3526 /* Check for write errors - if the file is being written to an NFS server,
3527 a write error may not show up until the file is closed, as NFS clients
3528 might not send writes to the server until the "write()" call finishes,
3529 so that the write may fail on the server but the "write()" may succeed. */
3531 cf_close_failure_alert_box(const char *filename, int err)
3534 /* Wiretap error. */
3537 case WTAP_ERR_CANT_CLOSE:
3538 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3539 "The file \"%s\" couldn't be closed for some unknown reason.",
3543 case WTAP_ERR_SHORT_WRITE:
3544 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3545 "Not all the packets could be written to the file \"%s\".",
3550 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3551 "An error occurred while closing the file \"%s\": %s.",
3552 filename, wtap_strerror(err));
3557 We assume that a close error from the OS is really a write error. */
3558 write_failure_alert_box(filename, err);
3562 /* Reload the current capture file. */
3564 cf_reload(capture_file *cf) {
3566 gboolean is_tempfile;
3569 /* If the file could be opened, "cf_open()" calls "cf_close()"
3570 to get rid of state for the old capture file before filling in state
3571 for the new capture file. "cf_close()" will remove the file if
3572 it's a temporary file; we don't want that to happen (for one thing,
3573 it'd prevent subsequent reopens from working). Remember whether it's
3574 a temporary file, mark it as not being a temporary file, and then
3575 reopen it as the type of file it was.
3577 Also, "cf_close()" will free "cf->filename", so we must make
3578 a copy of it first. */
3579 filename = g_strdup(cf->filename);
3580 is_tempfile = cf->is_tempfile;
3581 cf->is_tempfile = FALSE;
3582 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
3583 switch (cf_read(cf)) {
3587 /* Just because we got an error, that doesn't mean we were unable
3588 to read any of the file; we handle what we could get from the
3592 case CF_READ_ABORTED:
3593 /* The user bailed out of re-reading the capture file; the
3594 capture file has been closed - just free the capture file name
3595 string and return (without changing the last containing
3601 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
3602 Instead, the file was left open, so we should restore "cf->is_tempfile"
3605 XXX - change the menu? Presumably "cf_open()" will do that;
3606 make sure it does! */
3607 cf->is_tempfile = is_tempfile;
3609 /* "cf_open()" made a copy of the file name we handed it, so
3610 we should free up our copy. */
3614 /* Copies a file in binary mode, for those operating systems that care about
3616 * Returns TRUE on success, FALSE on failure. If a failure, it also
3617 * displays a simple dialog window with the error message.
3620 copy_binary_file(const char *from_filename, const char *to_filename)
3622 int from_fd, to_fd, nread, nwritten, err;
3625 /* Copy the raw bytes of the file. */
3626 from_fd = eth_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
3628 open_failure_alert_box(from_filename, errno, FALSE);
3632 /* Use open() instead of creat() so that we can pass the O_BINARY
3633 flag, which is relevant on Win32; it appears that "creat()"
3634 may open the file in text mode, not binary mode, but we want
3635 to copy the raw bytes of the file, so we need the output file
3636 to be open in binary mode. */
3637 to_fd = eth_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
3639 open_failure_alert_box(to_filename, errno, TRUE);
3644 while ((nread = eth_read(from_fd, pd, sizeof pd)) > 0) {
3645 nwritten = eth_write(to_fd, pd, nread);
3646 if (nwritten < nread) {
3650 err = WTAP_ERR_SHORT_WRITE;
3651 write_failure_alert_box(to_filename, err);
3659 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3660 "An error occurred while reading from the file \"%s\": %s.",
3661 from_filename, strerror(err));
3667 if (eth_close(to_fd) < 0) {
3668 write_failure_alert_box(to_filename, errno);