4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
42 #include <wsutil/tempfile.h>
43 #include <wsutil/file_util.h>
44 #include <wsutil/filesystem.h>
45 #include <wsutil/ws_version_info.h>
47 #include <wiretap/merge.h>
49 #include <epan/exceptions.h>
50 #include <epan/epan-int.h>
51 #include <epan/epan.h>
52 #include <epan/column.h>
53 #include <epan/packet.h>
54 #include <epan/column-utils.h>
55 #include <epan/expert.h>
56 #include <epan/prefs.h>
57 #include <epan/dfilter/dfilter.h>
58 #include <epan/epan_dissect.h>
60 #include <epan/dissectors/packet-data.h>
61 #include <epan/dissectors/packet-ber.h>
62 #include <epan/timestamp.h>
63 #include <epan/dfilter/dfilter-macro.h>
64 #include <epan/strutil.h>
65 #include <epan/addr_resolv.h>
68 #include "color_filters.h"
72 #include "frame_tvbuff.h"
74 #include "ui/alert_box.h"
75 #include "ui/simple_dialog.h"
76 #include "ui/main_statusbar.h"
77 #include "ui/progress_dlg.h"
78 #include "ui/ui_util.h"
80 /* Needed for addrinfo */
81 #ifdef HAVE_SYS_TYPES_H
82 # include <sys/types.h>
85 #ifdef HAVE_SYS_SOCKET_H
86 #include <sys/socket.h>
89 #ifdef HAVE_NETINET_IN_H
90 # include <netinet/in.h>
97 #ifdef HAVE_WINSOCK2_H
98 # include <winsock2.h>
101 #if defined(_WIN32) && defined(INET6)
102 # include <ws2tcpip.h>
106 gboolean auto_scroll_live;
109 static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
110 column_info *cinfo, gint64 offset);
112 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
119 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
121 static void match_subtree_text(proto_node *node, gpointer data);
122 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
124 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
126 static match_result match_narrow(capture_file *cf, frame_data *fdata,
128 static match_result match_wide(capture_file *cf, frame_data *fdata,
130 static match_result match_binary(capture_file *cf, frame_data *fdata,
132 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
134 static match_result match_marked(capture_file *cf, frame_data *fdata,
136 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
138 static gboolean find_packet(capture_file *cf,
139 match_result (*match_function)(capture_file *, frame_data *, void *),
140 void *criterion, search_direction dir);
142 static const char *cf_get_user_packet_comment(capture_file *cf, const frame_data *fd);
144 static void cf_open_failure_alert_box(const char *filename, int err,
145 gchar *err_info, gboolean for_writing,
147 static void cf_rename_failure_alert_box(const char *filename, int err);
148 static void cf_close_failure_alert_box(const char *filename, int err);
149 static void ref_time_packets(capture_file *cf);
150 /* Update the progress bar this many times when reading a file. */
151 #define N_PROGBAR_UPDATES 100
152 /* We read around 200k/100ms don't update the progress bar more often than that */
153 #define MIN_QUANTUM 200000
154 #define MIN_NUMBER_OF_PACKET 1500
157 * We could probably use g_signal_...() instead of the callbacks below but that
158 * would require linking our CLI programs to libgobject and creating an object
159 * instance for the signals.
162 cf_callback_t cb_fct;
164 } cf_callback_data_t;
166 static GList *cf_callbacks = NULL;
169 cf_callback_invoke(int event, gpointer data)
171 cf_callback_data_t *cb;
172 GList *cb_item = cf_callbacks;
174 /* there should be at least one interested */
175 g_assert(cb_item != NULL);
177 while (cb_item != NULL) {
178 cb = (cf_callback_data_t *)cb_item->data;
179 cb->cb_fct(event, data, cb->user_data);
180 cb_item = g_list_next(cb_item);
186 cf_callback_add(cf_callback_t func, gpointer user_data)
188 cf_callback_data_t *cb;
190 cb = g_new(cf_callback_data_t,1);
192 cb->user_data = user_data;
194 cf_callbacks = g_list_prepend(cf_callbacks, cb);
198 cf_callback_remove(cf_callback_t func)
200 cf_callback_data_t *cb;
201 GList *cb_item = cf_callbacks;
203 while (cb_item != NULL) {
204 cb = (cf_callback_data_t *)cb_item->data;
205 if (cb->cb_fct == func) {
206 cf_callbacks = g_list_remove(cf_callbacks, cb);
210 cb_item = g_list_next(cb_item);
213 g_assert_not_reached();
217 cf_timestamp_auto_precision(capture_file *cf)
221 /* don't try to get the file's precision if none is opened */
222 if (cf->state == FILE_CLOSED) {
226 /* Set the column widths of those columns that show the time in
227 "command-line-specified" format. */
228 for (i = 0; i < cf->cinfo.num_cols; i++) {
229 if (col_has_time_fmt(&cf->cinfo, i)) {
230 packet_list_resize_column(i);
236 cf_get_computed_elapsed(capture_file *cf)
238 return cf->computed_elapsed;
242 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
245 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
250 g_get_current_time(&time_now);
252 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
253 time_now.tv_usec - start_time->tv_usec;
255 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
258 static const nstime_t *
259 ws_get_frame_ts(void *data, guint32 frame_num)
261 capture_file *cf = (capture_file *) data;
263 if (cf->prev_dis && cf->prev_dis->num == frame_num)
264 return &cf->prev_dis->abs_ts;
266 if (cf->prev_cap && cf->prev_cap->num == frame_num)
267 return &cf->prev_cap->abs_ts;
270 frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
272 return (fd) ? &fd->abs_ts : NULL;
279 ws_get_user_comment(void *data, const frame_data *fd)
281 capture_file *cf = (capture_file *) data;
283 return cf_get_user_packet_comment(cf, fd);
287 ws_epan_new(capture_file *cf)
289 epan_t *epan = epan_new();
292 epan->get_frame_ts = ws_get_frame_ts;
293 epan->get_interface_name = cap_file_get_interface_name;
294 epan->get_user_comment = ws_get_user_comment;
300 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
305 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
309 /* The open succeeded. Close whatever capture file we had open,
310 and fill in the information for this file. */
313 /* XXX - we really want to initialize this after we've read all
314 the packets, so we know how much we'll ultimately need. */
315 ws_buffer_init(&cf->buf, 1500);
317 /* Create new epan session for dissection.
318 * (The old one was freed in cf_close().)
320 cf->epan = ws_epan_new(cf);
322 /* We're about to start reading the file. */
323 cf->state = FILE_READ_IN_PROGRESS;
328 /* Set the file name because we need it to set the follow stream filter.
329 XXX - is that still true? We need it for other reasons, though,
331 cf->filename = g_strdup(fname);
333 /* Indicate whether it's a permanent or temporary file. */
334 cf->is_tempfile = is_tempfile;
336 /* No user changes yet. */
337 cf->unsaved_changes = FALSE;
339 cf->computed_elapsed = 0;
341 cf->cd_t = wtap_file_type_subtype(cf->wth);
342 cf->open_type = type;
343 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
345 cf->packet_comment_count = 0;
346 cf->displayed_count = 0;
347 cf->marked_count = 0;
348 cf->ignored_count = 0;
349 cf->ref_time_count = 0;
350 cf->drops_known = FALSE;
352 cf->snap = wtap_snapshot_length(cf->wth);
354 /* Snapshot length not known. */
355 cf->has_snap = FALSE;
356 cf->snap = WTAP_MAX_PACKET_SIZE;
360 /* Allocate a frame_data_sequence for the frames in this file */
361 cf->frames = new_frame_data_sequence();
363 nstime_set_zero(&cf->elapsed_time);
369 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
370 cf_timestamp_auto_precision(cf);
372 packet_list_queue_draw();
373 cf_callback_invoke(cf_cb_file_opened, cf);
375 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
376 /* tell the BER dissector the file name */
377 ber_set_filename(cf->filename);
380 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
381 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
386 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
391 * Add an encapsulation type to cf->linktypes.
394 cf_add_encapsulation_type(capture_file *cf, int encap)
398 for (i = 0; i < cf->linktypes->len; i++) {
399 if (g_array_index(cf->linktypes, gint, i) == encap)
400 return; /* it's already there */
402 /* It's not already there - add it. */
403 g_array_append_val(cf->linktypes, encap);
406 /* Reset everything to a pristine state */
408 cf_close(capture_file *cf)
410 if (cf->state == FILE_CLOSED)
411 return; /* Nothing to do */
413 /* Die if we're in the middle of reading a file. */
414 g_assert(cf->state != FILE_READ_IN_PROGRESS);
416 cf_callback_invoke(cf_cb_file_closing, cf);
418 /* close things, if not already closed before */
419 color_filters_cleanup();
425 /* We have no file open... */
426 if (cf->filename != NULL) {
427 /* If it's a temporary file, remove it. */
429 ws_unlink(cf->filename);
430 g_free(cf->filename);
433 /* ...which means we have no changes to that file to save. */
434 cf->unsaved_changes = FALSE;
436 /* no open_routine type */
437 cf->open_type = WTAP_TYPE_AUTO;
439 /* Free up the packet buffer. */
440 ws_buffer_free(&cf->buf);
442 dfilter_free(cf->rfcode);
444 if (cf->frames != NULL) {
445 free_frame_data_sequence(cf->frames);
448 #ifdef WANT_PACKET_EDITOR
449 if (cf->edited_frames) {
450 g_tree_destroy(cf->edited_frames);
451 cf->edited_frames = NULL;
454 if (cf->frames_user_comments) {
455 g_tree_destroy(cf->frames_user_comments);
456 cf->frames_user_comments = NULL;
458 cf_unselect_packet(cf); /* nothing to select */
459 cf->first_displayed = 0;
460 cf->last_displayed = 0;
462 /* No frames, no frame selected, no field in that frame selected. */
464 cf->current_frame = 0;
466 cf->finfo_selected = NULL;
468 /* No frame link-layer types, either. */
469 if (cf->linktypes != NULL) {
470 g_array_free(cf->linktypes, TRUE);
471 cf->linktypes = NULL;
474 /* Clear the packet list. */
475 packet_list_freeze();
480 nstime_set_zero(&cf->elapsed_time);
482 reset_tap_listeners();
487 /* We have no file open. */
488 cf->state = FILE_CLOSED;
490 cf_callback_invoke(cf_cb_file_closed, cf);
494 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
498 progbar_val = (gfloat) file_pos / (gfloat) size;
499 if (progbar_val > 1.0) {
501 /* The file probably grew while we were reading it.
502 * Update file size, and try again.
504 size = wtap_file_size(cf->wth, NULL);
507 progbar_val = (gfloat) file_pos / (gfloat) size;
509 /* If it's still > 1, either "wtap_file_size()" failed (in which
510 * case there's not much we can do about it), or the file
511 * *shrank* (in which case there's not much we can do about
512 * it); just clip the progress value at 1.0.
514 if (progbar_val > 1.0f)
518 g_snprintf(status_str, status_size,
519 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
520 file_pos / 1024, size / 1024);
526 cf_read(capture_file *cf, gboolean reloading)
531 progdlg_t *progbar = NULL;
536 volatile gboolean create_proto_tree;
540 /* Compile the current display filter.
541 * We assume this will not fail since cf->dfilter is only set in
542 * cf_filter IFF the filter was valid.
544 compiled = dfilter_compile(cf->dfilter, &dfcode);
545 g_assert(!cf->dfilter || (compiled && dfcode));
547 /* Get the union of the flags for all tap listeners. */
548 tap_flags = union_of_tap_listener_flags();
550 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
552 reset_tap_listeners();
554 name_ptr = g_filename_display_basename(cf->filename);
557 cf_callback_invoke(cf_cb_file_reload_started, cf);
559 cf_callback_invoke(cf_cb_file_read_started, cf);
561 /* Record whether the file is compressed.
562 XXX - do we know this at open time? */
563 cf->iscompressed = wtap_iscompressed(cf->wth);
565 /* The packet list window will be empty until the file is completly loaded */
566 packet_list_freeze();
569 g_get_current_time(&start_time);
571 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
575 int displayed_once = 0;
583 gint64 progbar_quantum;
584 gint64 progbar_nextstep;
586 gchar status_str[100];
590 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
592 /* Find the size of the file. */
593 size = wtap_file_size(cf->wth, NULL);
595 /* Update the progress bar when it gets to this value. */
596 progbar_nextstep = 0;
597 /* When we reach the value that triggers a progress bar update,
598 bump that value by this amount. */
600 progbar_quantum = size/N_PROGBAR_UPDATES;
601 if (progbar_quantum < MIN_QUANTUM)
602 progbar_quantum = MIN_QUANTUM;
606 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
609 file_pos = wtap_read_so_far(cf->wth);
611 /* Create the progress bar if necessary.
612 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
614 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
615 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
617 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
618 TRUE, &stop_flag, &start_time, progbar_val);
620 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
621 TRUE, &stop_flag, &start_time, progbar_val);
624 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
625 when we update it, we have to run the GTK+ main loop to get it
626 to repaint what's pending, and doing so may involve an "ioctl()"
627 to see if there's any pending input from an X server, and doing
628 that for every packet can be costly, especially on a big file. */
629 if (file_pos >= progbar_nextstep) {
630 if (progbar != NULL) {
631 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
632 /* update the packet bar content on the first run or frequently on very large files */
634 if (progbar_quantum > 500000 || displayed_once == 0) {
635 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
637 packets_bar_update();
640 #endif /* HAVE_LIBPCAP */
641 update_progress_dlg(progbar, progbar_val, status_str);
643 progbar_nextstep += progbar_quantum;
648 /* Well, the user decided to abort the read. He/She will be warned and
649 it might be enough for him/her to work with the already loaded
651 This is especially true for very large capture files, where you don't
652 want to wait loading the whole file (which may last minutes or even
653 hours even on fast machines) just to see that it was the wrong file. */
656 read_packet(cf, dfcode, &edt, cinfo, data_offset);
659 CATCH(OutOfMemoryError) {
660 simple_message_box(ESD_TYPE_ERROR, NULL,
661 "More information and workarounds can be found at\n"
662 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
663 "Sorry, but Wireshark has run out of memory and has to terminate now.");
665 /* Could we close the current capture and free up memory from that? */
667 /* we have to terminate, as we cannot recover from the memory error */
673 /* Free the display name */
676 /* Cleanup and release all dfilter resources */
677 if (dfcode != NULL) {
678 dfilter_free(dfcode);
681 epan_dissect_cleanup(&edt);
683 /* We're done reading the file; destroy the progress bar if it was created. */
685 destroy_progress_dlg(progbar);
687 /* We're done reading sequentially through the file. */
688 cf->state = FILE_READ_DONE;
690 /* Close the sequential I/O side, to free up memory it requires. */
691 wtap_sequential_close(cf->wth);
693 /* Allow the protocol dissectors to free up memory that they
694 * don't need after the sequential run-through of the packets. */
695 postseq_cleanup_all_protocols();
697 /* compute the time it took to load the file */
698 compute_elapsed(cf, &start_time);
700 /* Set the file encapsulation type now; we don't know what it is until
701 we've looked at all the packets, as we don't know until then whether
702 there's more than one type (and thus whether it's
703 WTAP_ENCAP_PER_PACKET). */
704 cf->lnk_t = wtap_file_encap(cf->wth);
706 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
711 cf_callback_invoke(cf_cb_file_reload_finished, cf);
713 cf_callback_invoke(cf_cb_file_read_finished, cf);
715 /* If we have any displayed packets to select, select the first of those
716 packets by making the first row the selected row. */
717 if (cf->first_displayed != 0) {
718 packet_list_select_first_row();
722 simple_message_box(ESD_TYPE_WARN, NULL,
723 "The remaining packets in the file were discarded.\n"
725 "As a lot of packets from the original file will be missing,\n"
726 "remember to be careful when saving the current content to a file.\n",
727 "File loading was cancelled.");
728 return CF_READ_ERROR;
732 /* Put up a message box noting that the read failed somewhere along
733 the line. Don't throw out the stuff we managed to read, though,
737 case WTAP_ERR_UNSUPPORTED:
738 simple_error_message_box(
739 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
744 case WTAP_ERR_UNSUPPORTED_ENCAP:
745 simple_error_message_box(
746 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
751 case WTAP_ERR_SHORT_READ:
752 simple_error_message_box(
753 "The capture file appears to have been cut short"
754 " in the middle of a packet.");
757 case WTAP_ERR_BAD_FILE:
758 simple_error_message_box(
759 "The capture file appears to be damaged or corrupt.\n(%s)",
764 case WTAP_ERR_DECOMPRESS:
765 simple_error_message_box(
766 "The compressed capture file appears to be damaged or corrupt.\n"
772 simple_error_message_box(
773 "An error occurred while reading the"
774 " capture file: %s.", wtap_strerror(err));
777 return CF_READ_ERROR;
784 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
787 volatile int newly_displayed_packets = 0;
790 gboolean create_proto_tree;
794 /* Compile the current display filter.
795 * We assume this will not fail since cf->dfilter is only set in
796 * cf_filter IFF the filter was valid.
798 compiled = dfilter_compile(cf->dfilter, &dfcode);
799 g_assert(!cf->dfilter || (compiled && dfcode));
801 /* Get the union of the flags for all tap listeners. */
802 tap_flags = union_of_tap_listener_flags();
804 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
808 packet_list_check_end();
809 /* Don't freeze/thaw the list when doing live capture */
810 /*packet_list_freeze();*/
812 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
814 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
817 gint64 data_offset = 0;
820 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
822 while (to_read != 0) {
823 wtap_cleareof(cf->wth);
824 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
827 if (cf->state == FILE_READ_ABORTED) {
828 /* Well, the user decided to exit Wireshark. Break out of the
829 loop, and let the code below (which is called even if there
830 aren't any packets left to read) exit. */
833 if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
834 newly_displayed_packets++;
839 CATCH(OutOfMemoryError) {
840 simple_message_box(ESD_TYPE_ERROR, NULL,
841 "More information and workarounds can be found at\n"
842 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
843 "Sorry, but Wireshark has run out of memory and has to terminate now.");
845 /* Could we close the current capture and free up memory from that? */
846 return CF_READ_ABORTED;
848 /* we have to terminate, as we cannot recover from the memory error */
854 /* Update the file encapsulation; it might have changed based on the
855 packets we've read. */
856 cf->lnk_t = wtap_file_encap(cf->wth);
858 /* Cleanup and release all dfilter resources */
859 if (dfcode != NULL) {
860 dfilter_free(dfcode);
863 epan_dissect_cleanup(&edt);
865 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
866 cf->count, cf->state, *err);*/
868 /* Don't freeze/thaw the list when doing live capture */
869 /*packet_list_thaw();*/
870 /* With the new packet list the first packet
871 * isn't automatically selected.
873 if (!cf->current_frame)
874 packet_list_select_first_row();
876 /* moving to the end of the packet list - if the user requested so and
877 we have some new packets. */
878 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
879 packet_list_moveto_end();
881 if (cf->state == FILE_READ_ABORTED) {
882 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
883 so that our caller can kill off the capture child process;
884 this will cause an EOF on the pipe from the child, so
885 "cf_finish_tail()" will be called, and it will clean up
887 return CF_READ_ABORTED;
888 } else if (*err != 0) {
889 /* We got an error reading the capture file.
890 XXX - pop up a dialog box instead? */
891 g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")",
892 wtap_strerror(*err), err_info, cf->filename);
895 return CF_READ_ERROR;
901 cf_fake_continue_tail(capture_file *cf) {
902 cf->state = FILE_READ_DONE;
906 cf_finish_tail(capture_file *cf, int *err)
913 gboolean create_proto_tree;
917 /* Compile the current display filter.
918 * We assume this will not fail since cf->dfilter is only set in
919 * cf_filter IFF the filter was valid.
921 compiled = dfilter_compile(cf->dfilter, &dfcode);
922 g_assert(!cf->dfilter || (compiled && dfcode));
924 /* Get the union of the flags for all tap listeners. */
925 tap_flags = union_of_tap_listener_flags();
926 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
928 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
930 if (cf->wth == NULL) {
932 return CF_READ_ERROR;
935 packet_list_check_end();
936 /* Don't freeze/thaw the list when doing live capture */
937 /*packet_list_freeze();*/
939 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
941 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
942 if (cf->state == FILE_READ_ABORTED) {
943 /* Well, the user decided to abort the read. Break out of the
944 loop, and let the code below (which is called even if there
945 aren't any packets left to read) exit. */
948 read_packet(cf, dfcode, &edt, cinfo, data_offset);
951 /* Cleanup and release all dfilter resources */
952 if (dfcode != NULL) {
953 dfilter_free(dfcode);
956 epan_dissect_cleanup(&edt);
958 /* Don't freeze/thaw the list when doing live capture */
959 /*packet_list_thaw();*/
961 if (cf->state == FILE_READ_ABORTED) {
962 /* Well, the user decided to abort the read. We're only called
963 when the child capture process closes the pipe to us (meaning
964 it's probably exited), so we can just close the capture
965 file; we return CF_READ_ABORTED so our caller can do whatever
966 is appropriate when that happens. */
968 return CF_READ_ABORTED;
971 if (auto_scroll_live && cf->count != 0)
972 packet_list_moveto_end();
974 /* We're done reading sequentially through the file. */
975 cf->state = FILE_READ_DONE;
977 /* We're done reading sequentially through the file; close the
978 sequential I/O side, to free up memory it requires. */
979 wtap_sequential_close(cf->wth);
981 /* Allow the protocol dissectors to free up memory that they
982 * don't need after the sequential run-through of the packets. */
983 postseq_cleanup_all_protocols();
985 /* Update the file encapsulation; it might have changed based on the
986 packets we've read. */
987 cf->lnk_t = wtap_file_encap(cf->wth);
989 /* Update the details in the file-set dialog, as the capture file
990 * has likely grown since we first stat-ed it */
991 fileset_update_file(cf->filename);
994 /* We got an error reading the capture file.
995 XXX - pop up a dialog box? */
997 g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")",
998 wtap_strerror(*err), err_info, cf->filename);
1000 return CF_READ_ERROR;
1005 #endif /* HAVE_LIBPCAP */
1008 cf_get_display_name(capture_file *cf)
1012 /* Return a name to use in displays */
1013 if (!cf->is_tempfile) {
1014 /* Get the last component of the file name, and use that. */
1016 displayname = g_filename_display_basename(cf->filename);
1018 displayname=g_strdup("(No file)");
1021 /* The file we read is a temporary file from a live capture or
1022 a merge operation; we don't mention its name, but, if it's
1023 from a capture, give the source of the capture. */
1025 displayname = g_strdup(cf->source);
1027 displayname = g_strdup("(Untitled)");
1033 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1039 cf->source = g_strdup(source);
1041 cf->source = g_strdup("");
1045 const gchar *cf_get_tempfile_source(capture_file *cf) {
1053 /* XXX - use a macro instead? */
1055 cf_get_packet_count(capture_file *cf)
1060 /* XXX - use a macro instead? */
1062 cf_set_packet_count(capture_file *cf, int packet_count)
1064 cf->count = packet_count;
1067 /* XXX - use a macro instead? */
1069 cf_is_tempfile(capture_file *cf)
1071 return cf->is_tempfile;
1074 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1076 cf->is_tempfile = is_tempfile;
1080 /* XXX - use a macro instead? */
1081 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1083 cf->drops_known = drops_known;
1086 /* XXX - use a macro instead? */
1087 void cf_set_drops(capture_file *cf, guint32 drops)
1092 /* XXX - use a macro instead? */
1093 gboolean cf_get_drops_known(capture_file *cf)
1095 return cf->drops_known;
1098 /* XXX - use a macro instead? */
1099 guint32 cf_get_drops(capture_file *cf)
1104 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1106 cf->rfcode = rfcode;
1110 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1111 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1112 struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1116 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1117 &cf->ref, cf->prev_dis);
1118 cf->prev_cap = fdata;
1120 if (dfcode != NULL) {
1121 epan_dissect_prime_dfilter(edt, dfcode);
1124 /* Dissect the frame. */
1125 epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1127 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1128 if (dfcode != NULL) {
1129 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1131 if (fdata->flags.passed_dfilter) {
1132 /* This frame passed the display filter but it may depend on other
1133 * (potentially not displayed) frames. Find those frames and mark them
1136 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
1139 fdata->flags.passed_dfilter = 1;
1141 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1142 cf->displayed_count++;
1144 if (add_to_packet_list) {
1145 /* We fill the needed columns from new_packet_list */
1146 row = packet_list_append(cinfo, fdata);
1149 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1151 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1152 cf->prev_dis = fdata;
1154 /* If we haven't yet seen the first frame, this is it.
1156 XXX - we must do this before we add the row to the display,
1157 as, if the display's GtkCList's selection mode is
1158 GTK_SELECTION_BROWSE, when the first entry is added to it,
1159 "cf_select_packet()" will be called, and it will fetch the row
1160 data for the 0th row, and will get a null pointer rather than
1161 "fdata", as "gtk_clist_append()" won't yet have returned and
1162 thus "gtk_clist_set_row_data()" won't yet have been called.
1164 We thus need to leave behind bread crumbs so that
1165 "cf_select_packet()" can find this frame. See the comment
1166 in "cf_select_packet()". */
1167 if (cf->first_displayed == 0)
1168 cf->first_displayed = fdata->num;
1170 /* This is the last frame we've seen so far. */
1171 cf->last_displayed = fdata->num;
1174 epan_dissect_reset(edt);
1178 /* read in a new packet */
1179 /* returns the row of the new packet in the packet list or -1 if not displayed */
1181 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1182 column_info *cinfo, gint64 offset)
1184 struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1185 const guint8 *buf = wtap_buf_ptr(cf->wth);
1192 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1193 it's not already there.
1194 XXX - yes, this is O(N), so if every packet had a different
1195 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1196 there are probably going to be a small number of encapsulation types
1198 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1200 /* The frame number of this packet is one more than the count of
1201 frames in the file so far. */
1202 framenum = cf->count + 1;
1204 frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1208 epan_dissect_t rf_edt;
1210 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1211 epan_dissect_prime_dfilter(&rf_edt, cf->rfcode);
1212 epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1213 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1214 epan_dissect_cleanup(&rf_edt);
1218 /* This does a shallow copy of fdlocal, which is good enough. */
1219 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1222 if (phdr->opt_comment != NULL)
1223 cf->packet_comment_count++;
1224 cf->f_datalen = offset + fdlocal.cap_len;
1226 if (!cf->redissecting) {
1227 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1228 cinfo, phdr, buf, TRUE);
1236 cf_merge_files(char **out_filenamep, int in_file_count,
1237 char *const *in_filenames, int file_type, gboolean do_append)
1239 merge_in_file_t *in_files, *in_file;
1244 int open_err, read_err, write_err, close_err;
1248 gboolean got_read_error = FALSE, got_write_error = FALSE;
1250 progdlg_t *progbar = NULL;
1252 gint64 f_len, file_pos;
1254 GTimeVal start_time;
1255 gchar status_str[100];
1256 gint64 progbar_nextstep;
1257 gint64 progbar_quantum;
1258 gchar *display_basename;
1259 int selected_frame_type;
1260 gboolean fake_interface_ids = FALSE;
1262 /* open the input files */
1263 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1264 &open_err, &err_info, &err_fileno)) {
1266 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1271 if (*out_filenamep != NULL) {
1272 out_filename = *out_filenamep;
1273 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1277 out_fd = create_tempfile(&tmpname, "wireshark");
1280 out_filename = g_strdup(tmpname);
1281 *out_filenamep = out_filename;
1285 merge_close_in_files(in_file_count, in_files);
1287 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1291 selected_frame_type = merge_select_frame_type(in_file_count, in_files);
1293 /* If we are trying to merge a number of libpcap files with different encapsulation types
1294 * change the output file type to pcapng and create SHB and IDB:s for the new file use the
1295 * interface index stored in in_files per file to change the phdr before writing the datablock.
1296 * XXX should it be an option to convert to pcapng?
1298 * We need something similar when merging pcapng files possibly with an option to say
1299 * the same interface(s) used in all in files. SHBs comments should be merged together.
1301 if ((selected_frame_type == WTAP_ENCAP_PER_PACKET)&&(file_type == WTAP_FILE_TYPE_SUBTYPE_PCAP)) {
1302 /* Write output in pcapng format */
1303 wtapng_section_t *shb_hdr;
1304 wtapng_iface_descriptions_t *idb_inf, *idb_inf_merge_file;
1305 wtapng_if_descr_t int_data, *file_int_data;
1306 GString *comment_gstr;
1308 fake_interface_ids = TRUE;
1309 /* Create SHB info */
1310 shb_hdr = wtap_file_get_shb_info(in_files[0].wth);
1311 comment_gstr = g_string_new("");
1312 g_string_append_printf(comment_gstr, "%s \n",shb_hdr->opt_comment);
1313 g_string_append_printf(comment_gstr, "File created by merging: \n");
1314 file_type = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
1316 for (i = 0; i < in_file_count; i++) {
1317 g_string_append_printf(comment_gstr, "File%d: %s \n",i+1,in_files[i].filename);
1319 shb_hdr->section_length = -1;
1321 shb_hdr->opt_comment = g_string_free(comment_gstr, FALSE); /* NULL if not available */
1322 shb_hdr->shb_hardware = NULL; /* NULL if not available, UTF-8 string containing the */
1323 /* description of the hardware used to create this section. */
1324 shb_hdr->shb_os = NULL; /* NULL if not available, UTF-8 string containing the name */
1325 /* of the operating system used to create this section. */
1326 shb_hdr->shb_user_appl = g_strdup("Wireshark"); /* NULL if not available, UTF-8 string containing the name */
1327 /* of the application used to create this section. */
1329 /* create fake IDB info */
1330 idb_inf = g_new(wtapng_iface_descriptions_t,1);
1331 /* TODO make this the number of DIFFERENT encapsulation types
1332 * check that snaplength is the same too?
1334 idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1336 for (i = 0; i < in_file_count; i++) {
1337 idb_inf_merge_file = wtap_file_get_idb_info(in_files[i].wth);
1338 /* read the interface data from the in file to our combined interfca data */
1339 file_int_data = &g_array_index (idb_inf_merge_file->interface_data, wtapng_if_descr_t, 0);
1340 int_data.wtap_encap = file_int_data->wtap_encap;
1341 int_data.time_units_per_second = file_int_data->time_units_per_second;
1342 int_data.link_type = file_int_data->link_type;
1343 int_data.snap_len = file_int_data->snap_len;
1344 int_data.if_name = g_strdup(file_int_data->if_name);
1345 int_data.opt_comment = NULL;
1346 int_data.if_description = NULL;
1347 int_data.if_speed = 0;
1348 int_data.if_tsresol = 6;
1349 int_data.if_filter_str = NULL;
1350 int_data.bpf_filter_len = 0;
1351 int_data.if_filter_bpf_bytes = NULL;
1352 int_data.if_os = NULL;
1353 int_data.if_fcslen = -1;
1354 int_data.num_stat_entries = 0; /* Number of ISB:s */
1355 int_data.interface_statistics = NULL;
1357 g_array_append_val(idb_inf->interface_data, int_data);
1358 g_free(idb_inf_merge_file);
1360 /* Set fake interface Id in per file data */
1361 in_files[i].interface_id = i;
1364 pdh = wtap_dump_fdopen_ng(out_fd, file_type,
1365 selected_frame_type,
1366 merge_max_snapshot_length(in_file_count, in_files),
1367 FALSE /* compressed */, shb_hdr, idb_inf /* wtapng_iface_descriptions_t *idb_inf */, &open_err);
1371 merge_close_in_files(in_file_count, in_files);
1373 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1380 pdh = wtap_dump_fdopen(out_fd, file_type,
1381 selected_frame_type,
1382 merge_max_snapshot_length(in_file_count, in_files),
1383 FALSE /* compressed */, &open_err);
1386 merge_close_in_files(in_file_count, in_files);
1388 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1394 /* Get the sum of the sizes of all the files. */
1396 for (i = 0; i < in_file_count; i++)
1397 f_len += in_files[i].size;
1399 /* Update the progress bar when it gets to this value. */
1400 progbar_nextstep = 0;
1401 /* When we reach the value that triggers a progress bar update,
1402 bump that value by this amount. */
1403 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1404 /* Progress so far. */
1408 g_get_current_time(&start_time);
1410 /* do the merge (or append) */
1413 in_file = merge_append_read_packet(in_file_count, in_files, &read_err,
1416 in_file = merge_read_packet(in_file_count, in_files, &read_err,
1418 if (in_file == NULL) {
1423 if (read_err != 0) {
1424 /* I/O error reading from in_file */
1425 got_read_error = TRUE;
1429 /* Get the sum of the data offsets in all of the files. */
1431 for (i = 0; i < in_file_count; i++)
1432 data_offset += in_files[i].data_offset;
1434 /* Create the progress bar if necessary.
1435 We check on every iteration of the loop, so that it takes no
1436 longer than the standard time to create it (otherwise, for a
1437 large file, we might take considerably longer than that standard
1438 time in order to get to the next progress bar step). */
1439 if (progbar == NULL) {
1440 progbar = delayed_create_progress_dlg(NULL, "Merging", "files",
1441 FALSE, &stop_flag, &start_time, progbar_val);
1444 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1445 when we update it, we have to run the GTK+ main loop to get it
1446 to repaint what's pending, and doing so may involve an "ioctl()"
1447 to see if there's any pending input from an X server, and doing
1448 that for every packet can be costly, especially on a big file. */
1449 if (data_offset >= progbar_nextstep) {
1450 /* Get the sum of the seek positions in all of the files. */
1452 for (i = 0; i < in_file_count; i++)
1453 file_pos += wtap_read_so_far(in_files[i].wth);
1454 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1455 if (progbar_val > 1.0f) {
1456 /* Some file probably grew while we were reading it.
1457 That "shouldn't happen", so we'll just clip the progress
1461 if (progbar != NULL) {
1462 g_snprintf(status_str, sizeof(status_str),
1463 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1464 file_pos / 1024, f_len / 1024);
1465 update_progress_dlg(progbar, progbar_val, status_str);
1467 progbar_nextstep += progbar_quantum;
1471 /* Well, the user decided to abort the merge. */
1475 /* If we have WTAP_ENCAP_PER_PACKET and the infiles are of type
1476 * WTAP_FILE_TYPE_SUBTYPE_PCAP, we need to set the interface id
1477 * in the paket header = the interface index we used in the IDBs
1478 * interface description for this file(encapsulation type).
1480 if (fake_interface_ids) {
1481 struct wtap_pkthdr *phdr;
1483 phdr = wtap_phdr(in_file->wth);
1484 phdr->interface_id = in_file->interface_id;
1485 phdr->presence_flags = phdr->presence_flags | WTAP_HAS_INTERFACE_ID;
1487 if (!wtap_dump(pdh, wtap_phdr(in_file->wth),
1488 wtap_buf_ptr(in_file->wth), &write_err)) {
1489 got_write_error = TRUE;
1494 /* We're done merging the files; destroy the progress bar if it was created. */
1495 if (progbar != NULL)
1496 destroy_progress_dlg(progbar);
1498 merge_close_in_files(in_file_count, in_files);
1499 if (!got_write_error) {
1500 if (!wtap_dump_close(pdh, &write_err))
1501 got_write_error = TRUE;
1504 * We already got a write error; no need to report another
1505 * write error on close.
1507 * Don't overwrite the earlier write error.
1509 (void)wtap_dump_close(pdh, &close_err);
1512 if (got_read_error) {
1514 * Find the file on which we got the error, and report the error.
1516 for (i = 0; i < in_file_count; i++) {
1517 if (in_files[i].state == GOT_ERROR) {
1518 /* Put up a message box noting that a read failed somewhere along
1520 display_basename = g_filename_display_basename(in_files[i].filename);
1523 case WTAP_ERR_UNSUPPORTED_ENCAP:
1524 simple_error_message_box(
1525 "The capture file %s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1526 display_basename, err_info);
1530 case WTAP_ERR_SHORT_READ:
1531 simple_error_message_box(
1532 "The capture file %s appears to have been cut short"
1533 " in the middle of a packet.", display_basename);
1536 case WTAP_ERR_BAD_FILE:
1537 simple_error_message_box(
1538 "The capture file %s appears to be damaged or corrupt.\n(%s)",
1539 display_basename, err_info);
1543 case WTAP_ERR_DECOMPRESS:
1544 simple_error_message_box(
1545 "The compressed capture file %s appears to be damaged or corrupt.\n"
1546 "(%s)", display_basename, err_info);
1551 simple_error_message_box(
1552 "An error occurred while reading the"
1553 " capture file %s: %s.",
1554 display_basename, wtap_strerror(read_err));
1557 g_free(display_basename);
1562 if (got_write_error) {
1563 /* Put up an alert box for the write error. */
1564 if (write_err < 0) {
1565 /* Wiretap error. */
1566 switch (write_err) {
1568 case WTAP_ERR_UNSUPPORTED_ENCAP:
1570 * This is a problem with the particular frame we're writing and
1571 * the file type and subtype we're writing; note that, and report
1572 * the frame number and file type/subtype.
1574 display_basename = g_filename_display_basename(in_file ? in_file->filename : "UNKNOWN");
1575 simple_error_message_box(
1576 "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.",
1577 in_file ? in_file->packet_num : 0, display_basename,
1578 wtap_file_type_subtype_string(file_type));
1579 g_free(display_basename);
1582 case WTAP_ERR_PACKET_TOO_LARGE:
1584 * This is a problem with the particular frame we're writing and
1585 * the file type and subtype we're writing; note that, and report
1586 * the frame number and file type/subtype.
1588 display_basename = g_filename_display_basename(in_file ? in_file->filename : "UNKNOWN");
1589 simple_error_message_box(
1590 "Frame %u of \"%s\" is too large for a \"%s\" file.",
1591 in_file ? in_file->packet_num : 0, display_basename,
1592 wtap_file_type_subtype_string(file_type));
1593 g_free(display_basename);
1597 display_basename = g_filename_display_basename(out_filename);
1598 simple_error_message_box(
1599 "An error occurred while writing to the file \"%s\": %s.",
1600 out_filename, wtap_strerror(write_err));
1601 g_free(display_basename);
1606 write_failure_alert_box(out_filename, write_err);
1610 if (got_read_error || got_write_error || stop_flag) {
1611 /* Callers aren't expected to treat an error or an explicit abort
1612 differently - we put up error dialogs ourselves, so they don't
1620 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1622 const char *filter_new = dftext ? dftext : "";
1623 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1625 GTimeVal start_time;
1627 /* if new filter equals old one, do nothing unless told to do so */
1628 if (!force && strcmp(filter_new, filter_old) == 0) {
1634 if (dftext == NULL) {
1635 /* The new filter is an empty filter (i.e., display all packets).
1636 * so leave dfcode==NULL
1640 * We have a filter; make a copy of it (as we'll be saving it),
1641 * and try to compile it.
1643 dftext = g_strdup(dftext);
1644 if (!dfilter_compile(dftext, &dfcode)) {
1645 /* The attempt failed; report an error. */
1646 simple_message_box(ESD_TYPE_ERROR, NULL,
1647 "See the help for a description of the display filter syntax.",
1648 "\"%s\" isn't a valid display filter: %s",
1649 dftext, dfilter_error_msg);
1655 if (dfcode == NULL) {
1656 /* Yes - free the filter text, and set it to null. */
1662 /* We have a valid filter. Replace the current filter. */
1663 g_free(cf->dfilter);
1664 cf->dfilter = dftext;
1665 g_get_current_time(&start_time);
1668 /* Now rescan the packet list, applying the new filter, but not
1669 throwing away information constructed on a previous pass. */
1670 if (dftext == NULL) {
1671 rescan_packets(cf, "Resetting", "Filter", FALSE);
1673 rescan_packets(cf, "Filtering", dftext, FALSE);
1676 /* Cleanup and release all dfilter resources */
1677 dfilter_free(dfcode);
1683 cf_reftime_packets(capture_file *cf)
1685 ref_time_packets(cf);
1689 cf_redissect_packets(capture_file *cf)
1691 if (cf->state != FILE_CLOSED) {
1692 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1697 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1698 struct wtap_pkthdr *phdr, Buffer *buf)
1702 gchar *display_basename;
1704 #ifdef WANT_PACKET_EDITOR
1705 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1706 if (G_UNLIKELY(fdata->file_off == -1)) {
1707 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1710 simple_error_message_box("fdata->file_off == -1, but can't find modified frame.");
1714 *phdr = frame->phdr;
1715 ws_buffer_assure_space(buf, frame->phdr.caplen);
1716 memcpy(ws_buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
1721 if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1722 display_basename = g_filename_display_basename(cf->filename);
1725 case WTAP_ERR_UNSUPPORTED_ENCAP:
1726 simple_error_message_box("The file \"%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
1727 display_basename, err_info);
1731 case WTAP_ERR_BAD_FILE:
1732 simple_error_message_box("An error occurred while reading from the file \"%s\": %s.\n(%s)",
1733 display_basename, wtap_strerror(err), err_info);
1738 simple_error_message_box(
1739 "An error occurred while reading from the file \"%s\": %s.",
1740 display_basename, wtap_strerror(err));
1743 g_free(display_basename);
1750 cf_read_record(capture_file *cf, frame_data *fdata)
1752 return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1755 /* Rescan the list of packets, reconstructing the CList.
1757 "action" describes why we're doing this; it's used in the progress
1760 "action_item" describes what we're doing; it's used in the progress
1763 "redissect" is TRUE if we need to make the dissectors reconstruct
1764 any state information they have (because a preference that affects
1765 some dissector has changed, meaning some dissector might construct
1766 its state differently from the way it was constructed the last time). */
1768 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1770 /* Rescan packets new packet list */
1773 progdlg_t *progbar = NULL;
1776 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1777 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1778 gboolean selected_frame_seen;
1780 GTimeVal start_time;
1781 gchar status_str[100];
1782 int progbar_nextstep;
1783 int progbar_quantum;
1787 gboolean create_proto_tree;
1789 gboolean add_to_packet_list = FALSE;
1791 guint32 frames_count;
1793 /* Compile the current display filter.
1794 * We assume this will not fail since cf->dfilter is only set in
1795 * cf_filter IFF the filter was valid.
1797 compiled = dfilter_compile(cf->dfilter, &dfcode);
1798 g_assert(!cf->dfilter || (compiled && dfcode));
1800 /* Get the union of the flags for all tap listeners. */
1801 tap_flags = union_of_tap_listener_flags();
1802 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1804 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
1806 reset_tap_listeners();
1807 /* Which frame, if any, is the currently selected frame?
1808 XXX - should the selected frame or the focus frame be the "current"
1809 frame, that frame being the one from which "Find Frame" searches
1811 selected_frame = cf->current_frame;
1813 /* Mark frame num as not found */
1814 selected_frame_num = -1;
1816 /* Freeze the packet list while we redo it, so we don't get any
1817 screen updates while it happens. */
1818 packet_list_freeze();
1821 /* We need to re-initialize all the state information that protocols
1822 keep, because some preference that controls a dissector has changed,
1823 which might cause the state information to be constructed differently
1824 by that dissector. */
1826 /* We might receive new packets while redissecting, and we don't
1827 want to dissect those before their time. */
1828 cf->redissecting = TRUE;
1830 /* 'reset' dissection session */
1831 epan_free(cf->epan);
1832 cf->epan = ws_epan_new(cf);
1833 cf->cinfo.epan = cf->epan;
1835 /* We need to redissect the packets so we have to discard our old
1836 * packet list store. */
1837 packet_list_clear();
1838 add_to_packet_list = TRUE;
1841 /* We don't yet know which will be the first and last frames displayed. */
1842 cf->first_displayed = 0;
1843 cf->last_displayed = 0;
1845 /* We currently don't display any packets */
1846 cf->displayed_count = 0;
1848 /* Iterate through the list of frames. Call a routine for each frame
1849 to check whether it should be displayed and, if so, add it to
1850 the display list. */
1852 cf->prev_dis = NULL;
1853 cf->prev_cap = NULL;
1856 /* Update the progress bar when it gets to this value. */
1857 progbar_nextstep = 0;
1858 /* When we reach the value that triggers a progress bar update,
1859 bump that value by this amount. */
1860 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1861 /* Count of packets at which we've looked. */
1863 /* Progress so far. */
1867 g_get_current_time(&start_time);
1869 /* no previous row yet */
1870 prev_frame_num = -1;
1873 preceding_frame_num = -1;
1874 preceding_frame = NULL;
1875 following_frame_num = -1;
1876 following_frame = NULL;
1878 selected_frame_seen = FALSE;
1880 frames_count = cf->count;
1882 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1884 for (framenum = 1; framenum <= frames_count; framenum++) {
1885 fdata = frame_data_sequence_find(cf->frames, framenum);
1887 /* Create the progress bar if necessary.
1888 We check on every iteration of the loop, so that it takes no
1889 longer than the standard time to create it (otherwise, for a
1890 large file, we might take considerably longer than that standard
1891 time in order to get to the next progress bar step). */
1892 if (progbar == NULL)
1893 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1894 &stop_flag, &start_time,
1897 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1898 when we update it, we have to run the GTK+ main loop to get it
1899 to repaint what's pending, and doing so may involve an "ioctl()"
1900 to see if there's any pending input from an X server, and doing
1901 that for every packet can be costly, especially on a big file. */
1902 if (count >= progbar_nextstep) {
1903 /* let's not divide by zero. I should never be started
1904 * with count == 0, so let's assert that
1906 g_assert(cf->count > 0);
1907 progbar_val = (gfloat) count / frames_count;
1909 if (progbar != NULL) {
1910 g_snprintf(status_str, sizeof(status_str),
1911 "%4u of %u frames", count, frames_count);
1912 update_progress_dlg(progbar, progbar_val, status_str);
1915 progbar_nextstep += progbar_quantum;
1919 /* Well, the user decided to abort the filtering. Just stop.
1921 XXX - go back to the previous filter? Users probably just
1922 want not to wait for a filtering operation to finish;
1923 unless we cancel by having no filter, reverting to the
1924 previous filter will probably be even more expensive than
1925 continuing the filtering, as it involves going back to the
1926 beginning and filtering, and even with no filter we currently
1927 have to re-generate the entire clist, which is also expensive.
1929 I'm not sure what Network Monitor does, but it doesn't appear
1930 to give you an unfiltered display if you cancel. */
1937 /* Since all state for the frame was destroyed, mark the frame
1938 * as not visited, free the GSList referring to the state
1939 * data (the per-frame data itself was freed by
1940 * "init_dissection()"), and null out the GSList pointer. */
1941 frame_data_reset(fdata);
1942 frames_count = cf->count;
1945 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1946 fdata->flags.dependent_of_displayed = 0;
1948 if (!cf_read_record(cf, fdata))
1949 break; /* error reading the frame */
1951 /* If the previous frame is displayed, and we haven't yet seen the
1952 selected frame, remember that frame - it's the closest one we've
1953 yet seen before the selected frame. */
1954 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1955 preceding_frame_num = prev_frame_num;
1956 preceding_frame = prev_frame;
1959 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1961 ws_buffer_start_ptr(&cf->buf),
1962 add_to_packet_list);
1964 /* If this frame is displayed, and this is the first frame we've
1965 seen displayed after the selected frame, remember this frame -
1966 it's the closest one we've yet seen at or after the selected
1968 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1969 following_frame_num = fdata->num;
1970 following_frame = fdata;
1972 if (fdata == selected_frame) {
1973 selected_frame_seen = TRUE;
1974 if (fdata->flags.passed_dfilter)
1975 selected_frame_num = fdata->num;
1978 /* Remember this frame - it'll be the previous frame
1979 on the next pass through the loop. */
1980 prev_frame_num = fdata->num;
1984 epan_dissect_cleanup(&edt);
1986 /* We are done redissecting the packet list. */
1987 cf->redissecting = FALSE;
1990 frames_count = cf->count;
1991 /* Clear out what remains of the visited flags and per-frame data
1994 XXX - that may cause various forms of bogosity when dissecting
1995 these frames, as they won't have been seen by this sequential
1996 pass, but the only alternative I see is to keep scanning them
1997 even though the user requested that the scan stop, and that
1998 would leave the user stuck with an Wireshark grinding on
1999 until it finishes. Should we just stick them with that? */
2000 for (; framenum <= frames_count; framenum++) {
2001 fdata = frame_data_sequence_find(cf->frames, framenum);
2002 frame_data_reset(fdata);
2006 /* We're done filtering the packets; destroy the progress bar if it
2008 if (progbar != NULL)
2009 destroy_progress_dlg(progbar);
2011 /* Unfreeze the packet list. */
2012 if (!add_to_packet_list)
2013 packet_list_recreate_visible_rows();
2015 /* Compute the time it took to filter the file */
2016 compute_elapsed(cf, &start_time);
2020 if (selected_frame_num == -1) {
2021 /* The selected frame didn't pass the filter. */
2022 if (selected_frame == NULL) {
2023 /* That's because there *was* no selected frame. Make the first
2024 displayed frame the current frame. */
2025 selected_frame_num = 0;
2027 /* Find the nearest displayed frame to the selected frame (whether
2028 it's before or after that frame) and make that the current frame.
2029 If the next and previous displayed frames are equidistant from the
2030 selected frame, choose the next one. */
2031 g_assert(following_frame == NULL ||
2032 following_frame->num >= selected_frame->num);
2033 g_assert(preceding_frame == NULL ||
2034 preceding_frame->num <= selected_frame->num);
2035 if (following_frame == NULL) {
2036 /* No frame after the selected frame passed the filter, so we
2037 have to select the last displayed frame before the selected
2039 selected_frame_num = preceding_frame_num;
2040 selected_frame = preceding_frame;
2041 } else if (preceding_frame == NULL) {
2042 /* No frame before the selected frame passed the filter, so we
2043 have to select the first displayed frame after the selected
2045 selected_frame_num = following_frame_num;
2046 selected_frame = following_frame;
2048 /* Frames before and after the selected frame passed the filter, so
2049 we'll select the previous frame */
2050 selected_frame_num = preceding_frame_num;
2051 selected_frame = preceding_frame;
2056 if (selected_frame_num == -1) {
2057 /* There are no frames displayed at all. */
2058 cf_unselect_packet(cf);
2060 /* Either the frame that was selected passed the filter, or we've
2061 found the nearest displayed frame to that frame. Select it, make
2062 it the focus row, and make it visible. */
2063 /* Set to invalid to force update of packet list and packet details */
2064 cf->current_row = -1;
2065 if (selected_frame_num == 0) {
2066 packet_list_select_first_row();
2068 if (!packet_list_select_row_from_data(selected_frame)) {
2069 /* We didn't find a row corresponding to this frame.
2070 This means that the frame isn't being displayed currently,
2071 so we can't select it. */
2072 simple_message_box(ESD_TYPE_INFO, NULL,
2073 "The capture file is probably not fully dissected.",
2074 "End of capture exceeded.");
2079 /* Cleanup and release all dfilter resources */
2080 dfilter_free(dfcode);
2085 * Scan trough all frame data and recalculate the ref time
2086 * without rereading the file.
2087 * XXX - do we need a progres bar or is this fast enough?
2090 ref_time_packets(capture_file *cf)
2097 cf->prev_dis = NULL;
2100 for (framenum = 1; framenum <= cf->count; framenum++) {
2101 fdata = frame_data_sequence_find(cf->frames, framenum);
2103 /* just add some value here until we know if it is being displayed or not */
2104 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
2110 /* If we don't have the time stamp of the first packet in the
2111 capture, it's because this is the first packet. Save the time
2112 stamp of this packet as the time stamp of the first packet. */
2113 if (cf->ref == NULL)
2115 /* if this frames is marked as a reference time frame, reset
2116 firstsec and firstusec to this frame */
2117 if (fdata->flags.ref_time)
2120 /* If we don't have the time stamp of the previous displayed packet,
2121 it's because this is the first displayed packet. Save the time
2122 stamp of this packet as the time stamp of the previous displayed
2124 if (cf->prev_dis == NULL) {
2125 cf->prev_dis = fdata;
2128 /* Get the time elapsed between the first packet and this packet. */
2129 fdata->frame_ref_num = (fdata != cf->ref) ? cf->ref->num : 0;
2130 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->ref->abs_ts);
2132 /* If it's greater than the current elapsed time, set the elapsed time
2133 to it (we check for "greater than" so as not to be confused by
2134 time moving backwards). */
2135 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
2136 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
2137 cf->elapsed_time = rel_ts;
2140 /* If this frame is displayed, get the time elapsed between the
2141 previous displayed packet and this packet. */
2142 if ( fdata->flags.passed_dfilter ) {
2143 fdata->prev_dis_num = cf->prev_dis->num;
2144 cf->prev_dis = fdata;
2150 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
2151 /* This frame either passed the display filter list or is marked as
2152 a time reference frame. All time reference frames are displayed
2153 even if they don't pass the display filter */
2154 if (fdata->flags.ref_time) {
2155 /* if this was a TIME REF frame we should reset the cum_bytes field */
2156 cf->cum_bytes = fdata->pkt_len;
2157 fdata->cum_bytes = cf->cum_bytes;
2159 /* increase cum_bytes with this packets length */
2160 cf->cum_bytes += fdata->pkt_len;
2173 process_specified_records(capture_file *cf, packet_range_t *range,
2174 const char *string1, const char *string2, gboolean terminate_is_stop,
2175 gboolean (*callback)(capture_file *, frame_data *,
2176 struct wtap_pkthdr *, const guint8 *, void *),
2177 void *callback_args)
2182 psp_return_t ret = PSP_FINISHED;
2184 progdlg_t *progbar = NULL;
2187 gboolean progbar_stop_flag;
2188 GTimeVal progbar_start_time;
2189 gchar progbar_status_str[100];
2190 int progbar_nextstep;
2191 int progbar_quantum;
2192 range_process_e process_this;
2193 struct wtap_pkthdr phdr;
2195 memset(&phdr, 0, sizeof(struct wtap_pkthdr));
2196 ws_buffer_init(&buf, 1500);
2198 /* Update the progress bar when it gets to this value. */
2199 progbar_nextstep = 0;
2200 /* When we reach the value that triggers a progress bar update,
2201 bump that value by this amount. */
2202 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2203 /* Count of packets at which we've looked. */
2205 /* Progress so far. */
2208 progbar_stop_flag = FALSE;
2209 g_get_current_time(&progbar_start_time);
2212 packet_range_process_init(range);
2214 /* Iterate through all the packets, printing the packets that
2215 were selected by the current display filter. */
2216 for (framenum = 1; framenum <= cf->count; framenum++) {
2217 fdata = frame_data_sequence_find(cf->frames, framenum);
2219 /* Create the progress bar if necessary.
2220 We check on every iteration of the loop, so that it takes no
2221 longer than the standard time to create it (otherwise, for a
2222 large file, we might take considerably longer than that standard
2223 time in order to get to the next progress bar step). */
2224 if (progbar == NULL)
2225 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2228 &progbar_start_time,
2231 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2232 when we update it, we have to run the GTK+ main loop to get it
2233 to repaint what's pending, and doing so may involve an "ioctl()"
2234 to see if there's any pending input from an X server, and doing
2235 that for every packet can be costly, especially on a big file. */
2236 if (progbar_count >= progbar_nextstep) {
2237 /* let's not divide by zero. I should never be started
2238 * with count == 0, so let's assert that
2240 g_assert(cf->count > 0);
2241 progbar_val = (gfloat) progbar_count / cf->count;
2243 if (progbar != NULL) {
2244 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2245 "%4u of %u packets", progbar_count, cf->count);
2246 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2249 progbar_nextstep += progbar_quantum;
2252 if (progbar_stop_flag) {
2253 /* Well, the user decided to abort the operation. Just stop,
2254 and arrange to return PSP_STOPPED to our caller, so they know
2255 it was stopped explicitly. */
2262 if (range != NULL) {
2263 /* do we have to process this packet? */
2264 process_this = packet_range_process_packet(range, fdata);
2265 if (process_this == range_process_next) {
2266 /* this packet uninteresting, continue with next one */
2268 } else if (process_this == range_processing_finished) {
2269 /* all interesting packets processed, stop the loop */
2274 /* Get the packet */
2275 if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2276 /* Attempt to get the packet failed. */
2280 /* Process the packet */
2281 if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
2282 /* Callback failed. We assume it reported the error appropriately. */
2288 /* We're done printing the packets; destroy the progress bar if
2290 if (progbar != NULL)
2291 destroy_progress_dlg(progbar);
2293 ws_buffer_free(&buf);
2301 } retap_callback_args_t;
2304 retap_packet(capture_file *cf, frame_data *fdata,
2305 struct wtap_pkthdr *phdr, const guint8 *pd,
2308 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2310 epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2311 epan_dissect_reset(&args->edt);
2317 cf_retap_packets(capture_file *cf)
2319 packet_range_t range;
2320 retap_callback_args_t callback_args;
2321 gboolean construct_protocol_tree;
2322 gboolean filtering_tap_listeners;
2326 /* Presumably the user closed the capture file. */
2328 return CF_READ_ABORTED;
2331 /* Do we have any tap listeners with filters? */
2332 filtering_tap_listeners = have_filtering_tap_listeners();
2334 tap_flags = union_of_tap_listener_flags();
2336 /* If any tap listeners have filters, or require the protocol tree,
2337 construct the protocol tree. */
2338 construct_protocol_tree = filtering_tap_listeners ||
2339 (tap_flags & TL_REQUIRES_PROTO_TREE);
2341 /* If any tap listeners require the columns, construct them. */
2342 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2344 /* Reset the tap listeners. */
2345 reset_tap_listeners();
2347 epan_dissect_init(&callback_args.edt, cf->epan, construct_protocol_tree, FALSE);
2349 /* Iterate through the list of packets, dissecting all packets and
2350 re-running the taps. */
2351 packet_range_init(&range, cf);
2352 packet_range_process_init(&range);
2354 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2355 "all packets", TRUE, retap_packet,
2358 epan_dissect_cleanup(&callback_args.edt);
2362 /* Completed successfully. */
2366 /* Well, the user decided to abort the refiltering.
2367 Return CF_READ_ABORTED so our caller knows they did that. */
2368 return CF_READ_ABORTED;
2371 /* Error while retapping. */
2372 return CF_READ_ERROR;
2375 g_assert_not_reached();
2380 print_args_t *print_args;
2381 gboolean print_header_line;
2382 char *header_line_buf;
2383 int header_line_buf_len;
2384 gboolean print_formfeed;
2385 gboolean print_separator;
2389 int num_visible_cols;
2392 } print_callback_args_t;
2395 print_packet(capture_file *cf, frame_data *fdata,
2396 struct wtap_pkthdr *phdr, const guint8 *pd,
2399 print_callback_args_t *args = (print_callback_args_t *)argsp;
2405 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2406 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2408 /* Fill in the column information if we're printing the summary
2410 if (args->print_args->print_summary) {
2411 col_custom_prime_edt(&args->edt, &cf->cinfo);
2412 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2413 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2415 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2417 if (args->print_formfeed) {
2418 if (!new_page(args->print_args->stream))
2421 if (args->print_separator) {
2422 if (!print_line(args->print_args->stream, 0, ""))
2428 * We generate bookmarks, if the output format supports them.
2429 * The name is "__frameN__".
2431 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2433 if (args->print_args->print_summary) {
2434 if (!args->print_args->print_col_headings)
2435 args->print_header_line = FALSE;
2436 if (args->print_header_line) {
2437 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2439 args->print_header_line = FALSE; /* we might not need to print any more */
2441 cp = &args->line_buf[0];
2443 for (i = 0; i < args->num_visible_cols; i++) {
2444 /* Find the length of the string for this column. */
2445 column_len = (int) strlen(cf->cinfo.col_data[args->visible_cols[i]]);
2446 if (args->col_widths[i] > column_len)
2447 column_len = args->col_widths[i];
2449 /* Make sure there's room in the line buffer for the column; if not,
2450 double its length. */
2451 line_len += column_len + 1; /* "+1" for space */
2452 if (line_len > args->line_buf_len) {
2453 cp_off = (int) (cp - args->line_buf);
2454 args->line_buf_len = 2 * line_len;
2455 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2456 cp = args->line_buf + cp_off;
2459 /* Right-justify the packet number column. */
2460 if (cf->cinfo.col_fmt[args->visible_cols[i]] == COL_NUMBER)
2461 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
2463 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
2465 if (i != args->num_visible_cols - 1)
2471 * Generate a bookmark, using the summary line as the title.
2473 if (!print_bookmark(args->print_args->stream, bookmark_name,
2477 if (!print_line(args->print_args->stream, 0, args->line_buf))
2481 * Generate a bookmark, using "Frame N" as the title, as we're not
2482 * printing the summary line.
2484 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2485 if (!print_bookmark(args->print_args->stream, bookmark_name,
2488 } /* if (print_summary) */
2490 if (args->print_args->print_dissections != print_dissections_none) {
2491 if (args->print_args->print_summary) {
2492 /* Separate the summary line from the tree with a blank line. */
2493 if (!print_line(args->print_args->stream, 0, ""))
2497 /* Print the information in that tree. */
2498 if (!proto_tree_print(args->print_args, &args->edt, NULL, args->print_args->stream))
2501 /* Print a blank line if we print anything after this (aka more than one packet). */
2502 args->print_separator = TRUE;
2504 /* Print a header line if we print any more packet summaries */
2505 if (args->print_args->print_col_headings)
2506 args->print_header_line = TRUE;
2509 if (args->print_args->print_hex) {
2510 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2511 if (!print_line(args->print_args->stream, 0, ""))
2514 /* Print the full packet data as hex. */
2515 if (!print_hex_data(args->print_args->stream, &args->edt))
2518 /* Print a blank line if we print anything after this (aka more than one packet). */
2519 args->print_separator = TRUE;
2521 /* Print a header line if we print any more packet summaries */
2522 if (args->print_args->print_col_headings)
2523 args->print_header_line = TRUE;
2524 } /* if (args->print_args->print_dissections != print_dissections_none) */
2526 epan_dissect_reset(&args->edt);
2528 /* do we want to have a formfeed between each packet from now on? */
2529 if (args->print_args->print_formfeed) {
2530 args->print_formfeed = TRUE;
2536 epan_dissect_reset(&args->edt);
2541 cf_print_packets(capture_file *cf, print_args_t *print_args)
2543 print_callback_args_t callback_args;
2546 int i, cp_off, column_len, line_len;
2547 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2551 gboolean proto_tree_needed;
2553 callback_args.print_args = print_args;
2554 callback_args.print_header_line = print_args->print_col_headings;
2555 callback_args.header_line_buf = NULL;
2556 callback_args.header_line_buf_len = 256;
2557 callback_args.print_formfeed = FALSE;
2558 callback_args.print_separator = FALSE;
2559 callback_args.line_buf = NULL;
2560 callback_args.line_buf_len = 256;
2561 callback_args.col_widths = NULL;
2562 callback_args.num_visible_cols = 0;
2563 callback_args.visible_cols = NULL;
2565 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2566 destroy_print_stream(print_args->stream);
2567 return CF_PRINT_WRITE_ERROR;
2570 if (print_args->print_summary) {
2571 /* We're printing packet summaries. Allocate the header line buffer
2572 and get the column widths. */
2573 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2575 /* Find the number of visible columns and the last visible column */
2576 for (i = 0; i < prefs.num_cols; i++) {
2578 clp = g_list_nth(prefs.col_list, i);
2579 if (clp == NULL) /* Sanity check, Invalid column requested */
2582 cfmt = (fmt_data *) clp->data;
2583 if (cfmt->visible) {
2585 last_visible_col = i;
2589 /* Find the widths for each of the columns - maximum of the
2590 width of the title and the width of the data - and construct
2591 a buffer with a line containing the column titles. */
2592 callback_args.num_visible_cols = num_visible_col;
2593 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2594 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2595 cp = &callback_args.header_line_buf[0];
2597 visible_col_count = 0;
2598 for (i = 0; i < cf->cinfo.num_cols; i++) {
2600 clp = g_list_nth(prefs.col_list, i);
2601 if (clp == NULL) /* Sanity check, Invalid column requested */
2604 cfmt = (fmt_data *) clp->data;
2605 if (cfmt->visible == FALSE)
2608 /* Save the order of visible columns */
2609 callback_args.visible_cols[visible_col_count] = i;
2611 /* Don't pad the last column. */
2612 if (i == last_visible_col)
2613 callback_args.col_widths[visible_col_count] = 0;
2615 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.col_title[i]);
2616 data_width = get_column_char_width(get_column_format(i));
2617 if (data_width > callback_args.col_widths[visible_col_count])
2618 callback_args.col_widths[visible_col_count] = data_width;
2621 /* Find the length of the string for this column. */
2622 column_len = (int) strlen(cf->cinfo.col_title[i]);
2623 if (callback_args.col_widths[i] > column_len)
2624 column_len = callback_args.col_widths[visible_col_count];
2626 /* Make sure there's room in the line buffer for the column; if not,
2627 double its length. */
2628 line_len += column_len + 1; /* "+1" for space */
2629 if (line_len > callback_args.header_line_buf_len) {
2630 cp_off = (int) (cp - callback_args.header_line_buf);
2631 callback_args.header_line_buf_len = 2 * line_len;
2632 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2633 callback_args.header_line_buf_len + 1);
2634 cp = callback_args.header_line_buf + cp_off;
2637 /* Right-justify the packet number column. */
2638 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2639 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
2641 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
2643 if (i != cf->cinfo.num_cols - 1)
2646 visible_col_count++;
2650 /* Now start out the main line buffer with the same length as the
2651 header line buffer. */
2652 callback_args.line_buf_len = callback_args.header_line_buf_len;
2653 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2654 } /* if (print_summary) */
2656 /* Create the protocol tree, and make it visible, if we're printing
2657 the dissection or the hex data.
2658 XXX - do we need it if we're just printing the hex data? */
2660 callback_args.print_args->print_dissections != print_dissections_none ||
2661 callback_args.print_args->print_hex ||
2662 have_custom_cols(&cf->cinfo);
2663 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2665 /* Iterate through the list of packets, printing the packets we were
2667 ret = process_specified_records(cf, &print_args->range, "Printing",
2668 "selected packets", TRUE, print_packet,
2670 epan_dissect_cleanup(&callback_args.edt);
2671 g_free(callback_args.header_line_buf);
2672 g_free(callback_args.line_buf);
2673 g_free(callback_args.col_widths);
2674 g_free(callback_args.visible_cols);
2679 /* Completed successfully. */
2683 /* Well, the user decided to abort the printing.
2685 XXX - note that what got generated before they did that
2686 will get printed if we're piping to a print program; we'd
2687 have to write to a file and then hand that to the print
2688 program to make it actually not print anything. */
2692 /* Error while printing.
2694 XXX - note that what got generated before they did that
2695 will get printed if we're piping to a print program; we'd
2696 have to write to a file and then hand that to the print
2697 program to make it actually not print anything. */
2698 destroy_print_stream(print_args->stream);
2699 return CF_PRINT_WRITE_ERROR;
2702 if (!print_finale(print_args->stream)) {
2703 destroy_print_stream(print_args->stream);
2704 return CF_PRINT_WRITE_ERROR;
2707 if (!destroy_print_stream(print_args->stream))
2708 return CF_PRINT_WRITE_ERROR;
2716 } write_packet_callback_args_t;
2719 write_pdml_packet(capture_file *cf, frame_data *fdata,
2720 struct wtap_pkthdr *phdr, const guint8 *pd,
2723 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2725 /* Create the protocol tree, but don't fill in the column information. */
2726 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2728 /* Write out the information in that tree. */
2729 proto_tree_write_pdml(&args->edt, args->fh);
2731 epan_dissect_reset(&args->edt);
2733 return !ferror(args->fh);
2737 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2739 write_packet_callback_args_t callback_args;
2743 fh = ws_fopen(print_args->file, "w");
2745 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2747 write_pdml_preamble(fh, cf->filename);
2750 return CF_PRINT_WRITE_ERROR;
2753 callback_args.fh = fh;
2754 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2756 /* Iterate through the list of packets, printing the packets we were
2758 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2759 "selected packets", TRUE,
2760 write_pdml_packet, &callback_args);
2762 epan_dissect_cleanup(&callback_args.edt);
2767 /* Completed successfully. */
2771 /* Well, the user decided to abort the printing. */
2775 /* Error while printing. */
2777 return CF_PRINT_WRITE_ERROR;
2780 write_pdml_finale(fh);
2783 return CF_PRINT_WRITE_ERROR;
2786 /* XXX - check for an error */
2793 write_psml_packet(capture_file *cf, frame_data *fdata,
2794 struct wtap_pkthdr *phdr, const guint8 *pd,
2797 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2799 col_custom_prime_edt(&args->edt, &cf->cinfo);
2800 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2801 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2803 /* Write out the information in that tree. */
2804 proto_tree_write_psml(&args->edt, args->fh);
2806 epan_dissect_reset(&args->edt);
2808 return !ferror(args->fh);
2812 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2814 write_packet_callback_args_t callback_args;
2818 gboolean proto_tree_needed;
2820 fh = ws_fopen(print_args->file, "w");
2822 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2824 write_psml_preamble(cf, fh);
2827 return CF_PRINT_WRITE_ERROR;
2830 callback_args.fh = fh;
2832 /* Fill in the column information, only create the protocol tree
2833 if having custom columns. */
2834 proto_tree_needed = have_custom_cols(&cf->cinfo);
2835 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2837 /* Iterate through the list of packets, printing the packets we were
2839 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2840 "selected packets", TRUE,
2841 write_psml_packet, &callback_args);
2843 epan_dissect_cleanup(&callback_args.edt);
2848 /* Completed successfully. */
2852 /* Well, the user decided to abort the printing. */
2856 /* Error while printing. */
2858 return CF_PRINT_WRITE_ERROR;
2861 write_psml_finale(fh);
2864 return CF_PRINT_WRITE_ERROR;
2867 /* XXX - check for an error */
2874 write_csv_packet(capture_file *cf, frame_data *fdata,
2875 struct wtap_pkthdr *phdr, const guint8 *pd,
2878 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2880 /* Fill in the column information */
2881 col_custom_prime_edt(&args->edt, &cf->cinfo);
2882 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2883 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2885 /* Write out the information in that tree. */
2886 proto_tree_write_csv(&args->edt, args->fh);
2888 epan_dissect_reset(&args->edt);
2890 return !ferror(args->fh);
2894 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2896 write_packet_callback_args_t callback_args;
2897 gboolean proto_tree_needed;
2901 fh = ws_fopen(print_args->file, "w");
2903 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2905 write_csv_preamble(cf, fh);
2908 return CF_PRINT_WRITE_ERROR;
2911 callback_args.fh = fh;
2913 /* only create the protocol tree if having custom columns. */
2914 proto_tree_needed = have_custom_cols(&cf->cinfo);
2915 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2917 /* Iterate through the list of packets, printing the packets we were
2919 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2920 "selected packets", TRUE,
2921 write_csv_packet, &callback_args);
2923 epan_dissect_cleanup(&callback_args.edt);
2928 /* Completed successfully. */
2932 /* Well, the user decided to abort the printing. */
2936 /* Error while printing. */
2938 return CF_PRINT_WRITE_ERROR;
2941 write_csv_finale(fh);
2944 return CF_PRINT_WRITE_ERROR;
2947 /* XXX - check for an error */
2954 write_carrays_packet(capture_file *cf, frame_data *fdata,
2955 struct wtap_pkthdr *phdr,
2956 const guint8 *pd, void *argsp)
2958 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2960 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2961 proto_tree_write_carrays(fdata->num, args->fh, &args->edt);
2962 epan_dissect_reset(&args->edt);
2964 return !ferror(args->fh);
2968 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2970 write_packet_callback_args_t callback_args;
2974 fh = ws_fopen(print_args->file, "w");
2977 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2979 write_carrays_preamble(fh);
2983 return CF_PRINT_WRITE_ERROR;
2986 callback_args.fh = fh;
2987 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2989 /* Iterate through the list of packets, printing the packets we were
2991 ret = process_specified_records(cf, &print_args->range,
2993 "selected packets", TRUE,
2994 write_carrays_packet, &callback_args);
2996 epan_dissect_cleanup(&callback_args.edt);
3000 /* Completed successfully. */
3003 /* Well, the user decided to abort the printing. */
3006 /* Error while printing. */
3008 return CF_PRINT_WRITE_ERROR;
3011 write_carrays_finale(fh);
3015 return CF_PRINT_WRITE_ERROR;
3023 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
3024 search_direction dir)
3028 mdata.string = string;
3029 mdata.string_len = strlen(string);
3030 return find_packet(cf, match_protocol_tree, &mdata, dir);
3034 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
3036 mdata->frame_matched = FALSE;
3037 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
3038 mdata->string_len = strlen(mdata->string);
3040 /* Iterate through all the nodes looking for matching text */
3041 proto_tree_children_foreach(tree, match_subtree_text, mdata);
3042 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3046 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
3048 match_data *mdata = (match_data *)criterion;
3051 /* Load the frame's data. */
3052 if (!cf_read_record(cf, fdata)) {
3053 /* Attempt to get the packet failed. */
3057 /* Construct the protocol tree, including the displayed text */
3058 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
3059 /* We don't need the column information */
3060 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3062 /* Iterate through all the nodes, seeing if they have text that matches. */
3064 mdata->frame_matched = FALSE;
3065 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
3066 epan_dissect_cleanup(&edt);
3067 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3071 match_subtree_text(proto_node *node, gpointer data)
3073 match_data *mdata = (match_data *) data;
3074 const gchar *string = mdata->string;
3075 size_t string_len = mdata->string_len;
3076 capture_file *cf = mdata->cf;
3077 field_info *fi = PNODE_FINFO(node);
3078 gchar label_str[ITEM_LABEL_LENGTH];
3085 /* dissection with an invisible proto tree? */
3088 if (mdata->frame_matched) {
3089 /* We already had a match; don't bother doing any more work. */
3093 /* Don't match invisible entries. */
3094 if (PROTO_ITEM_IS_HIDDEN(node))
3097 /* was a free format label produced? */
3099 label_ptr = fi->rep->representation;
3101 /* no, make a generic label */
3102 label_ptr = label_str;
3103 proto_item_fill_label(fi, label_str);
3106 /* Does that label match? */
3107 label_len = strlen(label_ptr);
3108 for (i = 0; i < label_len; i++) {
3109 c_char = label_ptr[i];
3111 c_char = toupper(c_char);
3112 if (c_char == string[c_match]) {
3114 if (c_match == string_len) {
3115 /* No need to look further; we have a match */
3116 mdata->frame_matched = TRUE;
3124 /* Recurse into the subtree, if it exists */
3125 if (node->first_child != NULL)
3126 proto_tree_children_foreach(node, match_subtree_text, mdata);
3130 cf_find_packet_summary_line(capture_file *cf, const char *string,
3131 search_direction dir)
3135 mdata.string = string;
3136 mdata.string_len = strlen(string);
3137 return find_packet(cf, match_summary_line, &mdata, dir);
3141 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3143 match_data *mdata = (match_data *)criterion;
3144 const gchar *string = mdata->string;
3145 size_t string_len = mdata->string_len;
3147 const char *info_column;
3148 size_t info_column_len;
3149 match_result result = MR_NOTMATCHED;
3155 /* Load the frame's data. */
3156 if (!cf_read_record(cf, fdata)) {
3157 /* Attempt to get the packet failed. */
3161 /* Don't bother constructing the protocol tree */
3162 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3163 /* Get the column information */
3164 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
3167 /* Find the Info column */
3168 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3169 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
3170 /* Found it. See if we match. */
3171 info_column = edt.pi.cinfo->col_data[colx];
3172 info_column_len = strlen(info_column);
3173 for (i = 0; i < info_column_len; i++) {
3174 c_char = info_column[i];
3176 c_char = toupper(c_char);
3177 if (c_char == string[c_match]) {
3179 if (c_match == string_len) {
3180 result = MR_MATCHED;
3189 epan_dissect_cleanup(&edt);
3196 } cbs_t; /* "Counted byte string" */
3200 * The current match_* routines only support ASCII case insensitivity and don't
3201 * convert UTF-8 inputs to UTF-16 for matching.
3203 * We could modify them to use the GLib Unicode routines or the International
3204 * Components for Unicode library but it's not apparent that we could do so
3205 * without consuming a lot more CPU and memory or that searching would be
3206 * significantly better.
3210 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3211 search_direction dir)
3216 info.data_len = string_size;
3218 /* String or hex search? */
3220 /* String search - what type of string? */
3221 switch (cf->scs_type) {
3223 case SCS_NARROW_AND_WIDE:
3224 return find_packet(cf, match_narrow_and_wide, &info, dir);
3227 return find_packet(cf, match_narrow, &info, dir);
3230 return find_packet(cf, match_wide, &info, dir);
3233 g_assert_not_reached();
3237 return find_packet(cf, match_binary, &info, dir);
3241 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3243 cbs_t *info = (cbs_t *)criterion;
3244 const guint8 *ascii_text = info->data;
3245 size_t textlen = info->data_len;
3246 match_result result;
3253 /* Load the frame's data. */
3254 if (!cf_read_record(cf, fdata)) {
3255 /* Attempt to get the packet failed. */
3259 result = MR_NOTMATCHED;
3260 buf_len = fdata->cap_len;
3261 pd = ws_buffer_start_ptr(&cf->buf);
3263 while (i < buf_len) {
3266 c_char = toupper(c_char);
3267 if (c_char != '\0') {
3268 if (c_char == ascii_text[c_match]) {
3270 if (c_match == textlen) {
3271 result = MR_MATCHED;
3272 cf->search_pos = i; /* Save the position of the last character
3273 for highlighting the field. */
3278 g_assert(i>=c_match);
3279 i -= (guint32)c_match;
3289 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3292 cbs_t *info = (cbs_t *)criterion;
3293 const guint8 *ascii_text = info->data;
3294 size_t textlen = info->data_len;
3295 match_result result;
3301 /* Load the frame's data. */
3302 if (!cf_read_record(cf, fdata)) {
3303 /* Attempt to get the packet failed. */
3307 result = MR_NOTMATCHED;
3308 buf_len = fdata->cap_len;
3309 pd = ws_buffer_start_ptr(&cf->buf);
3311 while (i < buf_len) {
3314 c_char = toupper(c_char);
3315 if (c_char == ascii_text[c_match]) {
3317 if (c_match == textlen) {
3318 result = MR_MATCHED;
3319 cf->search_pos = i; /* Save the position of the last character
3320 for highlighting the field. */
3325 g_assert(i>=c_match);
3326 i -= (guint32)c_match;
3336 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3338 cbs_t *info = (cbs_t *)criterion;
3339 const guint8 *ascii_text = info->data;
3340 size_t textlen = info->data_len;
3341 match_result result;
3348 /* Load the frame's data. */
3349 if (!cf_read_record(cf, fdata)) {
3350 /* Attempt to get the packet failed. */
3354 result = MR_NOTMATCHED;
3355 buf_len = fdata->cap_len;
3356 pd = ws_buffer_start_ptr(&cf->buf);
3358 while (i < buf_len) {
3361 c_char = toupper(c_char);
3362 if (c_char == ascii_text[c_match]) {
3364 if (c_match == textlen) {
3365 result = MR_MATCHED;
3366 cf->search_pos = i; /* Save the position of the last character
3367 for highlighting the field. */
3373 g_assert(i>=(c_match*2));
3374 i -= (guint32)c_match*2;
3383 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3385 cbs_t *info = (cbs_t *)criterion;
3386 const guint8 *binary_data = info->data;
3387 size_t datalen = info->data_len;
3388 match_result result;
3394 /* Load the frame's data. */
3395 if (!cf_read_record(cf, fdata)) {
3396 /* Attempt to get the packet failed. */
3400 result = MR_NOTMATCHED;
3401 buf_len = fdata->cap_len;
3402 pd = ws_buffer_start_ptr(&cf->buf);
3404 while (i < buf_len) {
3405 if (pd[i] == binary_data[c_match]) {
3407 if (c_match == datalen) {
3408 result = MR_MATCHED;
3409 cf->search_pos = i; /* Save the position of the last character
3410 for highlighting the field. */
3415 g_assert(i>=c_match);
3416 i -= (guint32)c_match;
3425 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3426 search_direction dir)
3428 return find_packet(cf, match_dfilter, sfcode, dir);
3432 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3433 search_direction dir)
3438 if (!dfilter_compile(filter, &sfcode)) {
3440 * XXX - this shouldn't happen, as the filter string is machine
3445 if (sfcode == NULL) {
3447 * XXX - this shouldn't happen, as the filter string is machine
3452 result = find_packet(cf, match_dfilter, sfcode, dir);
3453 dfilter_free(sfcode);
3458 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3460 dfilter_t *sfcode = (dfilter_t *)criterion;
3462 match_result result;
3464 /* Load the frame's data. */
3465 if (!cf_read_record(cf, fdata)) {
3466 /* Attempt to get the packet failed. */
3470 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3471 epan_dissect_prime_dfilter(&edt, sfcode);
3472 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3473 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3474 epan_dissect_cleanup(&edt);
3479 cf_find_packet_marked(capture_file *cf, search_direction dir)
3481 return find_packet(cf, match_marked, NULL, dir);
3485 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3487 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3491 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3493 return find_packet(cf, match_time_reference, NULL, dir);
3497 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3499 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3503 find_packet(capture_file *cf,
3504 match_result (*match_function)(capture_file *, frame_data *, void *),
3505 void *criterion, search_direction dir)
3507 frame_data *start_fd;
3510 frame_data *new_fd = NULL;
3511 progdlg_t *progbar = NULL;
3516 GTimeVal start_time;
3517 gchar status_str[100];
3518 int progbar_nextstep;
3519 int progbar_quantum;
3521 match_result result;
3523 start_fd = cf->current_frame;
3524 if (start_fd != NULL) {
3525 /* Iterate through the list of packets, starting at the packet we've
3526 picked, calling a routine to run the filter on the packet, see if
3527 it matches, and stop if so. */
3529 framenum = start_fd->num;
3531 /* Update the progress bar when it gets to this value. */
3532 progbar_nextstep = 0;
3533 /* When we reach the value that triggers a progress bar update,
3534 bump that value by this amount. */
3535 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3536 /* Progress so far. */
3540 g_get_current_time(&start_time);
3542 title = cf->sfilter?cf->sfilter:"";
3544 /* Create the progress bar if necessary.
3545 We check on every iteration of the loop, so that it takes no
3546 longer than the standard time to create it (otherwise, for a
3547 large file, we might take considerably longer than that standard
3548 time in order to get to the next progress bar step). */
3549 if (progbar == NULL)
3550 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3551 FALSE, &stop_flag, &start_time, progbar_val);
3553 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3554 when we update it, we have to run the GTK+ main loop to get it
3555 to repaint what's pending, and doing so may involve an "ioctl()"
3556 to see if there's any pending input from an X server, and doing
3557 that for every packet can be costly, especially on a big file. */
3558 if (count >= progbar_nextstep) {
3559 /* let's not divide by zero. I should never be started
3560 * with count == 0, so let's assert that
3562 g_assert(cf->count > 0);
3564 progbar_val = (gfloat) count / cf->count;
3566 if (progbar != NULL) {
3567 g_snprintf(status_str, sizeof(status_str),
3568 "%4u of %u packets", count, cf->count);
3569 update_progress_dlg(progbar, progbar_val, status_str);
3572 progbar_nextstep += progbar_quantum;
3576 /* Well, the user decided to abort the search. Go back to the
3577 frame where we started. */
3582 /* Go past the current frame. */
3583 if (dir == SD_BACKWARD) {
3584 /* Go on to the previous frame. */
3585 if (framenum == 1) {
3587 * XXX - other apps have a bit more of a detailed message
3588 * for this, and instead of offering "OK" and "Cancel",
3589 * they offer things such as "Continue" and "Cancel";
3590 * we need an API for popping up alert boxes with
3591 * {Verb} and "Cancel".
3594 if (prefs.gui_find_wrap)
3596 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3597 framenum = cf->count; /* wrap around */
3601 statusbar_push_temporary_msg("Search reached the beginning.");
3602 framenum = start_fd->num; /* stay on previous packet */
3607 /* Go on to the next frame. */
3608 if (framenum == cf->count) {
3609 if (prefs.gui_find_wrap)
3611 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3612 framenum = 1; /* wrap around */
3616 statusbar_push_temporary_msg("Search reached the end.");
3617 framenum = start_fd->num; /* stay on previous packet */
3622 fdata = frame_data_sequence_find(cf->frames, framenum);
3626 /* Is this packet in the display? */
3627 if (fdata->flags.passed_dfilter) {
3628 /* Yes. Does it match the search criterion? */
3629 result = (*match_function)(cf, fdata, criterion);
3630 if (result == MR_ERROR) {
3631 /* Error; our caller has reported the error. Go back to the frame
3632 where we started. */
3635 } else if (result == MR_MATCHED) {
3636 /* Yes. Go to the new frame. */
3642 if (fdata == start_fd) {
3643 /* We're back to the frame we were on originally, and that frame
3644 doesn't match the search filter. The search failed. */
3649 /* We're done scanning the packets; destroy the progress bar if it
3651 if (progbar != NULL)
3652 destroy_progress_dlg(progbar);
3655 if (new_fd != NULL) {
3656 /* Find and select */
3657 cf->search_in_progress = TRUE;
3658 found = packet_list_select_row_from_data(new_fd);
3659 cf->search_in_progress = FALSE;
3660 cf->search_pos = 0; /* Reset the position */
3662 /* We didn't find a row corresponding to this frame.
3663 This means that the frame isn't being displayed currently,
3664 so we can't select it. */
3665 simple_message_box(ESD_TYPE_INFO, NULL,
3666 "The capture file is probably not fully dissected.",
3667 "End of capture exceeded.");
3670 return TRUE; /* success */
3672 return FALSE; /* failure */
3676 cf_goto_frame(capture_file *cf, guint fnumber)
3680 fdata = frame_data_sequence_find(cf->frames, fnumber);
3682 if (fdata == NULL) {
3683 /* we didn't find a packet with that packet number */
3684 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3685 return FALSE; /* we failed to go to that packet */
3687 if (!fdata->flags.passed_dfilter) {
3688 /* that packet currently isn't displayed */
3689 /* XXX - add it to the set of displayed packets? */
3690 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3691 return FALSE; /* we failed to go to that packet */
3694 if (!packet_list_select_row_from_data(fdata)) {
3695 /* We didn't find a row corresponding to this frame.
3696 This means that the frame isn't being displayed currently,
3697 so we can't select it. */
3698 simple_message_box(ESD_TYPE_INFO, NULL,
3699 "The capture file is probably not fully dissected.",
3700 "End of capture exceeded.");
3703 return TRUE; /* we got to that packet */
3707 cf_goto_top_frame(void)
3709 /* Find and select */
3710 packet_list_select_first_row();
3711 return TRUE; /* we got to that packet */
3715 cf_goto_bottom_frame(void)
3717 /* Find and select */
3718 packet_list_select_last_row();
3719 return TRUE; /* we got to that packet */
3723 * Go to frame specified by currently selected protocol tree item.
3726 cf_goto_framenum(capture_file *cf)
3728 header_field_info *hfinfo;
3731 if (cf->finfo_selected) {
3732 hfinfo = cf->finfo_selected->hfinfo;
3734 if (hfinfo->type == FT_FRAMENUM) {
3735 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3737 return cf_goto_frame(cf, framenum);
3744 /* Select the packet on a given row. */
3746 cf_select_packet(capture_file *cf, int row)
3748 epan_dissect_t *old_edt;
3751 /* Get the frame data struct pointer for this frame */
3752 fdata = packet_list_get_row_data(row);
3754 if (fdata == NULL) {
3755 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3756 the first entry is added to it by "real_insert_row()", that row
3757 is selected (see "real_insert_row()", in "ui/gtk/gtkclist.c", in both
3758 our version and the vanilla GTK+ version).
3760 This means that a "select-row" signal is emitted; this causes
3761 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3764 "cf_select_packet()" fetches, above, the data associated with the
3765 row that was selected; however, as "gtk_clist_append()", which
3766 called "real_insert_row()", hasn't yet returned, we haven't yet
3767 associated any data with that row, so we get back a null pointer.
3769 We can't assume that there's only one frame in the frame list,
3770 either, as we may be filtering the display.
3772 We therefore assume that, if "row" is 0, i.e. the first row
3773 is being selected, and "cf->first_displayed" equals
3774 "cf->last_displayed", i.e. there's only one frame being
3775 displayed, that frame is the frame we want.
3777 This means we have to set "cf->first_displayed" and
3778 "cf->last_displayed" before adding the row to the
3779 GtkCList; see the comment in "add_packet_to_packet_list()". */
3781 if (row == 0 && cf->first_displayed == cf->last_displayed)
3782 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3785 /* If fdata _still_ isn't set simply give up. */
3786 if (fdata == NULL) {
3790 /* Get the data in that frame. */
3791 if (!cf_read_record (cf, fdata)) {
3795 /* Record that this frame is the current frame. */
3796 cf->current_frame = fdata;
3797 cf->current_row = row;
3800 /* Create the logical protocol tree. */
3801 /* We don't need the columns here. */
3802 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3804 tap_build_interesting(cf->edt);
3805 epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3806 cf->current_frame, NULL);
3808 dfilter_macro_build_ftv_cache(cf->edt->tree);
3810 cf_callback_invoke(cf_cb_packet_selected, cf);
3812 if (old_edt != NULL)
3813 epan_dissect_free(old_edt);
3817 /* Unselect the selected packet, if any. */
3819 cf_unselect_packet(capture_file *cf)
3821 epan_dissect_t *old_edt = cf->edt;
3825 /* No packet is selected. */
3826 cf->current_frame = NULL;
3827 cf->current_row = 0;
3829 cf_callback_invoke(cf_cb_packet_unselected, cf);
3831 /* No protocol tree means no selected field. */
3832 cf_unselect_field(cf);
3834 /* Destroy the epan_dissect_t for the unselected packet. */
3835 if (old_edt != NULL)
3836 epan_dissect_free(old_edt);
3839 /* Unset the selected protocol tree field, if any. */
3841 cf_unselect_field(capture_file *cf)
3843 cf->finfo_selected = NULL;
3845 cf_callback_invoke(cf_cb_field_unselected, cf);
3849 * Mark a particular frame.
3852 cf_mark_frame(capture_file *cf, frame_data *frame)
3854 if (! frame->flags.marked) {
3855 frame->flags.marked = TRUE;
3856 if (cf->count > cf->marked_count)
3862 * Unmark a particular frame.
3865 cf_unmark_frame(capture_file *cf, frame_data *frame)
3867 if (frame->flags.marked) {
3868 frame->flags.marked = FALSE;
3869 if (cf->marked_count > 0)
3875 * Ignore a particular frame.
3878 cf_ignore_frame(capture_file *cf, frame_data *frame)
3880 if (! frame->flags.ignored) {
3881 frame->flags.ignored = TRUE;
3882 if (cf->count > cf->ignored_count)
3883 cf->ignored_count++;
3888 * Un-ignore a particular frame.
3891 cf_unignore_frame(capture_file *cf, frame_data *frame)
3893 if (frame->flags.ignored) {
3894 frame->flags.ignored = FALSE;
3895 if (cf->ignored_count > 0)
3896 cf->ignored_count--;
3901 * Read the comment in SHB block
3905 cf_read_shb_comment(capture_file *cf)
3907 wtapng_section_t *shb_inf;
3908 const gchar *temp_str;
3910 /* Get info from SHB */
3911 shb_inf = wtap_file_get_shb_info(cf->wth);
3912 if (shb_inf == NULL)
3914 temp_str = shb_inf->opt_comment;
3922 cf_update_capture_comment(capture_file *cf, gchar *comment)
3924 wtapng_section_t *shb_inf;
3926 /* Get info from SHB */
3927 shb_inf = wtap_file_get_shb_info(cf->wth);
3929 /* See if the comment has changed or not */
3930 if (shb_inf && shb_inf->opt_comment) {
3931 if (strcmp(shb_inf->opt_comment, comment) == 0) {
3940 /* The comment has changed, let's update it */
3941 wtap_write_shb_comment(cf->wth, comment);
3942 /* Mark the file as having unsaved changes */
3943 cf->unsaved_changes = TRUE;
3947 cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
3949 if (cf->frames_user_comments)
3950 return (const char *)g_tree_lookup(cf->frames_user_comments, fd);
3957 cf_get_comment(capture_file *cf, const frame_data *fd)
3959 /* fetch user comment */
3960 if (fd->flags.has_user_comment)
3961 return g_strdup(cf_get_user_packet_comment(cf, fd));
3963 /* fetch phdr comment */
3964 if (fd->flags.has_phdr_comment) {
3965 struct wtap_pkthdr phdr; /* Packet header */
3966 Buffer buf; /* Packet data */
3968 memset(&phdr, 0, sizeof(struct wtap_pkthdr));
3970 ws_buffer_init(&buf, 1500);
3971 if (!cf_read_record_r(cf, fd, &phdr, &buf))
3972 { /* XXX, what we can do here? */ }
3974 ws_buffer_free(&buf);
3975 return phdr.opt_comment;
3981 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3983 const frame_data *fdata1 = (const frame_data *) a;
3984 const frame_data *fdata2 = (const frame_data *) b;
3986 return (fdata1->num < fdata2->num) ? -1 :
3987 (fdata1->num > fdata2->num) ? 1 :
3992 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3994 char *pkt_comment = cf_get_comment(cf, fd);
3996 /* Check if the comment has changed */
3997 if (!g_strcmp0(pkt_comment, new_comment)) {
3998 g_free(pkt_comment);
4001 g_free(pkt_comment);
4004 cf->packet_comment_count--;
4007 cf->packet_comment_count++;
4009 fd->flags.has_user_comment = TRUE;
4011 if (!cf->frames_user_comments)
4012 cf->frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
4014 /* insert new packet comment */
4015 g_tree_replace(cf->frames_user_comments, fd, g_strdup(new_comment));
4017 expert_update_comment_count(cf->packet_comment_count);
4019 /* OK, we have unsaved changes. */
4020 cf->unsaved_changes = TRUE;
4025 * What types of comments does this capture file have?
4028 cf_comment_types(capture_file *cf)
4030 guint32 comment_types = 0;
4032 if (cf_read_shb_comment(cf) != NULL)
4033 comment_types |= WTAP_COMMENT_PER_SECTION;
4034 if (cf->packet_comment_count != 0)
4035 comment_types |= WTAP_COMMENT_PER_PACKET;
4036 return comment_types;
4039 #ifdef WANT_PACKET_EDITOR
4041 g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_)
4052 modified_frame_data_free(gpointer data)
4054 modified_frame_data *mfd = (modified_frame_data *)data;
4061 * Give a frame new, edited data.
4064 cf_set_frame_edited(capture_file *cf, frame_data *fd,
4065 struct wtap_pkthdr *phdr, guint8 *pd)
4067 modified_frame_data *mfd = (modified_frame_data *)g_malloc(sizeof(modified_frame_data));
4072 if (cf->edited_frames == NULL)
4073 cf->edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL,
4074 modified_frame_data_free);
4075 g_tree_insert(cf->edited_frames, GINT_TO_POINTER(fd->num), mfd);
4078 /* Mark the file as having unsaved changes */
4079 cf->unsaved_changes = TRUE;
4087 } save_callback_args_t;
4090 * Save a capture to a file, in a particular format, saving either
4091 * all packets, all currently-displayed packets, or all marked packets.
4093 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4094 * up a message box for the failure.
4097 save_record(capture_file *cf, frame_data *fdata,
4098 struct wtap_pkthdr *phdr, const guint8 *pd,
4101 save_callback_args_t *args = (save_callback_args_t *)argsp;
4102 struct wtap_pkthdr hdr;
4104 gchar *display_basename;
4105 const char *pkt_comment;
4107 if (fdata->flags.has_user_comment)
4108 pkt_comment = cf_get_user_packet_comment(cf, fdata);
4110 pkt_comment = phdr->opt_comment;
4112 /* init the wtap header for saving */
4113 /* TODO: reuse phdr */
4114 /* XXX - these are the only flags that correspond to data that we have
4115 in the frame_data structure and that matter on a per-packet basis.
4117 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
4118 and "on the wire" lengths, or it doesn't.
4120 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
4123 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
4124 from the packet flags. */
4125 hdr.rec_type = phdr->rec_type;
4126 hdr.presence_flags = 0;
4127 if (fdata->flags.has_ts)
4128 hdr.presence_flags |= WTAP_HAS_TS;
4129 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
4130 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
4131 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
4132 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
4133 hdr.ts.secs = fdata->abs_ts.secs;
4134 hdr.ts.nsecs = fdata->abs_ts.nsecs;
4135 hdr.caplen = phdr->caplen;
4136 hdr.len = phdr->len;
4137 hdr.pkt_encap = fdata->lnk_t;
4139 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
4141 hdr.pack_flags = phdr->pack_flags;
4142 hdr.opt_comment = g_strdup(pkt_comment);
4145 hdr.pseudo_header = phdr->pseudo_header;
4148 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
4150 /* and save the packet */
4151 if (!wtap_dump(args->pdh, &hdr, pd, &err)) {
4153 /* Wiretap error. */
4156 case WTAP_ERR_UNSUPPORTED_ENCAP:
4158 * This is a problem with the particular frame we're writing and
4159 * the file type and subtype we're writing; note that, and report
4160 * the frame number and file type/subtype.
4162 simple_error_message_box(
4163 "Frame %u has a network type that can't be saved in a \"%s\" file.",
4164 fdata->num, wtap_file_type_subtype_string(args->file_type));
4167 case WTAP_ERR_PACKET_TOO_LARGE:
4169 * This is a problem with the particular frame we're writing and
4170 * the file type and subtype we're writing; note that, and report
4171 * the frame number and file type/subtype.
4173 simple_error_message_box(
4174 "Frame %u is larger than Wireshark supports in a \"%s\" file.",
4175 fdata->num, wtap_file_type_subtype_string(args->file_type));
4179 display_basename = g_filename_display_basename(args->fname);
4180 simple_error_message_box(
4181 "An error occurred while writing to the file \"%s\": %s.",
4182 display_basename, wtap_strerror(err));
4183 g_free(display_basename);
4188 write_failure_alert_box(args->fname, err);
4193 g_free(hdr.opt_comment);
4198 * Can this capture file be written out in any format using Wiretap
4199 * rather than by copying the raw data?
4202 cf_can_write_with_wiretap(capture_file *cf)
4204 /* We don't care whether we support the comments in this file or not;
4205 if we can't, we'll offer the user the option of discarding the
4207 return wtap_dump_can_write(cf->linktypes, 0);
4211 * Should we let the user do a save?
4215 * the file has unsaved changes, and we can save it in some
4216 * format through Wiretap
4220 * the file is a temporary file and has no unsaved changes (so
4221 * that "saving" it just means copying it).
4223 * XXX - we shouldn't allow files to be edited if they can't be saved,
4224 * so cf->unsaved_changes should be true only if the file can be saved.
4226 * We don't care whether we support the comments in this file or not;
4227 * if we can't, we'll offer the user the option of discarding the
4231 cf_can_save(capture_file *cf)
4233 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4234 /* Saved changes, and we can write it out with Wiretap. */
4238 if (cf->is_tempfile && !cf->unsaved_changes) {
4240 * Temporary file with no unsaved changes, so we can just do a
4246 /* Nothing to save. */
4251 * Should we let the user do a "save as"?
4255 * we can save it in some format through Wiretap
4259 * the file is a temporary file and has no unsaved changes (so
4260 * that "saving" it just means copying it).
4262 * XXX - we shouldn't allow files to be edited if they can't be saved,
4263 * so cf->unsaved_changes should be true only if the file can be saved.
4265 * We don't care whether we support the comments in this file or not;
4266 * if we can't, we'll offer the user the option of discarding the
4270 cf_can_save_as(capture_file *cf)
4272 if (wtap_dump_can_write(cf->linktypes, 0)) {
4273 /* We can write it out with Wiretap. */
4277 if (cf->is_tempfile && !cf->unsaved_changes) {
4279 * Temporary file with no unsaved changes, so we can just do a
4285 /* Nothing to save. */
4290 * Does this file have unsaved data?
4293 cf_has_unsaved_data(capture_file *cf)
4296 * If this is a temporary file, or a file with unsaved changes, it
4299 return cf->is_tempfile || cf->unsaved_changes;
4303 * Quick scan to find packet offsets.
4305 static cf_read_status_t
4306 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
4308 const struct wtap_pkthdr *phdr;
4313 progdlg_t *progbar = NULL;
4317 GTimeVal start_time;
4318 gchar status_str[100];
4319 gint64 progbar_nextstep;
4320 gint64 progbar_quantum;
4325 int displayed_once = 0;
4328 /* Close the old handle. */
4329 wtap_close(cf->wth);
4331 /* Open the new file. */
4332 /* XXX: this will go through all open_routines for a matching one. But right
4333 now rescan_file() is only used when a file is being saved to a different
4334 format than the original, and the user is not given a choice of which
4335 reader to use (only which format to save it in), so doing this makes
4337 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, err, &err_info, TRUE);
4338 if (cf->wth == NULL) {
4339 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
4340 return CF_READ_ERROR;
4343 /* We're scanning a file whose contents should be the same as what
4344 we had before, so we don't discard dissection state etc.. */
4347 /* Set the file name because we need it to set the follow stream filter.
4348 XXX - is that still true? We need it for other reasons, though,
4350 cf->filename = g_strdup(fname);
4352 /* Indicate whether it's a permanent or temporary file. */
4353 cf->is_tempfile = is_tempfile;
4355 /* No user changes yet. */
4356 cf->unsaved_changes = FALSE;
4358 cf->cd_t = wtap_file_type_subtype(cf->wth);
4359 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4361 cf->snap = wtap_snapshot_length(cf->wth);
4362 if (cf->snap == 0) {
4363 /* Snapshot length not known. */
4364 cf->has_snap = FALSE;
4365 cf->snap = WTAP_MAX_PACKET_SIZE;
4367 cf->has_snap = TRUE;
4369 name_ptr = g_filename_display_basename(cf->filename);
4371 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4373 /* Record whether the file is compressed.
4374 XXX - do we know this at open time? */
4375 cf->iscompressed = wtap_iscompressed(cf->wth);
4377 /* Find the size of the file. */
4378 size = wtap_file_size(cf->wth, NULL);
4380 /* Update the progress bar when it gets to this value. */
4381 progbar_nextstep = 0;
4382 /* When we reach the value that triggers a progress bar update,
4383 bump that value by this amount. */
4385 progbar_quantum = size/N_PROGBAR_UPDATES;
4386 if (progbar_quantum < MIN_QUANTUM)
4387 progbar_quantum = MIN_QUANTUM;
4389 progbar_quantum = 0;
4392 g_get_current_time(&start_time);
4395 phdr = wtap_phdr(cf->wth);
4396 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
4398 fdata = frame_data_sequence_find(cf->frames, framenum);
4399 fdata->file_off = data_offset;
4402 file_pos = wtap_read_so_far(cf->wth);
4404 /* Create the progress bar if necessary.
4405 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
4407 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
4408 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
4409 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4410 TRUE, &stop_flag, &start_time, progbar_val);
4413 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
4414 when we update it, we have to run the GTK+ main loop to get it
4415 to repaint what's pending, and doing so may involve an "ioctl()"
4416 to see if there's any pending input from an X server, and doing
4417 that for every packet can be costly, especially on a big file. */
4418 if (file_pos >= progbar_nextstep) {
4419 if (progbar != NULL) {
4420 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
4421 /* update the packet bar content on the first run or frequently on very large files */
4423 if (progbar_quantum > 500000 || displayed_once == 0) {
4424 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
4426 packets_bar_update();
4429 #endif /* HAVE_LIBPCAP */
4430 update_progress_dlg(progbar, progbar_val, status_str);
4432 progbar_nextstep += progbar_quantum;
4437 /* Well, the user decided to abort the rescan. Sadly, as this
4438 isn't a reread, recovering is difficult, so we'll just
4439 close the current capture. */
4443 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4444 it's not already there.
4445 XXX - yes, this is O(N), so if every packet had a different
4446 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4447 there are probably going to be a small number of encapsulation types
4449 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4452 /* Free the display name */
4455 /* We're done reading the file; destroy the progress bar if it was created. */
4456 if (progbar != NULL)
4457 destroy_progress_dlg(progbar);
4459 /* We're done reading sequentially through the file. */
4460 cf->state = FILE_READ_DONE;
4462 /* Close the sequential I/O side, to free up memory it requires. */
4463 wtap_sequential_close(cf->wth);
4465 /* compute the time it took to load the file */
4466 compute_elapsed(cf, &start_time);
4468 /* Set the file encapsulation type now; we don't know what it is until
4469 we've looked at all the packets, as we don't know until then whether
4470 there's more than one type (and thus whether it's
4471 WTAP_ENCAP_PER_PACKET). */
4472 cf->lnk_t = wtap_file_encap(cf->wth);
4474 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4477 /* Our caller will give up at this point. */
4478 return CF_READ_ABORTED;
4482 /* Put up a message box noting that the read failed somewhere along
4483 the line. Don't throw out the stuff we managed to read, though,
4487 case WTAP_ERR_UNSUPPORTED:
4488 simple_error_message_box(
4489 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
4494 case WTAP_ERR_UNSUPPORTED_ENCAP:
4495 simple_error_message_box(
4496 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
4501 case WTAP_ERR_SHORT_READ:
4502 simple_error_message_box(
4503 "The capture file appears to have been cut short"
4504 " in the middle of a packet.");
4507 case WTAP_ERR_BAD_FILE:
4508 simple_error_message_box(
4509 "The capture file appears to be damaged or corrupt.\n(%s)",
4514 case WTAP_ERR_DECOMPRESS:
4515 simple_error_message_box(
4516 "The compressed capture file appears to be damaged or corrupt.\n"
4522 simple_error_message_box(
4523 "An error occurred while reading the"
4524 " capture file: %s.", wtap_strerror(*err));
4527 return CF_READ_ERROR;
4533 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4534 gboolean compressed, gboolean discard_comments,
4535 gboolean dont_reopen)
4538 gchar *fname_new = NULL;
4541 addrinfo_lists_t *addr_lists;
4545 gchar *display_basename;
4552 save_callback_args_t callback_args;
4554 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4556 addr_lists = get_addrinfo_list();
4558 if (save_format == cf->cd_t && compressed == cf->iscompressed
4559 && !discard_comments && !cf->unsaved_changes
4560 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4561 /* We're saving in the format it's already in, and we're
4562 not discarding comments, and there are no changes we have
4563 in memory that aren't saved to the file, and we have no name
4564 resolution blocks to write, so we can just move or copy the raw data. */
4566 if (cf->is_tempfile) {
4567 /* The file being saved is a temporary file from a live
4568 capture, so it doesn't need to stay around under that name;
4569 first, try renaming the capture buffer file to the new name.
4570 This acts as a "safe save", in that, if the file already
4571 exists, the existing file will be removed only if the rename
4574 Sadly, on Windows, as we have the current capture file
4575 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4576 (to cause the rename to remove an existing target), as
4577 done by ws_stdio_rename() (ws_rename() is #defined to
4578 be ws_stdio_rename() on Windows) will fail.
4580 According to the MSDN documentation for CreateFile(), if,
4581 when we open a capture file, we were to directly do a CreateFile(),
4582 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4583 convert it to a file descriptor with _open_osfhandle(),
4584 that would allow the file to be renamed out from under us.
4586 However, that doesn't work in practice. Perhaps the problem
4587 is that the process doing the rename is the process that
4588 has the file open. */
4590 if (ws_rename(cf->filename, fname) == 0) {
4591 /* That succeeded - there's no need to copy the source file. */
4592 how_to_save = SAVE_WITH_MOVE;
4594 if (errno == EXDEV) {
4595 /* They're on different file systems, so we have to copy the
4597 how_to_save = SAVE_WITH_COPY;
4599 /* The rename failed, but not because they're on different
4600 file systems - put up an error message. (Or should we
4601 just punt and try to copy? The only reason why I'd
4602 expect the rename to fail and the copy to succeed would
4603 be if we didn't have permission to remove the file from
4604 the temporary directory, and that might be fixable - but
4605 is it worth requiring the user to go off and fix it?) */
4606 cf_rename_failure_alert_box(fname, errno);
4611 how_to_save = SAVE_WITH_COPY;
4614 /* It's a permanent file, so we should copy it, and not remove the
4616 how_to_save = SAVE_WITH_COPY;
4619 if (how_to_save == SAVE_WITH_COPY) {
4620 /* Copy the file, if we haven't moved it. If we're overwriting
4621 an existing file, we do it with a "safe save", by writing
4622 to a new file and, if the write succeeds, renaming the
4623 new file on top of the old file. */
4624 if (file_exists(fname)) {
4625 fname_new = g_strdup_printf("%s~", fname);
4626 if (!copy_file_binary_mode(cf->filename, fname_new))
4629 if (!copy_file_binary_mode(cf->filename, fname))
4634 /* Either we're saving in a different format or we're saving changes,
4635 such as added, modified, or removed comments, that haven't yet
4636 been written to the underlying file; we can't do that by copying
4637 or moving the capture file, we have to do it by writing the packets
4640 wtapng_section_t *shb_hdr = NULL;
4641 wtapng_iface_descriptions_t *idb_inf = NULL;
4644 shb_hdr = wtap_file_get_shb_info(cf->wth);
4645 idb_inf = wtap_file_get_idb_info(cf->wth);
4647 /* Determine what file encapsulation type we should use. */
4648 encap = wtap_dump_file_encap_type(cf->linktypes);
4650 if (file_exists(fname)) {
4651 /* We're overwriting an existing file; write out to a new file,
4652 and, if that succeeds, rename the new file on top of the
4653 old file. That makes this a "safe save", so that we don't
4654 lose the old file if we have a problem writing out the new
4655 file. (If the existing file is the current capture file,
4656 we *HAVE* to do that, otherwise we're overwriting the file
4657 from which we're reading the packets that we're writing!) */
4658 fname_new = g_strdup_printf("%s~", fname);
4659 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4660 compressed, shb_hdr, idb_inf, &err);
4662 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4663 compressed, shb_hdr, idb_inf, &err);
4669 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4673 /* Add address resolution */
4674 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4676 /* Iterate through the list of packets, processing all the packets. */
4677 callback_args.pdh = pdh;
4678 callback_args.fname = fname;
4679 callback_args.file_type = save_format;
4680 switch (process_specified_records(cf, NULL, "Saving", "packets",
4681 TRUE, save_record, &callback_args)) {
4684 /* Completed successfully. */
4688 /* The user decided to abort the saving.
4689 If we're writing to a temporary file, remove it.
4690 XXX - should we do so even if we're not writing to a
4692 wtap_dump_close(pdh, &err);
4693 if (fname_new != NULL)
4694 ws_unlink(fname_new);
4695 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4696 return CF_WRITE_ABORTED;
4699 /* Error while saving.
4700 If we're writing to a temporary file, remove it. */
4701 if (fname_new != NULL)
4702 ws_unlink(fname_new);
4703 wtap_dump_close(pdh, &err);
4707 if (!wtap_dump_close(pdh, &err)) {
4708 cf_close_failure_alert_box(fname, err);
4712 how_to_save = SAVE_WITH_WTAP;
4715 if (fname_new != NULL) {
4716 /* We wrote out to fname_new, and should rename it on top of
4717 fname. fname_new is now closed, so that should be possible even
4718 on Windows. However, on Windows, we first need to close whatever
4719 file descriptors we have open for fname. */
4721 wtap_fdclose(cf->wth);
4723 /* Now do the rename. */
4724 if (ws_rename(fname_new, fname) == -1) {
4725 /* Well, the rename failed. */
4726 cf_rename_failure_alert_box(fname, errno);
4728 /* Attempt to reopen the random file descriptor using the
4729 current file's filename. (At this point, the sequential
4730 file descriptor is closed.) */
4731 if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
4732 /* Oh, well, we're screwed. */
4733 display_basename = g_filename_display_basename(cf->filename);
4734 simple_error_message_box(
4735 file_open_error_message(err, FALSE), display_basename);
4736 g_free(display_basename);
4743 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4744 cf->unsaved_changes = FALSE;
4747 switch (how_to_save) {
4749 case SAVE_WITH_MOVE:
4750 /* We just moved the file, so the wtap structure refers to the
4751 new file, and all the information other than the filename
4752 and the "is temporary" status applies to the new file; just
4754 g_free(cf->filename);
4755 cf->filename = g_strdup(fname);
4756 cf->is_tempfile = FALSE;
4757 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4760 case SAVE_WITH_COPY:
4761 /* We just copied the file, s all the information other than
4762 the wtap structure, the filename, and the "is temporary"
4763 status applies to the new file; just update that. */
4764 wtap_close(cf->wth);
4765 /* Although we're just "copying" and then opening the copy, it will
4766 try all open_routine readers to open the copy, so we need to
4767 reset the cfile's open_type. */
4768 cf->open_type = WTAP_TYPE_AUTO;
4769 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4770 if (cf->wth == NULL) {
4771 cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
4774 g_free(cf->filename);
4775 cf->filename = g_strdup(fname);
4776 cf->is_tempfile = FALSE;
4778 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4781 case SAVE_WITH_WTAP:
4782 /* Open and read the file we saved to.
4784 XXX - this is somewhat of a waste; we already have the
4785 packets, all this gets us is updated file type information
4786 (which we could just stuff into "cf"), and having the new
4787 file be the one we have opened and from which we're reading
4788 the data, and it means we have to spend time opening and
4789 reading the file, which could be a significant amount of
4790 time if the file is large.
4792 If the capture-file-writing code were to return the
4793 seek offset of each packet it writes, we could save that
4794 in the frame_data structure for the frame, and just open
4795 the file without reading it again...
4797 ...as long as, for gzipped files, the process of writing
4798 out the file *also* generates the information needed to
4799 support fast random access to the compressed file. */
4800 /* rescan_file will cause us to try all open_routines, so
4801 reset cfile's open_type */
4802 cf->open_type = WTAP_TYPE_AUTO;
4803 if (rescan_file(cf, fname, FALSE, &err) != CF_READ_OK) {
4804 /* The rescan failed; just close the file. Either
4805 a dialog was popped up for the failure, so the
4806 user knows what happened, or they stopped the
4807 rescan, in which case they know what happened. */
4813 /* If we were told to discard the comments, do so. */
4814 if (discard_comments) {
4815 /* Remove SHB comment, if any. */
4816 wtap_write_shb_comment(cf->wth, NULL);
4818 /* remove all user comments */
4819 for (framenum = 1; framenum <= cf->count; framenum++) {
4820 fdata = frame_data_sequence_find(cf->frames, framenum);
4822 fdata->flags.has_phdr_comment = FALSE;
4823 fdata->flags.has_user_comment = FALSE;
4826 if (cf->frames_user_comments) {
4827 g_tree_destroy(cf->frames_user_comments);
4828 cf->frames_user_comments = NULL;
4831 cf->packet_comment_count = 0;
4837 if (fname_new != NULL) {
4838 /* We were trying to write to a temporary file; get rid of it if it
4839 exists. (We don't care whether this fails, as, if it fails,
4840 there's not much we can do about it. I guess if it failed for
4841 a reason other than "it doesn't exist", we could report an
4842 error, so the user knows there's a junk file that they might
4843 want to clean up.) */
4844 ws_unlink(fname_new);
4847 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4848 return CF_WRITE_ERROR;
4852 cf_export_specified_packets(capture_file *cf, const char *fname,
4853 packet_range_t *range, guint save_format,
4854 gboolean compressed)
4856 gchar *fname_new = NULL;
4859 save_callback_args_t callback_args;
4860 wtapng_section_t *shb_hdr;
4861 wtapng_iface_descriptions_t *idb_inf;
4864 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4866 packet_range_process_init(range);
4868 /* We're writing out specified packets from the specified capture
4869 file to another file. Even if all captured packets are to be
4870 written, don't special-case the operation - read each packet
4871 and then write it out if it's one of the specified ones. */
4873 shb_hdr = wtap_file_get_shb_info(cf->wth);
4874 idb_inf = wtap_file_get_idb_info(cf->wth);
4876 /* Determine what file encapsulation type we should use. */
4877 encap = wtap_dump_file_encap_type(cf->linktypes);
4879 if (file_exists(fname)) {
4880 /* We're overwriting an existing file; write out to a new file,
4881 and, if that succeeds, rename the new file on top of the
4882 old file. That makes this a "safe save", so that we don't
4883 lose the old file if we have a problem writing out the new
4884 file. (If the existing file is the current capture file,
4885 we *HAVE* to do that, otherwise we're overwriting the file
4886 from which we're reading the packets that we're writing!) */
4887 fname_new = g_strdup_printf("%s~", fname);
4888 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4889 compressed, shb_hdr, idb_inf, &err);
4891 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4892 compressed, shb_hdr, idb_inf, &err);
4898 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4902 /* Add address resolution */
4903 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4905 /* Iterate through the list of packets, processing the packets we were
4908 XXX - we've already called "packet_range_process_init(range)", but
4909 "process_specified_records()" will do it again. Fortunately,
4910 that's harmless in this case, as we haven't done anything to
4911 "range" since we initialized it. */
4912 callback_args.pdh = pdh;
4913 callback_args.fname = fname;
4914 callback_args.file_type = save_format;
4915 switch (process_specified_records(cf, range, "Writing", "specified records",
4916 TRUE, save_record, &callback_args)) {
4919 /* Completed successfully. */
4923 /* The user decided to abort the saving.
4924 If we're writing to a temporary file, remove it.
4925 XXX - should we do so even if we're not writing to a
4927 wtap_dump_close(pdh, &err);
4928 if (fname_new != NULL)
4929 ws_unlink(fname_new);
4930 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4931 return CF_WRITE_ABORTED;
4935 /* Error while saving.
4936 If we're writing to a temporary file, remove it. */
4937 if (fname_new != NULL)
4938 ws_unlink(fname_new);
4939 wtap_dump_close(pdh, &err);
4943 if (!wtap_dump_close(pdh, &err)) {
4944 cf_close_failure_alert_box(fname, err);
4948 if (fname_new != NULL) {
4949 /* We wrote out to fname_new, and should rename it on top of
4950 fname; fname is now closed, so that should be possible even
4951 on Windows. Do the rename. */
4952 if (ws_rename(fname_new, fname) == -1) {
4953 /* Well, the rename failed. */
4954 cf_rename_failure_alert_box(fname, errno);
4959 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4963 if (fname_new != NULL) {
4964 /* We were trying to write to a temporary file; get rid of it if it
4965 exists. (We don't care whether this fails, as, if it fails,
4966 there's not much we can do about it. I guess if it failed for
4967 a reason other than "it doesn't exist", we could report an
4968 error, so the user knows there's a junk file that they might
4969 want to clean up.) */
4970 ws_unlink(fname_new);
4973 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4974 return CF_WRITE_ERROR;
4978 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
4979 gboolean for_writing, int file_type)
4981 gchar *display_basename;
4984 /* Wiretap error. */
4985 display_basename = g_filename_display_basename(filename);
4988 case WTAP_ERR_NOT_REGULAR_FILE:
4989 simple_error_message_box(
4990 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4994 case WTAP_ERR_RANDOM_OPEN_PIPE:
4995 /* Seen only when opening a capture file for reading. */
4996 simple_error_message_box(
4997 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.\n"
4998 "To capture from a pipe or FIFO use wireshark -i -",
5002 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
5003 /* Seen only when opening a capture file for reading. */
5004 simple_error_message_box(
5005 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
5009 case WTAP_ERR_UNSUPPORTED:
5010 /* Seen only when opening a capture file for reading. */
5011 simple_error_message_box(
5012 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
5014 display_basename, err_info);
5018 case WTAP_ERR_CANT_WRITE_TO_PIPE:
5019 /* Seen only when opening a capture file for writing. */
5020 simple_error_message_box(
5021 "The file \"%s\" is a pipe, and %s capture files can't be "
5022 "written to a pipe.",
5023 display_basename, wtap_file_type_subtype_string(file_type));
5026 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
5027 /* Seen only when opening a capture file for writing. */
5028 simple_error_message_box(
5029 "Wireshark doesn't support writing capture files in that format.");
5032 case WTAP_ERR_UNSUPPORTED_ENCAP:
5034 simple_error_message_box("Wireshark can't save this capture in that format.");
5036 simple_error_message_box(
5037 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
5039 display_basename, err_info);
5044 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
5046 simple_error_message_box(
5047 "Wireshark can't save this capture in that format.");
5049 simple_error_message_box(
5050 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
5055 case WTAP_ERR_BAD_FILE:
5056 /* Seen only when opening a capture file for reading. */
5057 simple_error_message_box(
5058 "The file \"%s\" appears to be damaged or corrupt.\n"
5060 display_basename, err_info);
5064 case WTAP_ERR_CANT_OPEN:
5066 simple_error_message_box(
5067 "The file \"%s\" could not be created for some unknown reason.",
5070 simple_error_message_box(
5071 "The file \"%s\" could not be opened for some unknown reason.",
5076 case WTAP_ERR_SHORT_READ:
5077 simple_error_message_box(
5078 "The file \"%s\" appears to have been cut short"
5079 " in the middle of a packet or other data.",
5083 case WTAP_ERR_SHORT_WRITE:
5084 simple_error_message_box(
5085 "A full header couldn't be written to the file \"%s\".",
5089 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
5090 simple_error_message_box(
5091 "This file type cannot be written as a compressed file.");
5094 case WTAP_ERR_DECOMPRESS:
5095 simple_error_message_box(
5096 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
5097 "(%s)", display_basename, err_info);
5102 simple_error_message_box(
5103 "The file \"%s\" could not be %s: %s.",
5105 for_writing ? "created" : "opened",
5106 wtap_strerror(err));
5109 g_free(display_basename);
5112 open_failure_alert_box(filename, err, for_writing);
5117 * XXX - whether we mention the source pathname, the target pathname,
5118 * or both depends on the error and on what we find if we look for
5119 * one or both of them.
5122 cf_rename_failure_alert_box(const char *filename, int err)
5124 gchar *display_basename;
5126 display_basename = g_filename_display_basename(filename);
5130 /* XXX - should check whether the source exists and, if not,
5131 report it as the problem and, if so, report the destination
5133 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
5138 /* XXX - if we're doing a rename after a safe save, we should
5139 probably say something else. */
5140 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
5145 /* XXX - this should probably mention both the source and destination
5147 simple_error_message_box("The file \"%s\" could not be moved: %s.",
5148 display_basename, wtap_strerror(err));
5151 g_free(display_basename);
5154 /* Check for write errors - if the file is being written to an NFS server,
5155 a write error may not show up until the file is closed, as NFS clients
5156 might not send writes to the server until the "write()" call finishes,
5157 so that the write may fail on the server but the "write()" may succeed. */
5159 cf_close_failure_alert_box(const char *filename, int err)
5161 gchar *display_basename;
5164 /* Wiretap error. */
5165 display_basename = g_filename_display_basename(filename);
5168 case WTAP_ERR_CANT_CLOSE:
5169 simple_error_message_box(
5170 "The file \"%s\" couldn't be closed for some unknown reason.",
5174 case WTAP_ERR_SHORT_WRITE:
5175 simple_error_message_box(
5176 "Not all the packets could be written to the file \"%s\".",
5181 simple_error_message_box(
5182 "An error occurred while closing the file \"%s\": %s.",
5183 display_basename, wtap_strerror(err));
5186 g_free(display_basename);
5189 We assume that a close error from the OS is really a write error. */
5190 write_failure_alert_box(filename, err);
5194 /* Reload the current capture file. */
5196 cf_reload(capture_file *cf) {
5198 gboolean is_tempfile;
5201 /* If the file could be opened, "cf_open()" calls "cf_close()"
5202 to get rid of state for the old capture file before filling in state
5203 for the new capture file. "cf_close()" will remove the file if
5204 it's a temporary file; we don't want that to happen (for one thing,
5205 it'd prevent subsequent reopens from working). Remember whether it's
5206 a temporary file, mark it as not being a temporary file, and then
5207 reopen it as the type of file it was.
5209 Also, "cf_close()" will free "cf->filename", so we must make
5210 a copy of it first. */
5211 filename = g_strdup(cf->filename);
5212 is_tempfile = cf->is_tempfile;
5213 cf->is_tempfile = FALSE;
5214 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
5215 switch (cf_read(cf, TRUE)) {
5219 /* Just because we got an error, that doesn't mean we were unable
5220 to read any of the file; we handle what we could get from the
5224 case CF_READ_ABORTED:
5225 /* The user bailed out of re-reading the capture file; the
5226 capture file has been closed - just free the capture file name
5227 string and return (without changing the last containing
5233 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
5234 Instead, the file was left open, so we should restore "cf->is_tempfile"
5237 XXX - change the menu? Presumably "cf_open()" will do that;
5238 make sure it does! */
5239 cf->is_tempfile = is_tempfile;
5241 /* "cf_open()" made a copy of the file name we handed it, so
5242 we should free up our copy. */
5252 * indent-tabs-mode: nil
5255 * ex: set shiftwidth=2 tabstop=8 expandtab:
5256 * :indentSize=2:tabSize=8:noTabs=true: