Put the structure of a capture_file back in cfile.h.
[metze/wireshark/wip.git] / file.c
1 /* file.c
2  * File I/O routines
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * SPDX-License-Identifier: GPL-2.0+
9  */
10
11 #include <config.h>
12
13 #include <time.h>
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include <errno.h>
20
21 #include <wsutil/tempfile.h>
22 #include <wsutil/file_util.h>
23 #include <wsutil/filesystem.h>
24 #include <version_info.h>
25
26 #include <wiretap/merge.h>
27
28 #include <epan/exceptions.h>
29 #include <epan/epan-int.h>
30 #include <epan/epan.h>
31 #include <epan/column.h>
32 #include <epan/packet.h>
33 #include <epan/column-utils.h>
34 #include <epan/expert.h>
35 #include <epan/prefs.h>
36 #include <epan/dfilter/dfilter.h>
37 #include <epan/epan_dissect.h>
38 #include <epan/tap.h>
39 #include <epan/dissectors/packet-ber.h>
40 #include <epan/timestamp.h>
41 #include <epan/dfilter/dfilter-macro.h>
42 #include <epan/strutil.h>
43 #include <epan/addr_resolv.h>
44 #include <epan/color_filters.h>
45
46 #include "cfile.h"
47 #include "file.h"
48 #include "fileset.h"
49 #include "frame_tvbuff.h"
50
51 #include "ui/alert_box.h"
52 #include "ui/simple_dialog.h"
53 #include "ui/main_statusbar.h"
54 #include "ui/progress_dlg.h"
55 #include "ui/ws_ui_util.h"
56
57 /* Needed for addrinfo */
58 #ifdef HAVE_SYS_TYPES_H
59 # include <sys/types.h>
60 #endif
61
62 #ifdef HAVE_SYS_SOCKET_H
63 #include <sys/socket.h>
64 #endif
65
66 #ifdef HAVE_NETINET_IN_H
67 # include <netinet/in.h>
68 #endif
69
70 #ifdef _WIN32
71 # include <winsock2.h>
72 # include <ws2tcpip.h>
73 #endif
74
75 #ifdef HAVE_LIBPCAP
76 gboolean auto_scroll_live; /* GTK+ only? */
77 #endif
78
79 static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
80     column_info *cinfo, gint64 offset);
81
82 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
83
84 typedef enum {
85   MR_NOTMATCHED,
86   MR_MATCHED,
87   MR_ERROR
88 } match_result;
89 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
90     void *criterion);
91 static void match_subtree_text(proto_node *node, gpointer data);
92 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
93     void *criterion);
94 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
95     void *criterion);
96 static match_result match_narrow(capture_file *cf, frame_data *fdata,
97     void *criterion);
98 static match_result match_wide(capture_file *cf, frame_data *fdata,
99     void *criterion);
100 static match_result match_binary(capture_file *cf, frame_data *fdata,
101     void *criterion);
102 static match_result match_regex(capture_file *cf, frame_data *fdata,
103     void *criterion);
104 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
105     void *criterion);
106 static match_result match_marked(capture_file *cf, frame_data *fdata,
107     void *criterion);
108 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
109     void *criterion);
110 static gboolean find_packet(capture_file *cf,
111     match_result (*match_function)(capture_file *, frame_data *, void *),
112     void *criterion, search_direction dir);
113
114 static const char *cf_get_user_packet_comment(frame_set *fs, const frame_data *fd);
115
116 static void cf_rename_failure_alert_box(const char *filename, int err);
117 static void ref_time_packets(capture_file *cf);
118
119 /* Seconds spent processing packets between pushing UI updates. */
120 #define PROGBAR_UPDATE_INTERVAL 0.150
121
122 /* Show the progress bar after this many seconds. */
123 #define PROGBAR_SHOW_DELAY 0.5
124
125 /*
126  * We could probably use g_signal_...() instead of the callbacks below but that
127  * would require linking our CLI programs to libgobject and creating an object
128  * instance for the signals.
129  */
130 typedef struct {
131   cf_callback_t cb_fct;
132   gpointer      user_data;
133 } cf_callback_data_t;
134
135 static GList *cf_callbacks = NULL;
136
137 static void
138 cf_callback_invoke(int event, gpointer data)
139 {
140   cf_callback_data_t *cb;
141   GList              *cb_item = cf_callbacks;
142
143   /* there should be at least one interested */
144   g_assert(cb_item != NULL);
145
146   while (cb_item != NULL) {
147     cb = (cf_callback_data_t *)cb_item->data;
148     cb->cb_fct(event, data, cb->user_data);
149     cb_item = g_list_next(cb_item);
150   }
151 }
152
153
154 void
155 cf_callback_add(cf_callback_t func, gpointer user_data)
156 {
157   cf_callback_data_t *cb;
158
159   cb = g_new(cf_callback_data_t,1);
160   cb->cb_fct = func;
161   cb->user_data = user_data;
162
163   cf_callbacks = g_list_prepend(cf_callbacks, cb);
164 }
165
166 void
167 cf_callback_remove(cf_callback_t func, gpointer user_data)
168 {
169   cf_callback_data_t *cb;
170   GList              *cb_item = cf_callbacks;
171
172   while (cb_item != NULL) {
173     cb = (cf_callback_data_t *)cb_item->data;
174     if (cb->cb_fct == func && cb->user_data == user_data) {
175       cf_callbacks = g_list_remove(cf_callbacks, cb);
176       g_free(cb);
177       return;
178     }
179     cb_item = g_list_next(cb_item);
180   }
181
182   g_assert_not_reached();
183 }
184
185 void
186 cf_timestamp_auto_precision(capture_file *cf)
187 {
188   int i;
189
190   /* don't try to get the file's precision if none is opened */
191   if (cf->state == FILE_CLOSED) {
192     return;
193   }
194
195   /* Set the column widths of those columns that show the time in
196      "command-line-specified" format. */
197   for (i = 0; i < cf->cinfo.num_cols; i++) {
198     if (col_has_time_fmt(&cf->cinfo, i)) {
199       packet_list_resize_column(i);
200     }
201   }
202 }
203
204 gulong
205 cf_get_computed_elapsed(capture_file *cf)
206 {
207   return cf->computed_elapsed;
208 }
209
210 /*
211  * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
212  * replace this
213  */
214 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
215 {
216   gdouble  delta_time;
217   GTimeVal time_now;
218
219   g_get_current_time(&time_now);
220
221   delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
222     time_now.tv_usec - start_time->tv_usec;
223
224   cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
225 }
226
227 static const nstime_t *
228 ws_get_frame_ts(frame_set *fs, guint32 frame_num)
229 {
230   if (fs->prev_dis && fs->prev_dis->num == frame_num)
231     return &fs->prev_dis->abs_ts;
232
233   if (fs->prev_cap && fs->prev_cap->num == frame_num)
234     return &fs->prev_cap->abs_ts;
235
236   if (fs->frames) {
237     frame_data *fd = frame_data_sequence_find(fs->frames, frame_num);
238
239     return (fd) ? &fd->abs_ts : NULL;
240   }
241
242   return NULL;
243 }
244
245 static const char *
246 ws_get_user_comment(frame_set *fs, const frame_data *fd)
247 {
248   return cf_get_user_packet_comment(fs, fd);
249 }
250
251 static epan_t *
252 ws_epan_new(capture_file *cf)
253 {
254   epan_t *epan = epan_new();
255
256   epan->fs = &cf->frame_set_info;
257   epan->get_frame_ts = ws_get_frame_ts;
258   epan->get_interface_name = frame_set_get_interface_name;
259   epan->get_interface_description = frame_set_get_interface_description;
260   epan->get_user_comment = ws_get_user_comment;
261
262   return epan;
263 }
264
265 cf_status_t
266 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
267 {
268   wtap  *wth;
269   gchar *err_info;
270
271   wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
272   if (wth == NULL)
273     goto fail;
274
275   /* The open succeeded.  Close whatever capture file we had open,
276      and fill in the information for this file. */
277   cf_close(cf);
278
279   /* Initialize the packet header. */
280   wtap_phdr_init(&cf->phdr);
281
282   /* XXX - we really want to initialize this after we've read all
283      the packets, so we know how much we'll ultimately need. */
284   ws_buffer_init(&cf->buf, 1500);
285
286   /* Create new epan session for dissection.
287    * (The old one was freed in cf_close().)
288    */
289   cf->epan = ws_epan_new(cf);
290
291   /* We're about to start reading the file. */
292   cf->state = FILE_READ_IN_PROGRESS;
293
294   cf->frame_set_info.wth = wth;
295   cf->f_datalen = 0;
296
297   /* Set the file name because we need it to set the follow stream filter.
298      XXX - is that still true?  We need it for other reasons, though,
299      in any case. */
300   cf->filename = g_strdup(fname);
301
302   /* Indicate whether it's a permanent or temporary file. */
303   cf->is_tempfile = is_tempfile;
304
305   /* No user changes yet. */
306   cf->unsaved_changes = FALSE;
307
308   cf->computed_elapsed = 0;
309
310   cf->cd_t        = wtap_file_type_subtype(cf->frame_set_info.wth);
311   cf->open_type   = type;
312   cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
313   cf->count     = 0;
314   cf->packet_comment_count = 0;
315   cf->displayed_count = 0;
316   cf->marked_count = 0;
317   cf->ignored_count = 0;
318   cf->ref_time_count = 0;
319   cf->drops_known = FALSE;
320   cf->drops     = 0;
321   cf->snap      = wtap_snapshot_length(cf->frame_set_info.wth);
322
323   /* Allocate a frame_data_sequence for the frames in this file */
324   cf->frame_set_info.frames = new_frame_data_sequence();
325
326   nstime_set_zero(&cf->elapsed_time);
327   cf->frame_set_info.ref = NULL;
328   cf->frame_set_info.prev_dis = NULL;
329   cf->frame_set_info.prev_cap = NULL;
330   cf->cum_bytes = 0;
331
332   packet_list_queue_draw();
333   cf_callback_invoke(cf_cb_file_opened, cf);
334
335   if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
336     /* tell the BER dissector the file name */
337     ber_set_filename(cf->filename);
338   }
339
340   wtap_set_cb_new_ipv4(cf->frame_set_info.wth, add_ipv4_name);
341   wtap_set_cb_new_ipv6(cf->frame_set_info.wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
342
343   return CF_OK;
344
345 fail:
346   cfile_open_failure_alert_box(fname, *err, err_info);
347   return CF_ERROR;
348 }
349
350 /*
351  * Add an encapsulation type to cf->linktypes.
352  */
353 static void
354 cf_add_encapsulation_type(capture_file *cf, int encap)
355 {
356   guint i;
357
358   for (i = 0; i < cf->linktypes->len; i++) {
359     if (g_array_index(cf->linktypes, gint, i) == encap)
360       return; /* it's already there */
361   }
362   /* It's not already there - add it. */
363   g_array_append_val(cf->linktypes, encap);
364 }
365
366 /* Reset everything to a pristine state */
367 void
368 cf_close(capture_file *cf)
369 {
370   cf->stop_flag = FALSE;
371   if (cf->state == FILE_CLOSED)
372     return; /* Nothing to do */
373
374   /* Die if we're in the middle of reading a file. */
375   g_assert(cf->state != FILE_READ_IN_PROGRESS);
376
377   cf_callback_invoke(cf_cb_file_closing, cf);
378
379   /* close things, if not already closed before */
380   color_filters_cleanup();
381
382   if (cf->frame_set_info.wth) {
383     wtap_close(cf->frame_set_info.wth);
384     cf->frame_set_info.wth = NULL;
385   }
386   /* We have no file open... */
387   if (cf->filename != NULL) {
388     /* If it's a temporary file, remove it. */
389     if (cf->is_tempfile)
390       ws_unlink(cf->filename);
391     g_free(cf->filename);
392     cf->filename = NULL;
393   }
394   /* ...which means we have no changes to that file to save. */
395   cf->unsaved_changes = FALSE;
396
397   /* no open_routine type */
398   cf->open_type = WTAP_TYPE_AUTO;
399
400   /* Clean up the packet header. */
401   wtap_phdr_cleanup(&cf->phdr);
402
403   /* Free up the packet buffer. */
404   ws_buffer_free(&cf->buf);
405
406   dfilter_free(cf->rfcode);
407   cf->rfcode = NULL;
408   if (cf->frame_set_info.frames != NULL) {
409     free_frame_data_sequence(cf->frame_set_info.frames);
410     cf->frame_set_info.frames = NULL;
411   }
412   if (cf->frame_set_info.frames_user_comments) {
413     g_tree_destroy(cf->frame_set_info.frames_user_comments);
414     cf->frame_set_info.frames_user_comments = NULL;
415   }
416   cf_unselect_packet(cf);   /* nothing to select */
417   cf->first_displayed = 0;
418   cf->last_displayed = 0;
419
420   /* No frames, no frame selected, no field in that frame selected. */
421   cf->count = 0;
422   cf->current_frame = 0;
423   cf->current_row = 0;
424   cf->finfo_selected = NULL;
425
426   /* No frame link-layer types, either. */
427   if (cf->linktypes != NULL) {
428     g_array_free(cf->linktypes, TRUE);
429     cf->linktypes = NULL;
430   }
431
432   /* Clear the packet list. */
433   packet_list_freeze();
434   packet_list_clear();
435   packet_list_thaw();
436
437   cf->f_datalen = 0;
438   nstime_set_zero(&cf->elapsed_time);
439
440   reset_tap_listeners();
441
442   epan_free(cf->epan);
443   cf->epan = NULL;
444
445   /* We have no file open. */
446   cf->state = FILE_CLOSED;
447
448   cf_callback_invoke(cf_cb_file_closed, cf);
449 }
450
451 /*
452  * TRUE if the progress dialog doesn't exist and it looks like we'll
453  * take > 2s to load, FALSE otherwise.
454  */
455 static inline gboolean
456 progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
457 {
458   double elapsed;
459
460   if (progdlg) return FALSE;
461   elapsed = g_timer_elapsed(prog_timer, NULL);
462   if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */
463       || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
464     return TRUE;
465   }
466   return FALSE;
467 }
468
469 static float
470 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
471 {
472   float progbar_val;
473
474   progbar_val = (gfloat) file_pos / (gfloat) size;
475   if (progbar_val > 1.0) {
476
477     /*  The file probably grew while we were reading it.
478      *  Update file size, and try again.
479      */
480     size = wtap_file_size(cf->frame_set_info.wth, NULL);
481
482     if (size >= 0)
483       progbar_val = (gfloat) file_pos / (gfloat) size;
484
485     /*  If it's still > 1, either "wtap_file_size()" failed (in which
486      *  case there's not much we can do about it), or the file
487      *  *shrank* (in which case there's not much we can do about
488      *  it); just clip the progress value at 1.0.
489      */
490     if (progbar_val > 1.0f)
491       progbar_val = 1.0f;
492   }
493
494   g_snprintf(status_str, status_size,
495              "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
496              file_pos / 1024, size / 1024);
497
498   return progbar_val;
499 }
500
501 cf_read_status_t
502 cf_read(capture_file *cf, gboolean reloading)
503 {
504   int                  err = 0;
505   gchar               *err_info = NULL;
506   gchar               *name_ptr;
507   progdlg_t           *volatile progbar = NULL;
508   GTimer              *prog_timer = g_timer_new();
509   GTimeVal             start_time;
510   epan_dissect_t       edt;
511   dfilter_t           *dfcode;
512   volatile gboolean    create_proto_tree;
513   guint                tap_flags;
514   gboolean             compiled;
515   volatile gboolean    is_read_aborted = FALSE;
516
517   /* Compile the current display filter.
518    * We assume this will not fail since cf->dfilter is only set in
519    * cf_filter IFF the filter was valid.
520    */
521   compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
522   g_assert(!cf->dfilter || (compiled && dfcode));
523
524   /* Get the union of the flags for all tap listeners. */
525   tap_flags = union_of_tap_listener_flags();
526
527   /*
528    * Determine whether we need to create a protocol tree.
529    * We do if:
530    *
531    *    we're going to apply a display filter;
532    *
533    *    one of the tap listeners is going to apply a filter;
534    *
535    *    one of the tap listeners requires a protocol tree;
536    *
537    *    a postdissector wants field values or protocols on
538    *    the first pass.
539    */
540   create_proto_tree =
541     (dfcode != NULL || have_filtering_tap_listeners() ||
542      (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
543
544   reset_tap_listeners();
545
546   name_ptr = g_filename_display_basename(cf->filename);
547
548   if (reloading)
549     cf_callback_invoke(cf_cb_file_reload_started, cf);
550   else
551     cf_callback_invoke(cf_cb_file_read_started, cf);
552
553   /* Record whether the file is compressed.
554      XXX - do we know this at open time? */
555   cf->iscompressed = wtap_iscompressed(cf->frame_set_info.wth);
556
557   /* The packet list window will be empty until the file is completly loaded */
558   packet_list_freeze();
559
560   cf->stop_flag = FALSE;
561   g_get_current_time(&start_time);
562
563   epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
564
565   TRY {
566     int     count             = 0;
567
568     gint64  size;
569     gint64  file_pos;
570     gint64  data_offset;
571
572     float   progbar_val;
573     gchar   status_str[100];
574
575     column_info *cinfo;
576
577     /* If any tap listeners require the columns, construct them. */
578     cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
579
580     /* Find the size of the file. */
581     size = wtap_file_size(cf->frame_set_info.wth, NULL);
582
583     g_timer_start(prog_timer);
584
585     while ((wtap_read(cf->frame_set_info.wth, &err, &err_info, &data_offset))) {
586       if (size >= 0) {
587         count++;
588         file_pos = wtap_read_so_far(cf->frame_set_info.wth);
589
590         /* Create the progress bar if necessary. */
591         if (progress_is_slow(progbar, prog_timer, size, file_pos)) {
592           progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
593           if (reloading)
594             progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
595                 TRUE, &cf->stop_flag, &start_time, progbar_val);
596           else
597             progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
598                 TRUE, &cf->stop_flag, &start_time, progbar_val);
599         }
600
601         /*
602          * Update the progress bar, but do it only after
603          * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
604          * and packets_bar_update will likely trigger UI paint events, which
605          * might take a while depending on the platform and display. Reset
606          * our timer *after* painting.
607          */
608         if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
609           progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
610           /* update the packet bar content on the first run or frequently on very large files */
611           update_progress_dlg(progbar, progbar_val, status_str);
612           compute_elapsed(cf, &start_time);
613           packets_bar_update();
614           g_timer_start(prog_timer);
615         }
616       }
617
618       if (cf->state == FILE_READ_ABORTED) {
619         /* Well, the user decided to exit Wireshark.  Break out of the
620            loop, and let the code below (which is called even if there
621            aren't any packets left to read) exit. */
622         is_read_aborted = TRUE;
623         break;
624       }
625       if (cf->stop_flag) {
626         /* Well, the user decided to abort the read. He/She will be warned and
627            it might be enough for him/her to work with the already loaded
628            packets.
629            This is especially true for very large capture files, where you don't
630            want to wait loading the whole file (which may last minutes or even
631            hours even on fast machines) just to see that it was the wrong file. */
632         break;
633       }
634       read_packet(cf, dfcode, &edt, cinfo, data_offset);
635     }
636   }
637   CATCH(OutOfMemoryError) {
638     simple_message_box(ESD_TYPE_ERROR, NULL,
639                    "More information and workarounds can be found at\n"
640                    "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
641                    "Sorry, but Wireshark has run out of memory and has to terminate now.");
642 #if 0
643     /* Could we close the current capture and free up memory from that? */
644 #else
645     /* we have to terminate, as we cannot recover from the memory error */
646     exit(1);
647 #endif
648   }
649   ENDTRY;
650
651   /* Free the display name */
652   g_free(name_ptr);
653
654   /* Cleanup and release all dfilter resources */
655   dfilter_free(dfcode);
656
657   epan_dissect_cleanup(&edt);
658
659   /* We're done reading the file; destroy the progress bar if it was created. */
660   if (progbar != NULL)
661     destroy_progress_dlg(progbar);
662   g_timer_destroy(prog_timer);
663
664   /* We're done reading sequentially through the file. */
665   cf->state = FILE_READ_DONE;
666
667   /* Close the sequential I/O side, to free up memory it requires. */
668   wtap_sequential_close(cf->frame_set_info.wth);
669
670   /* Allow the protocol dissectors to free up memory that they
671    * don't need after the sequential run-through of the packets. */
672   postseq_cleanup_all_protocols();
673
674   /* compute the time it took to load the file */
675   compute_elapsed(cf, &start_time);
676
677   /* Set the file encapsulation type now; we don't know what it is until
678      we've looked at all the packets, as we don't know until then whether
679      there's more than one type (and thus whether it's
680      WTAP_ENCAP_PER_PACKET). */
681   cf->lnk_t = wtap_file_encap(cf->frame_set_info.wth);
682
683   cf->current_frame = frame_data_sequence_find(cf->frame_set_info.frames, cf->first_displayed);
684   cf->current_row = 0;
685
686   packet_list_thaw();
687   if (reloading)
688     cf_callback_invoke(cf_cb_file_reload_finished, cf);
689   else
690     cf_callback_invoke(cf_cb_file_read_finished, cf);
691
692   /* If we have any displayed packets to select, select the first of those
693      packets by making the first row the selected row. */
694   if (cf->first_displayed != 0) {
695     packet_list_select_first_row();
696   }
697
698   if (is_read_aborted) {
699     /*
700      * Well, the user decided to exit Wireshark while reading this *offline*
701      * capture file (Live captures are handled by something like
702      * cf_continue_tail). Clean up accordingly.
703      */
704     cf_close(cf);
705     return CF_READ_ABORTED;
706   }
707
708   if (cf->stop_flag) {
709     simple_message_box(ESD_TYPE_WARN, NULL,
710                   "The remaining packets in the file were discarded.\n"
711                   "\n"
712                   "As a lot of packets from the original file will be missing,\n"
713                   "remember to be careful when saving the current content to a file.\n",
714                   "File loading was cancelled.");
715     return CF_READ_ERROR;
716   }
717
718   if (err != 0) {
719     /* Put up a message box noting that the read failed somewhere along
720        the line.  Don't throw out the stuff we managed to read, though,
721        if any. */
722     cfile_read_failure_alert_box(NULL, err, err_info);
723     return CF_READ_ERROR;
724   } else
725     return CF_READ_OK;
726 }
727
728 #ifdef HAVE_LIBPCAP
729 cf_read_status_t
730 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
731 {
732   gchar            *err_info;
733   volatile int      newly_displayed_packets = 0;
734   dfilter_t        *dfcode;
735   epan_dissect_t    edt;
736   gboolean          create_proto_tree;
737   guint             tap_flags;
738   gboolean          compiled;
739
740   /* Compile the current display filter.
741    * We assume this will not fail since cf->dfilter is only set in
742    * cf_filter IFF the filter was valid.
743    */
744   compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
745   g_assert(!cf->dfilter || (compiled && dfcode));
746
747   /* Get the union of the flags for all tap listeners. */
748   tap_flags = union_of_tap_listener_flags();
749
750   /*
751    * Determine whether we need to create a protocol tree.
752    * We do if:
753    *
754    *    we're going to apply a display filter;
755    *
756    *    one of the tap listeners is going to apply a filter;
757    *
758    *    one of the tap listeners requires a protocol tree;
759    *
760    *    a postdissector wants field values or protocols on
761    *    the first pass.
762    */
763   create_proto_tree =
764     (dfcode != NULL || have_filtering_tap_listeners() ||
765      (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
766
767   *err = 0;
768
769   packet_list_check_end();
770   /* Don't freeze/thaw the list when doing live capture */
771   /*packet_list_freeze();*/
772
773   /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
774
775   epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
776
777   TRY {
778     gint64 data_offset = 0;
779     column_info *cinfo;
780
781     /* If any tap listeners require the columns, construct them. */
782     cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
783
784     while (to_read != 0) {
785       wtap_cleareof(cf->frame_set_info.wth);
786       if (!wtap_read(cf->frame_set_info.wth, err, &err_info, &data_offset)) {
787         break;
788       }
789       if (cf->state == FILE_READ_ABORTED) {
790         /* Well, the user decided to exit Wireshark.  Break out of the
791            loop, and let the code below (which is called even if there
792            aren't any packets left to read) exit. */
793         break;
794       }
795       if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
796         newly_displayed_packets++;
797       }
798       to_read--;
799     }
800   }
801   CATCH(OutOfMemoryError) {
802     simple_message_box(ESD_TYPE_ERROR, NULL,
803                    "More information and workarounds can be found at\n"
804                    "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
805                    "Sorry, but Wireshark has run out of memory and has to terminate now.");
806 #if 0
807     /* Could we close the current capture and free up memory from that? */
808     return CF_READ_ABORTED;
809 #else
810     /* we have to terminate, as we cannot recover from the memory error */
811     exit(1);
812 #endif
813   }
814   ENDTRY;
815
816   /* Update the file encapsulation; it might have changed based on the
817      packets we've read. */
818   cf->lnk_t = wtap_file_encap(cf->frame_set_info.wth);
819
820   /* Cleanup and release all dfilter resources */
821   dfilter_free(dfcode);
822
823   epan_dissect_cleanup(&edt);
824
825   /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
826     cf->count, cf->state, *err);*/
827
828   /* Don't freeze/thaw the list when doing live capture */
829   /*packet_list_thaw();*/
830   /* With the new packet list the first packet
831    * isn't automatically selected.
832    */
833   if (!cf->current_frame)
834     packet_list_select_first_row();
835
836   /* moving to the end of the packet list - if the user requested so and
837      we have some new packets. */
838   if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
839       packet_list_moveto_end();
840
841   if (cf->state == FILE_READ_ABORTED) {
842     /* Well, the user decided to exit Wireshark.  Return CF_READ_ABORTED
843        so that our caller can kill off the capture child process;
844        this will cause an EOF on the pipe from the child, so
845        "cf_finish_tail()" will be called, and it will clean up
846        and exit. */
847     return CF_READ_ABORTED;
848   } else if (*err != 0) {
849     /* We got an error reading the capture file.
850        XXX - pop up a dialog box instead? */
851     if (err_info != NULL) {
852       g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
853                 wtap_strerror(*err), cf->filename, err_info);
854       g_free(err_info);
855     } else {
856       g_warning("Error \"%s\" while reading \"%s\"",
857                 wtap_strerror(*err), cf->filename);
858     }
859     return CF_READ_ERROR;
860   } else
861     return CF_READ_OK;
862 }
863
864 void
865 cf_fake_continue_tail(capture_file *cf) {
866   cf->state = FILE_READ_DONE;
867 }
868
869 cf_read_status_t
870 cf_finish_tail(capture_file *cf, int *err)
871 {
872   gchar     *err_info;
873   gint64     data_offset;
874   dfilter_t *dfcode;
875   column_info *cinfo;
876   epan_dissect_t edt;
877   gboolean   create_proto_tree;
878   guint      tap_flags;
879   gboolean   compiled;
880
881   /* Compile the current display filter.
882    * We assume this will not fail since cf->dfilter is only set in
883    * cf_filter IFF the filter was valid.
884    */
885   compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
886   g_assert(!cf->dfilter || (compiled && dfcode));
887
888   /* Get the union of the flags for all tap listeners. */
889   tap_flags = union_of_tap_listener_flags();
890
891   /* If any tap listeners require the columns, construct them. */
892   cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
893
894   /*
895    * Determine whether we need to create a protocol tree.
896    * We do if:
897    *
898    *    we're going to apply a display filter;
899    *
900    *    one of the tap listeners is going to apply a filter;
901    *
902    *    one of the tap listeners requires a protocol tree;
903    *
904    *    a postdissector wants field values or protocols on
905    *    the first pass.
906    */
907   create_proto_tree =
908     (dfcode != NULL || have_filtering_tap_listeners() ||
909      (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
910
911   if (cf->frame_set_info.wth == NULL) {
912     cf_close(cf);
913     return CF_READ_ERROR;
914   }
915
916   packet_list_check_end();
917   /* Don't freeze/thaw the list when doing live capture */
918   /*packet_list_freeze();*/
919
920   epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
921
922   while ((wtap_read(cf->frame_set_info.wth, err, &err_info, &data_offset))) {
923     if (cf->state == FILE_READ_ABORTED) {
924       /* Well, the user decided to abort the read.  Break out of the
925          loop, and let the code below (which is called even if there
926          aren't any packets left to read) exit. */
927       break;
928     }
929     read_packet(cf, dfcode, &edt, cinfo, data_offset);
930   }
931
932   /* Cleanup and release all dfilter resources */
933   dfilter_free(dfcode);
934
935   epan_dissect_cleanup(&edt);
936
937   /* Don't freeze/thaw the list when doing live capture */
938   /*packet_list_thaw();*/
939
940   if (cf->state == FILE_READ_ABORTED) {
941     /* Well, the user decided to abort the read.  We're only called
942        when the child capture process closes the pipe to us (meaning
943        it's probably exited), so we can just close the capture
944        file; we return CF_READ_ABORTED so our caller can do whatever
945        is appropriate when that happens. */
946     cf_close(cf);
947     return CF_READ_ABORTED;
948   }
949
950   if (auto_scroll_live && cf->count != 0)
951     packet_list_moveto_end();
952
953   /* We're done reading sequentially through the file. */
954   cf->state = FILE_READ_DONE;
955
956   /* We're done reading sequentially through the file; close the
957      sequential I/O side, to free up memory it requires. */
958   wtap_sequential_close(cf->frame_set_info.wth);
959
960   /* Allow the protocol dissectors to free up memory that they
961    * don't need after the sequential run-through of the packets. */
962   postseq_cleanup_all_protocols();
963
964   /* Update the file encapsulation; it might have changed based on the
965      packets we've read. */
966   cf->lnk_t = wtap_file_encap(cf->frame_set_info.wth);
967
968   /* Update the details in the file-set dialog, as the capture file
969    * has likely grown since we first stat-ed it */
970   fileset_update_file(cf->filename);
971
972   if (*err != 0) {
973     /* We got an error reading the capture file.
974        XXX - pop up a dialog box? */
975     if (err_info != NULL) {
976       g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
977                 wtap_strerror(*err), cf->filename, err_info);
978       g_free(err_info);
979     } else {
980       g_warning("Error \"%s\" while reading \"%s\"",
981                 wtap_strerror(*err), cf->filename);
982     }
983     return CF_READ_ERROR;
984   } else {
985     return CF_READ_OK;
986   }
987 }
988 #endif /* HAVE_LIBPCAP */
989
990 gchar *
991 cf_get_display_name(capture_file *cf)
992 {
993   gchar *displayname;
994
995   /* Return a name to use in displays */
996   if (!cf->is_tempfile) {
997     /* Get the last component of the file name, and use that. */
998     if (cf->filename) {
999       displayname = g_filename_display_basename(cf->filename);
1000     } else {
1001       displayname=g_strdup("(No file)");
1002     }
1003   } else {
1004     /* The file we read is a temporary file from a live capture or
1005        a merge operation; we don't mention its name, but, if it's
1006        from a capture, give the source of the capture. */
1007     if (cf->source) {
1008       displayname = g_strdup(cf->source);
1009     } else {
1010       displayname = g_strdup("(Untitled)");
1011     }
1012   }
1013   return displayname;
1014 }
1015
1016 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1017   if (cf->source) {
1018     g_free(cf->source);
1019   }
1020
1021   if (source) {
1022     cf->source = g_strdup(source);
1023   } else {
1024     cf->source = g_strdup("");
1025   }
1026 }
1027
1028 const gchar *cf_get_tempfile_source(capture_file *cf) {
1029   if (!cf->source) {
1030     return "";
1031   }
1032
1033   return cf->source;
1034 }
1035
1036 /* XXX - use a macro instead? */
1037 int
1038 cf_get_packet_count(capture_file *cf)
1039 {
1040   return cf->count;
1041 }
1042
1043 /* XXX - use a macro instead? */
1044 gboolean
1045 cf_is_tempfile(capture_file *cf)
1046 {
1047   return cf->is_tempfile;
1048 }
1049
1050 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1051 {
1052   cf->is_tempfile = is_tempfile;
1053 }
1054
1055
1056 /* XXX - use a macro instead? */
1057 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1058 {
1059   cf->drops_known = drops_known;
1060 }
1061
1062 /* XXX - use a macro instead? */
1063 void cf_set_drops(capture_file *cf, guint32 drops)
1064 {
1065   cf->drops = drops;
1066 }
1067
1068 /* XXX - use a macro instead? */
1069 gboolean cf_get_drops_known(capture_file *cf)
1070 {
1071   return cf->drops_known;
1072 }
1073
1074 /* XXX - use a macro instead? */
1075 guint32 cf_get_drops(capture_file *cf)
1076 {
1077   return cf->drops;
1078 }
1079
1080 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1081 {
1082   cf->rfcode = rfcode;
1083 }
1084
1085 static int
1086 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1087     epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1088     struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1089 {
1090   gint            row               = -1;
1091
1092   frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1093                                 &cf->frame_set_info.ref, cf->frame_set_info.prev_dis);
1094   cf->frame_set_info.prev_cap = fdata;
1095
1096   if (dfcode != NULL) {
1097       epan_dissect_prime_with_dfilter(edt, dfcode);
1098   }
1099 #if 0
1100   /* Prepare coloring rules, this ensures that display filter rules containing
1101    * frame.color_rule references are still processed.
1102    * TODO: actually detect that situation or maybe apply other optimizations? */
1103   if (edt->tree && color_filters_used()) {
1104     color_filters_prime_edt(edt);
1105     fdata->flags.need_colorize = 1;
1106   }
1107 #endif
1108
1109   if (!fdata->flags.visited) {
1110     /* This is the first pass, so prime the epan_dissect_t with the
1111        hfids postdissectors want on the first pass. */
1112     prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1113   }
1114
1115   /* Dissect the frame. */
1116   epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1117
1118   /* If we don't have a display filter, set "passed_dfilter" to 1. */
1119   if (dfcode != NULL) {
1120     fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1121
1122     if (fdata->flags.passed_dfilter) {
1123       /* This frame passed the display filter but it may depend on other
1124        * (potentially not displayed) frames.  Find those frames and mark them
1125        * as depended upon.
1126        */
1127       g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frame_set_info.frames);
1128     }
1129   } else
1130     fdata->flags.passed_dfilter = 1;
1131
1132   if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1133     cf->displayed_count++;
1134
1135   if (add_to_packet_list) {
1136     /* We fill the needed columns from new_packet_list */
1137       row = packet_list_append(cinfo, fdata);
1138   }
1139
1140   if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1141   {
1142     frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1143     cf->frame_set_info.prev_dis = fdata;
1144
1145     /* If we haven't yet seen the first frame, this is it. */
1146     if (cf->first_displayed == 0)
1147       cf->first_displayed = fdata->num;
1148
1149     /* This is the last frame we've seen so far. */
1150     cf->last_displayed = fdata->num;
1151   }
1152
1153   epan_dissect_reset(edt);
1154   return row;
1155 }
1156
1157 /* read in a new packet */
1158 /* returns the row of the new packet in the packet list or -1 if not displayed */
1159 static int
1160 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1161             column_info *cinfo, gint64 offset)
1162 {
1163   struct wtap_pkthdr *phdr = wtap_phdr(cf->frame_set_info.wth);
1164   const guint8 *buf = wtap_buf_ptr(cf->frame_set_info.wth);
1165   frame_data    fdlocal;
1166   guint32       framenum;
1167   frame_data   *fdata;
1168   gboolean      passed = TRUE;
1169   int           row = -1;
1170
1171   /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1172      it's not already there.
1173      XXX - yes, this is O(N), so if every packet had a different
1174      link-layer encapsulation type, it'd be O(N^2) to read the file, but
1175      there are probably going to be a small number of encapsulation types
1176      in a file. */
1177   cf_add_encapsulation_type(cf, phdr->pkt_encap);
1178
1179   /* The frame number of this packet is one more than the count of
1180      frames in the file so far. */
1181   framenum = cf->count + 1;
1182
1183   frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1184
1185   if (cf->rfcode) {
1186     epan_dissect_t rf_edt;
1187
1188     epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1189     epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode);
1190     epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1191     passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1192     epan_dissect_cleanup(&rf_edt);
1193   }
1194
1195   if (passed) {
1196     /* This does a shallow copy of fdlocal, which is good enough. */
1197     fdata = frame_data_sequence_add(cf->frame_set_info.frames, &fdlocal);
1198
1199     cf->count++;
1200     if (phdr->opt_comment != NULL)
1201       cf->packet_comment_count++;
1202     cf->f_datalen = offset + fdlocal.cap_len;
1203
1204     if (!cf->redissecting) {
1205       row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1206                                       cinfo, phdr, buf, TRUE);
1207     }
1208   }
1209
1210   return row;
1211 }
1212
1213
1214 typedef struct _callback_data_t {
1215   gpointer         pd_window;
1216   gint64           f_len;
1217   GTimeVal         start_time;
1218   progdlg_t       *progbar;
1219   GTimer          *prog_timer;
1220   gboolean         stop_flag;
1221 } callback_data_t;
1222
1223
1224 static gboolean
1225 merge_callback(merge_event event, int num _U_,
1226                const merge_in_file_t in_files[], const guint in_file_count,
1227                void *data)
1228 {
1229   guint i;
1230   callback_data_t *cb_data = (callback_data_t*) data;
1231
1232   g_assert(cb_data != NULL);
1233
1234   switch (event) {
1235
1236     case MERGE_EVENT_INPUT_FILES_OPENED:
1237       /* do nothing */
1238       break;
1239
1240     case MERGE_EVENT_FRAME_TYPE_SELECTED:
1241       /* do nothing */
1242       break;
1243
1244     case MERGE_EVENT_READY_TO_MERGE:
1245       /* Get the sum of the sizes of all the files. */
1246       for (i = 0; i < in_file_count; i++)
1247         cb_data->f_len += in_files[i].size;
1248
1249       cb_data->prog_timer = g_timer_new();
1250       g_timer_start(cb_data->prog_timer);
1251
1252       g_get_current_time(&cb_data->start_time);
1253       break;
1254
1255     case MERGE_EVENT_PACKET_WAS_READ:
1256       {
1257         gint64 data_offset = 0;
1258
1259         /* Get the sum of the data offsets in all of the files. */
1260         data_offset = 0;
1261         for (i = 0; i < in_file_count; i++)
1262           data_offset += in_files[i].data_offset;
1263
1264         /* Create the progress bar if necessary.
1265            We check on every iteration of the loop, so that it takes no
1266            longer than the standard time to create it (otherwise, for a
1267            large file, we might take considerably longer than that standard
1268            time in order to get to the next progress bar step). */
1269         if (cb_data->progbar == NULL) {
1270           cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, "Merging", "files",
1271             FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1272         }
1273
1274         /*
1275          * Update the progress bar, but do it only after
1276          * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1277          * and packets_bar_update will likely trigger UI paint events, which
1278          * might take a while depending on the platform and display. Reset
1279          * our timer *after* painting.
1280          */
1281         if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1282             float  progbar_val;
1283             gint64 file_pos = 0;
1284             /* Get the sum of the seek positions in all of the files. */
1285             for (i = 0; i < in_file_count; i++)
1286               file_pos += wtap_read_so_far(in_files[i].wth);
1287
1288             progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1289             if (progbar_val > 1.0f) {
1290               /* Some file probably grew while we were reading it.
1291                  That "shouldn't happen", so we'll just clip the progress
1292                  value at 1.0. */
1293               progbar_val = 1.0f;
1294             }
1295
1296             if (cb_data->progbar != NULL) {
1297               gchar status_str[100];
1298               g_snprintf(status_str, sizeof(status_str),
1299                          "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1300                          file_pos / 1024, cb_data->f_len / 1024);
1301               update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1302             }
1303             g_timer_start(cb_data->prog_timer);
1304         }
1305       }
1306       break;
1307
1308     case MERGE_EVENT_DONE:
1309       /* We're done merging the files; destroy the progress bar if it was created. */
1310       if (cb_data->progbar != NULL)
1311         destroy_progress_dlg(cb_data->progbar);
1312       g_timer_destroy(cb_data->prog_timer);
1313       break;
1314   }
1315
1316   return cb_data->stop_flag;
1317 }
1318
1319
1320
1321 cf_status_t
1322 cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
1323                            int in_file_count, char *const *in_filenames,
1324                            int file_type, gboolean do_append)
1325 {
1326   int                        err      = 0;
1327   gchar                     *err_info = NULL;
1328   guint                      err_fileno;
1329   guint32                    err_framenum;
1330   merge_result               status;
1331   merge_progress_callback_t  cb;
1332   callback_data_t           *cb_data = g_new0(callback_data_t, 1);
1333
1334   /* prepare our callback routine */
1335   cb_data->pd_window = pd_window;
1336   cb.callback_func = merge_callback;
1337   cb.data = cb_data;
1338
1339   cf_callback_invoke(cf_cb_file_merge_started, NULL);
1340
1341   /* merge the files */
1342   status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1343                                    (const char *const *) in_filenames,
1344                                    in_file_count, do_append,
1345                                    IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1346                                    "Wireshark", &cb, &err, &err_info,
1347                                    &err_fileno, &err_framenum);
1348
1349   g_free(cb.data);
1350
1351   switch (status) {
1352     case MERGE_OK:
1353       break;
1354
1355     case MERGE_USER_ABORTED:
1356       /* this isn't really an error, though we will return CF_ERROR later */
1357       break;
1358
1359     case MERGE_ERR_CANT_OPEN_INFILE:
1360       cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info);
1361       break;
1362
1363     case MERGE_ERR_CANT_OPEN_OUTFILE:
1364       cfile_dump_open_failure_alert_box(*out_filenamep, err, file_type);
1365       break;
1366
1367     case MERGE_ERR_CANT_READ_INFILE:
1368       cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
1369       break;
1370
1371     case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1372       simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
1373                                err_framenum, in_filenames[err_fileno]);
1374       break;
1375
1376     case MERGE_ERR_CANT_WRITE_OUTFILE:
1377        cfile_write_failure_alert_box(in_filenames[err_fileno],
1378                                      *out_filenamep, err, err_info,
1379                                      err_framenum, file_type);
1380        break;
1381
1382     case MERGE_ERR_CANT_CLOSE_OUTFILE:
1383         cfile_close_failure_alert_box(*out_filenamep, err);
1384         break;
1385
1386     default:
1387       simple_error_message_box("Unknown merge_files error %d", status);
1388       break;
1389   }
1390
1391   cf_callback_invoke(cf_cb_file_merge_finished, NULL);
1392
1393   if (status != MERGE_OK) {
1394     /* Callers aren't expected to treat an error or an explicit abort
1395        differently - we put up error dialogs ourselves, so they don't
1396        have to. */
1397     return CF_ERROR;
1398   } else
1399     return CF_OK;
1400 }
1401
1402 cf_status_t
1403 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1404 {
1405   const char *filter_new = dftext ? dftext : "";
1406   const char *filter_old = cf->dfilter ? cf->dfilter : "";
1407   dfilter_t  *dfcode;
1408   gchar      *err_msg;
1409   GTimeVal    start_time;
1410
1411   /* if new filter equals old one, do nothing unless told to do so */
1412   if (!force && strcmp(filter_new, filter_old) == 0) {
1413     return CF_OK;
1414   }
1415
1416   dfcode=NULL;
1417
1418   if (dftext == NULL) {
1419     /* The new filter is an empty filter (i.e., display all packets).
1420      * so leave dfcode==NULL
1421      */
1422   } else {
1423     /*
1424      * We have a filter; make a copy of it (as we'll be saving it),
1425      * and try to compile it.
1426      */
1427     dftext = g_strdup(dftext);
1428     if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1429       /* The attempt failed; report an error. */
1430       simple_message_box(ESD_TYPE_ERROR, NULL,
1431           "See the help for a description of the display filter syntax.",
1432           "\"%s\" isn't a valid display filter: %s",
1433           dftext, err_msg);
1434       g_free(err_msg);
1435       g_free(dftext);
1436       return CF_ERROR;
1437     }
1438
1439     /* Was it empty? */
1440     if (dfcode == NULL) {
1441       /* Yes - free the filter text, and set it to null. */
1442       g_free(dftext);
1443       dftext = NULL;
1444     }
1445   }
1446
1447   /* We have a valid filter.  Replace the current filter. */
1448   g_free(cf->dfilter);
1449   cf->dfilter = dftext;
1450   g_get_current_time(&start_time);
1451
1452
1453   /* Now rescan the packet list, applying the new filter, but not
1454      throwing away information constructed on a previous pass. */
1455   if (cf->state != FILE_CLOSED) {
1456     if (dftext == NULL) {
1457       rescan_packets(cf, "Resetting", "Filter", FALSE);
1458     } else {
1459       rescan_packets(cf, "Filtering", dftext, FALSE);
1460     }
1461   }
1462
1463   /* Cleanup and release all dfilter resources */
1464   dfilter_free(dfcode);
1465
1466   return CF_OK;
1467 }
1468
1469 void
1470 cf_reftime_packets(capture_file *cf)
1471 {
1472   ref_time_packets(cf);
1473 }
1474
1475 void
1476 cf_redissect_packets(capture_file *cf)
1477 {
1478   if (cf->state != FILE_CLOSED) {
1479     rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1480   }
1481 }
1482
1483 gboolean
1484 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1485                  struct wtap_pkthdr *phdr, Buffer *buf)
1486 {
1487   int    err;
1488   gchar *err_info;
1489
1490   if (!wtap_seek_read(cf->frame_set_info.wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1491     cfile_read_failure_alert_box(cf->filename, err, err_info);
1492     return FALSE;
1493   }
1494   return TRUE;
1495 }
1496
1497 gboolean
1498 cf_read_record(capture_file *cf, frame_data *fdata)
1499 {
1500   return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1501 }
1502
1503 /* Rescan the list of packets, reconstructing the CList.
1504
1505    "action" describes why we're doing this; it's used in the progress
1506    dialog box.
1507
1508    "action_item" describes what we're doing; it's used in the progress
1509    dialog box.
1510
1511    "redissect" is TRUE if we need to make the dissectors reconstruct
1512    any state information they have (because a preference that affects
1513    some dissector has changed, meaning some dissector might construct
1514    its state differently from the way it was constructed the last time). */
1515 static void
1516 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1517 {
1518   /* Rescan packets new packet list */
1519   guint32     framenum;
1520   frame_data *fdata;
1521   progdlg_t  *progbar = NULL;
1522   GTimer     *prog_timer = g_timer_new();
1523   int         count;
1524   frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1525   int         selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1526   gboolean    selected_frame_seen;
1527   float       progbar_val;
1528   GTimeVal    start_time;
1529   gchar       status_str[100];
1530   epan_dissect_t  edt;
1531   dfilter_t  *dfcode;
1532   column_info *cinfo;
1533   gboolean    create_proto_tree;
1534   guint       tap_flags;
1535   gboolean    add_to_packet_list = FALSE;
1536   gboolean    compiled;
1537   guint32     frames_count;
1538
1539   /* Compile the current display filter.
1540    * We assume this will not fail since cf->dfilter is only set in
1541    * cf_filter IFF the filter was valid.
1542    */
1543   compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1544   g_assert(!cf->dfilter || (compiled && dfcode));
1545
1546   /* Get the union of the flags for all tap listeners. */
1547   tap_flags = union_of_tap_listener_flags();
1548
1549   /* If any tap listeners require the columns, construct them. */
1550   cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1551
1552   /*
1553    * Determine whether we need to create a protocol tree.
1554    * We do if:
1555    *
1556    *    we're going to apply a display filter;
1557    *
1558    *    one of the tap listeners is going to apply a filter;
1559    *
1560    *    one of the tap listeners requires a protocol tree;
1561    *
1562    *    we're redissecting and a postdissector wants field
1563    *    values or protocols on the first pass.
1564    */
1565   create_proto_tree =
1566     (dfcode != NULL || have_filtering_tap_listeners() ||
1567      (tap_flags & TL_REQUIRES_PROTO_TREE) ||
1568      (redissect && postdissectors_want_hfids()));
1569
1570   reset_tap_listeners();
1571   /* Which frame, if any, is the currently selected frame?
1572      XXX - should the selected frame or the focus frame be the "current"
1573      frame, that frame being the one from which "Find Frame" searches
1574      start? */
1575   selected_frame = cf->current_frame;
1576
1577   /* Mark frame num as not found */
1578   selected_frame_num = -1;
1579
1580   /* Freeze the packet list while we redo it, so we don't get any
1581      screen updates while it happens. */
1582   packet_list_freeze();
1583
1584   if (redissect) {
1585     /* We need to re-initialize all the state information that protocols
1586        keep, because some preference that controls a dissector has changed,
1587        which might cause the state information to be constructed differently
1588        by that dissector. */
1589
1590     /* We might receive new packets while redissecting, and we don't
1591        want to dissect those before their time. */
1592     cf->redissecting = TRUE;
1593
1594     /* 'reset' dissection session */
1595     epan_free(cf->epan);
1596     if (cf->edt && cf->edt->pi.fd) {
1597       /* All pointers in "per frame proto data" for the currently selected
1598          packet are allocated in wmem_file_scope() and deallocated in epan_free().
1599          Free them here to avoid unintended usage in packet_list_clear(). */
1600       frame_data_destroy(cf->edt->pi.fd);
1601     }
1602     cf->epan = ws_epan_new(cf);
1603     cf->cinfo.epan = cf->epan;
1604
1605     /* A new Lua tap listener may be registered in lua_prime_all_fields()
1606        called via epan_new() / init_dissection() when reloading Lua plugins. */
1607     if (!create_proto_tree && have_filtering_tap_listeners()) {
1608       create_proto_tree = TRUE;
1609     }
1610
1611     /* We need to redissect the packets so we have to discard our old
1612      * packet list store. */
1613     packet_list_clear();
1614     add_to_packet_list = TRUE;
1615   }
1616
1617   /* We don't yet know which will be the first and last frames displayed. */
1618   cf->first_displayed = 0;
1619   cf->last_displayed = 0;
1620
1621   /* We currently don't display any packets */
1622   cf->displayed_count = 0;
1623
1624   /* Iterate through the list of frames.  Call a routine for each frame
1625      to check whether it should be displayed and, if so, add it to
1626      the display list. */
1627   cf->frame_set_info.ref = NULL;
1628   cf->frame_set_info.prev_dis = NULL;
1629   cf->frame_set_info.prev_cap = NULL;
1630   cf->cum_bytes = 0;
1631
1632   cf_callback_invoke(cf_cb_file_rescan_started, cf);
1633
1634   g_timer_start(prog_timer);
1635   /* Count of packets at which we've looked. */
1636   count = 0;
1637   /* Progress so far. */
1638   progbar_val = 0.0f;
1639
1640   cf->stop_flag = FALSE;
1641   g_get_current_time(&start_time);
1642
1643   /* no previous row yet */
1644   prev_frame_num = -1;
1645   prev_frame = NULL;
1646
1647   preceding_frame_num = -1;
1648   preceding_frame = NULL;
1649   following_frame_num = -1;
1650   following_frame = NULL;
1651
1652   selected_frame_seen = FALSE;
1653
1654   frames_count = cf->count;
1655
1656   epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1657
1658   for (framenum = 1; framenum <= frames_count; framenum++) {
1659     fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
1660
1661     /* Create the progress bar if necessary.
1662        We check on every iteration of the loop, so that it takes no
1663        longer than the standard time to create it (otherwise, for a
1664        large file, we might take considerably longer than that standard
1665        time in order to get to the next progress bar step). */
1666     if (progbar == NULL)
1667       progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1668                                             &cf->stop_flag,
1669                                             &start_time,
1670                                             progbar_val);
1671
1672     /*
1673      * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1674      * has elapsed. Calling update_progress_dlg and packets_bar_update will
1675      * likely trigger UI paint events, which might take a while depending on
1676      * the platform and display. Reset our timer *after* painting.
1677      */
1678     if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1679       /* let's not divide by zero. I should never be started
1680        * with count == 0, so let's assert that
1681        */
1682       g_assert(cf->count > 0);
1683       progbar_val = (gfloat) count / frames_count;
1684
1685       if (progbar != NULL) {
1686         g_snprintf(status_str, sizeof(status_str),
1687                   "%4u of %u frames", count, frames_count);
1688         update_progress_dlg(progbar, progbar_val, status_str);
1689       }
1690
1691       g_timer_start(prog_timer);
1692     }
1693
1694     if (cf->stop_flag) {
1695       /* Well, the user decided to abort the filtering.  Just stop.
1696
1697          XXX - go back to the previous filter?  Users probably just
1698          want not to wait for a filtering operation to finish;
1699          unless we cancel by having no filter, reverting to the
1700          previous filter will probably be even more expensive than
1701          continuing the filtering, as it involves going back to the
1702          beginning and filtering, and even with no filter we currently
1703          have to re-generate the entire clist, which is also expensive.
1704
1705          I'm not sure what Network Monitor does, but it doesn't appear
1706          to give you an unfiltered display if you cancel. */
1707       break;
1708     }
1709
1710     count++;
1711
1712     if (redissect) {
1713       /* Since all state for the frame was destroyed, mark the frame
1714        * as not visited, free the GSList referring to the state
1715        * data (the per-frame data itself was freed by
1716        * "init_dissection()"), and null out the GSList pointer. */
1717       frame_data_reset(fdata);
1718       frames_count = cf->count;
1719     }
1720
1721     /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1722     fdata->flags.dependent_of_displayed = 0;
1723
1724     if (!cf_read_record(cf, fdata))
1725       break; /* error reading the frame */
1726
1727     /* If the previous frame is displayed, and we haven't yet seen the
1728        selected frame, remember that frame - it's the closest one we've
1729        yet seen before the selected frame. */
1730     if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1731       preceding_frame_num = prev_frame_num;
1732       preceding_frame = prev_frame;
1733     }
1734
1735     add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1736                                     cinfo, &cf->phdr,
1737                                     ws_buffer_start_ptr(&cf->buf),
1738                                     add_to_packet_list);
1739
1740     /* If this frame is displayed, and this is the first frame we've
1741        seen displayed after the selected frame, remember this frame -
1742        it's the closest one we've yet seen at or after the selected
1743        frame. */
1744     if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1745       following_frame_num = fdata->num;
1746       following_frame = fdata;
1747     }
1748     if (fdata == selected_frame) {
1749       selected_frame_seen = TRUE;
1750       if (fdata->flags.passed_dfilter)
1751           selected_frame_num = fdata->num;
1752     }
1753
1754     /* Remember this frame - it'll be the previous frame
1755        on the next pass through the loop. */
1756     prev_frame_num = fdata->num;
1757     prev_frame = fdata;
1758   }
1759
1760   epan_dissect_cleanup(&edt);
1761
1762   /* We are done redissecting the packet list. */
1763   cf->redissecting = FALSE;
1764
1765   if (redissect) {
1766       frames_count = cf->count;
1767     /* Clear out what remains of the visited flags and per-frame data
1768        pointers.
1769
1770        XXX - that may cause various forms of bogosity when dissecting
1771        these frames, as they won't have been seen by this sequential
1772        pass, but the only alternative I see is to keep scanning them
1773        even though the user requested that the scan stop, and that
1774        would leave the user stuck with an Wireshark grinding on
1775        until it finishes.  Should we just stick them with that? */
1776     for (; framenum <= frames_count; framenum++) {
1777       fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
1778       frame_data_reset(fdata);
1779     }
1780   }
1781
1782   /* We're done filtering the packets; destroy the progress bar if it
1783      was created. */
1784   if (progbar != NULL)
1785     destroy_progress_dlg(progbar);
1786   g_timer_destroy(prog_timer);
1787
1788   /* Unfreeze the packet list. */
1789   if (!add_to_packet_list)
1790     packet_list_recreate_visible_rows();
1791
1792   /* Compute the time it took to filter the file */
1793   compute_elapsed(cf, &start_time);
1794
1795   packet_list_thaw();
1796
1797   cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1798
1799   if (selected_frame_num == -1) {
1800     /* The selected frame didn't pass the filter. */
1801     if (selected_frame == NULL) {
1802       /* That's because there *was* no selected frame.  Make the first
1803          displayed frame the current frame. */
1804       selected_frame_num = 0;
1805     } else {
1806       /* Find the nearest displayed frame to the selected frame (whether
1807          it's before or after that frame) and make that the current frame.
1808          If the next and previous displayed frames are equidistant from the
1809          selected frame, choose the next one. */
1810       g_assert(following_frame == NULL ||
1811                following_frame->num >= selected_frame->num);
1812       g_assert(preceding_frame == NULL ||
1813                preceding_frame->num <= selected_frame->num);
1814       if (following_frame == NULL) {
1815         /* No frame after the selected frame passed the filter, so we
1816            have to select the last displayed frame before the selected
1817            frame. */
1818         selected_frame_num = preceding_frame_num;
1819         selected_frame = preceding_frame;
1820       } else if (preceding_frame == NULL) {
1821         /* No frame before the selected frame passed the filter, so we
1822            have to select the first displayed frame after the selected
1823            frame. */
1824         selected_frame_num = following_frame_num;
1825         selected_frame = following_frame;
1826       } else {
1827         /* Frames before and after the selected frame passed the filter, so
1828            we'll select the previous frame */
1829         selected_frame_num = preceding_frame_num;
1830         selected_frame = preceding_frame;
1831       }
1832     }
1833   }
1834
1835   if (selected_frame_num == -1) {
1836     /* There are no frames displayed at all. */
1837     cf_unselect_packet(cf);
1838   } else {
1839     /* Either the frame that was selected passed the filter, or we've
1840        found the nearest displayed frame to that frame.  Select it, make
1841        it the focus row, and make it visible. */
1842     /* Set to invalid to force update of packet list and packet details */
1843     cf->current_row = -1;
1844     if (selected_frame_num == 0) {
1845       packet_list_select_first_row();
1846     }else{
1847       if (!packet_list_select_row_from_data(selected_frame)) {
1848         /* We didn't find a row corresponding to this frame.
1849            This means that the frame isn't being displayed currently,
1850            so we can't select it. */
1851         simple_message_box(ESD_TYPE_INFO, NULL,
1852                            "The capture file is probably not fully dissected.",
1853                            "End of capture exceeded.");
1854       }
1855     }
1856   }
1857
1858   /* Cleanup and release all dfilter resources */
1859   dfilter_free(dfcode);
1860 }
1861
1862
1863 /*
1864  * Scan through all frame data and recalculate the ref time
1865  * without rereading the file.
1866  * XXX - do we need a progres bar or is this fast enough?
1867  */
1868 static void
1869 ref_time_packets(capture_file *cf)
1870 {
1871   guint32     framenum;
1872   frame_data *fdata;
1873   nstime_t rel_ts;
1874
1875   cf->frame_set_info.ref = NULL;
1876   cf->frame_set_info.prev_dis = NULL;
1877   cf->cum_bytes = 0;
1878
1879   for (framenum = 1; framenum <= cf->count; framenum++) {
1880     fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
1881
1882     /* just add some value here until we know if it is being displayed or not */
1883     fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1884
1885     /*
1886      *Timestamps
1887      */
1888
1889     /* If we don't have the time stamp of the first packet in the
1890      capture, it's because this is the first packet.  Save the time
1891      stamp of this packet as the time stamp of the first packet. */
1892     if (cf->frame_set_info.ref == NULL)
1893         cf->frame_set_info.ref = fdata;
1894       /* if this frames is marked as a reference time frame, reset
1895         firstsec and firstusec to this frame */
1896     if (fdata->flags.ref_time)
1897         cf->frame_set_info.ref = fdata;
1898
1899     /* If we don't have the time stamp of the previous displayed packet,
1900      it's because this is the first displayed packet.  Save the time
1901      stamp of this packet as the time stamp of the previous displayed
1902      packet. */
1903     if (cf->frame_set_info.prev_dis == NULL) {
1904         cf->frame_set_info.prev_dis = fdata;
1905     }
1906
1907     /* Get the time elapsed between the first packet and this packet. */
1908     fdata->frame_ref_num = (fdata != cf->frame_set_info.ref) ? cf->frame_set_info.ref->num : 0;
1909     nstime_delta(&rel_ts, &fdata->abs_ts, &cf->frame_set_info.ref->abs_ts);
1910
1911     /* If it's greater than the current elapsed time, set the elapsed time
1912      to it (we check for "greater than" so as not to be confused by
1913      time moving backwards). */
1914     if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1915         || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1916         cf->elapsed_time = rel_ts;
1917     }
1918
1919     /* If this frame is displayed, get the time elapsed between the
1920      previous displayed packet and this packet. */
1921     if ( fdata->flags.passed_dfilter ) {
1922         fdata->prev_dis_num = cf->frame_set_info.prev_dis->num;
1923         cf->frame_set_info.prev_dis = fdata;
1924     }
1925
1926     /*
1927      * Byte counts
1928      */
1929     if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1930         /* This frame either passed the display filter list or is marked as
1931         a time reference frame.  All time reference frames are displayed
1932         even if they don't pass the display filter */
1933         if (fdata->flags.ref_time) {
1934             /* if this was a TIME REF frame we should reset the cum_bytes field */
1935             cf->cum_bytes = fdata->pkt_len;
1936             fdata->cum_bytes = cf->cum_bytes;
1937         } else {
1938             /* increase cum_bytes with this packets length */
1939             cf->cum_bytes += fdata->pkt_len;
1940         }
1941     }
1942   }
1943 }
1944
1945 typedef enum {
1946   PSP_FINISHED,
1947   PSP_STOPPED,
1948   PSP_FAILED
1949 } psp_return_t;
1950
1951 static psp_return_t
1952 process_specified_records(capture_file *cf, packet_range_t *range,
1953     const char *string1, const char *string2, gboolean terminate_is_stop,
1954     gboolean (*callback)(capture_file *, frame_data *,
1955                          struct wtap_pkthdr *, const guint8 *, void *),
1956     void *callback_args,
1957     gboolean show_progress_bar)
1958 {
1959   guint32          framenum;
1960   frame_data      *fdata;
1961   Buffer           buf;
1962   psp_return_t     ret     = PSP_FINISHED;
1963
1964   progdlg_t       *progbar = NULL;
1965   GTimer          *prog_timer = g_timer_new();
1966   int              progbar_count;
1967   float            progbar_val;
1968   GTimeVal         progbar_start_time;
1969   gchar            progbar_status_str[100];
1970   range_process_e  process_this;
1971   struct wtap_pkthdr phdr;
1972
1973   wtap_phdr_init(&phdr);
1974   ws_buffer_init(&buf, 1500);
1975
1976   g_timer_start(prog_timer);
1977   /* Count of packets at which we've looked. */
1978   progbar_count = 0;
1979   /* Progress so far. */
1980   progbar_val = 0.0f;
1981
1982   cf->stop_flag = FALSE;
1983   g_get_current_time(&progbar_start_time);
1984
1985   if (range != NULL)
1986     packet_range_process_init(range);
1987
1988   /* Iterate through all the packets, printing the packets that
1989      were selected by the current display filter.  */
1990   for (framenum = 1; framenum <= cf->count; framenum++) {
1991     fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
1992
1993     /* Create the progress bar if necessary.
1994        We check on every iteration of the loop, so that it takes no
1995        longer than the standard time to create it (otherwise, for a
1996        large file, we might take considerably longer than that standard
1997        time in order to get to the next progress bar step). */
1998     if (show_progress_bar && progbar == NULL)
1999       progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2000                                             terminate_is_stop,
2001                                             &cf->stop_flag,
2002                                             &progbar_start_time,
2003                                             progbar_val);
2004
2005     /*
2006      * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
2007      * has elapsed. Calling update_progress_dlg and packets_bar_update will
2008      * likely trigger UI paint events, which might take a while depending on
2009      * the platform and display. Reset our timer *after* painting.
2010      */
2011     if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
2012       /* let's not divide by zero. I should never be started
2013        * with count == 0, so let's assert that
2014        */
2015       g_assert(cf->count > 0);
2016       progbar_val = (gfloat) progbar_count / cf->count;
2017
2018       g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2019                   "%4u of %u packets", progbar_count, cf->count);
2020       update_progress_dlg(progbar, progbar_val, progbar_status_str);
2021
2022       g_timer_start(prog_timer);
2023     }
2024
2025     if (cf->stop_flag) {
2026       /* Well, the user decided to abort the operation.  Just stop,
2027          and arrange to return PSP_STOPPED to our caller, so they know
2028          it was stopped explicitly. */
2029       ret = PSP_STOPPED;
2030       break;
2031     }
2032
2033     progbar_count++;
2034
2035     if (range != NULL) {
2036       /* do we have to process this packet? */
2037       process_this = packet_range_process_packet(range, fdata);
2038       if (process_this == range_process_next) {
2039         /* this packet uninteresting, continue with next one */
2040         continue;
2041       } else if (process_this == range_processing_finished) {
2042         /* all interesting packets processed, stop the loop */
2043         break;
2044       }
2045     }
2046
2047     /* Get the packet */
2048     if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2049       /* Attempt to get the packet failed. */
2050       ret = PSP_FAILED;
2051       break;
2052     }
2053     /* Process the packet */
2054     if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
2055       /* Callback failed.  We assume it reported the error appropriately. */
2056       ret = PSP_FAILED;
2057       break;
2058     }
2059   }
2060
2061   /* We're done printing the packets; destroy the progress bar if
2062      it was created. */
2063   if (progbar != NULL)
2064     destroy_progress_dlg(progbar);
2065   g_timer_destroy(prog_timer);
2066
2067   wtap_phdr_cleanup(&phdr);
2068   ws_buffer_free(&buf);
2069
2070   return ret;
2071 }
2072
2073 typedef struct {
2074   epan_dissect_t edt;
2075   column_info *cinfo;
2076 } retap_callback_args_t;
2077
2078 static gboolean
2079 retap_packet(capture_file *cf, frame_data *fdata,
2080              struct wtap_pkthdr *phdr, const guint8 *pd,
2081              void *argsp)
2082 {
2083   retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2084
2085   epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2086   epan_dissect_reset(&args->edt);
2087
2088   return TRUE;
2089 }
2090
2091 cf_read_status_t
2092 cf_retap_packets(capture_file *cf)
2093 {
2094   packet_range_t        range;
2095   retap_callback_args_t callback_args;
2096   gboolean              create_proto_tree;
2097   guint                 tap_flags;
2098   psp_return_t          ret;
2099
2100   /* Presumably the user closed the capture file. */
2101   if (cf == NULL) {
2102     return CF_READ_ABORTED;
2103   }
2104
2105   cf_callback_invoke(cf_cb_file_retap_started, cf);
2106
2107   /* Get the union of the flags for all tap listeners. */
2108   tap_flags = union_of_tap_listener_flags();
2109
2110   /* If any tap listeners require the columns, construct them. */
2111   callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2112
2113   /*
2114    * Determine whether we need to create a protocol tree.
2115    * We do if:
2116    *
2117    *    one of the tap listeners is going to apply a filter;
2118    *
2119    *    one of the tap listeners requires a protocol tree.
2120    */
2121   create_proto_tree =
2122     (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
2123
2124   /* Reset the tap listeners. */
2125   reset_tap_listeners();
2126
2127   epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
2128
2129   /* Iterate through the list of packets, dissecting all packets and
2130      re-running the taps. */
2131   packet_range_init(&range, cf);
2132   packet_range_process_init(&range);
2133
2134   ret = process_specified_records(cf, &range, "Recalculating statistics on",
2135                                   "all packets", TRUE, retap_packet,
2136                                   &callback_args, TRUE);
2137
2138   epan_dissect_cleanup(&callback_args.edt);
2139
2140   cf_callback_invoke(cf_cb_file_retap_finished, cf);
2141
2142   switch (ret) {
2143   case PSP_FINISHED:
2144     /* Completed successfully. */
2145     return CF_READ_OK;
2146
2147   case PSP_STOPPED:
2148     /* Well, the user decided to abort the refiltering.
2149        Return CF_READ_ABORTED so our caller knows they did that. */
2150     return CF_READ_ABORTED;
2151
2152   case PSP_FAILED:
2153     /* Error while retapping. */
2154     return CF_READ_ERROR;
2155   }
2156
2157   g_assert_not_reached();
2158   return CF_READ_OK;
2159 }
2160
2161 typedef struct {
2162   print_args_t *print_args;
2163   gboolean      print_header_line;
2164   char         *header_line_buf;
2165   int           header_line_buf_len;
2166   gboolean      print_formfeed;
2167   gboolean      print_separator;
2168   char         *line_buf;
2169   int           line_buf_len;
2170   gint         *col_widths;
2171   int           num_visible_cols;
2172   gint         *visible_cols;
2173   epan_dissect_t edt;
2174 } print_callback_args_t;
2175
2176 static gboolean
2177 print_packet(capture_file *cf, frame_data *fdata,
2178              struct wtap_pkthdr *phdr, const guint8 *pd,
2179              void *argsp)
2180 {
2181   print_callback_args_t *args = (print_callback_args_t *)argsp;
2182   int             i;
2183   char           *cp;
2184   int             line_len;
2185   int             column_len;
2186   int             cp_off;
2187   char            bookmark_name[9+10+1];  /* "__frameNNNNNNNNNN__\0" */
2188   char            bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0"  */
2189   col_item_t*     col_item;
2190
2191   /* Fill in the column information if we're printing the summary
2192      information. */
2193   if (args->print_args->print_summary) {
2194     col_custom_prime_edt(&args->edt, &cf->cinfo);
2195     epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2196     epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2197   } else
2198     epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2199
2200   if (args->print_formfeed) {
2201     if (!new_page(args->print_args->stream))
2202       goto fail;
2203   } else {
2204       if (args->print_separator) {
2205         if (!print_line(args->print_args->stream, 0, ""))
2206           goto fail;
2207       }
2208   }
2209
2210   /*
2211    * We generate bookmarks, if the output format supports them.
2212    * The name is "__frameN__".
2213    */
2214   g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2215
2216   if (args->print_args->print_summary) {
2217     if (!args->print_args->print_col_headings)
2218         args->print_header_line = FALSE;
2219     if (args->print_header_line) {
2220       if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2221         goto fail;
2222       args->print_header_line = FALSE;  /* we might not need to print any more */
2223     }
2224     cp = &args->line_buf[0];
2225     line_len = 0;
2226     for (i = 0; i < args->num_visible_cols; i++) {
2227       col_item = &cf->cinfo.columns[args->visible_cols[i]];
2228       /* Find the length of the string for this column. */
2229       column_len = (int) strlen(col_item->col_data);
2230       if (args->col_widths[i] > column_len)
2231          column_len = args->col_widths[i];
2232
2233       /* Make sure there's room in the line buffer for the column; if not,
2234          double its length. */
2235       line_len += column_len + 1;   /* "+1" for space */
2236       if (line_len > args->line_buf_len) {
2237         cp_off = (int) (cp - args->line_buf);
2238         args->line_buf_len = 2 * line_len;
2239         args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2240         cp = args->line_buf + cp_off;
2241       }
2242
2243       /* Right-justify the packet number column. */
2244       if (col_item->col_fmt == COL_NUMBER)
2245         g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2246       else
2247         g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2248       cp += column_len;
2249       if (i != args->num_visible_cols - 1)
2250         *cp++ = ' ';
2251     }
2252     *cp = '\0';
2253
2254     /*
2255      * Generate a bookmark, using the summary line as the title.
2256      */
2257     if (!print_bookmark(args->print_args->stream, bookmark_name,
2258                         args->line_buf))
2259       goto fail;
2260
2261     if (!print_line(args->print_args->stream, 0, args->line_buf))
2262       goto fail;
2263   } else {
2264     /*
2265      * Generate a bookmark, using "Frame N" as the title, as we're not
2266      * printing the summary line.
2267      */
2268     g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2269     if (!print_bookmark(args->print_args->stream, bookmark_name,
2270                         bookmark_title))
2271       goto fail;
2272   } /* if (print_summary) */
2273
2274   if (args->print_args->print_dissections != print_dissections_none) {
2275     if (args->print_args->print_summary) {
2276       /* Separate the summary line from the tree with a blank line. */
2277       if (!print_line(args->print_args->stream, 0, ""))
2278         goto fail;
2279     }
2280
2281     /* Print the information in that tree. */
2282     if (!proto_tree_print(args->print_args->print_dissections,
2283                           args->print_args->print_hex, &args->edt, NULL,
2284                           args->print_args->stream))
2285       goto fail;
2286
2287     /* Print a blank line if we print anything after this (aka more than one packet). */
2288     args->print_separator = TRUE;
2289
2290     /* Print a header line if we print any more packet summaries */
2291     if (args->print_args->print_col_headings)
2292         args->print_header_line = TRUE;
2293   }
2294
2295   if (args->print_args->print_hex) {
2296     if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2297       if (!print_line(args->print_args->stream, 0, ""))
2298         goto fail;
2299     }
2300     /* Print the full packet data as hex. */
2301     if (!print_hex_data(args->print_args->stream, &args->edt))
2302       goto fail;
2303
2304     /* Print a blank line if we print anything after this (aka more than one packet). */
2305     args->print_separator = TRUE;
2306
2307     /* Print a header line if we print any more packet summaries */
2308     if (args->print_args->print_col_headings)
2309         args->print_header_line = TRUE;
2310   } /* if (args->print_args->print_dissections != print_dissections_none) */
2311
2312   epan_dissect_reset(&args->edt);
2313
2314   /* do we want to have a formfeed between each packet from now on? */
2315   if (args->print_args->print_formfeed) {
2316     args->print_formfeed = TRUE;
2317   }
2318
2319   return TRUE;
2320
2321 fail:
2322   epan_dissect_reset(&args->edt);
2323   return FALSE;
2324 }
2325
2326 cf_print_status_t
2327 cf_print_packets(capture_file *cf, print_args_t *print_args,
2328                  gboolean show_progress_bar)
2329 {
2330   print_callback_args_t callback_args;
2331   gint          data_width;
2332   char         *cp;
2333   int           i, cp_off, column_len, line_len;
2334   int           num_visible_col = 0, last_visible_col = 0, visible_col_count;
2335   psp_return_t  ret;
2336   GList        *clp;
2337   fmt_data     *cfmt;
2338   gboolean      proto_tree_needed;
2339
2340   callback_args.print_args = print_args;
2341   callback_args.print_header_line = print_args->print_col_headings;
2342   callback_args.header_line_buf = NULL;
2343   callback_args.header_line_buf_len = 256;
2344   callback_args.print_formfeed = FALSE;
2345   callback_args.print_separator = FALSE;
2346   callback_args.line_buf = NULL;
2347   callback_args.line_buf_len = 256;
2348   callback_args.col_widths = NULL;
2349   callback_args.num_visible_cols = 0;
2350   callback_args.visible_cols = NULL;
2351
2352   if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2353     destroy_print_stream(print_args->stream);
2354     return CF_PRINT_WRITE_ERROR;
2355   }
2356
2357   if (print_args->print_summary) {
2358     /* We're printing packet summaries.  Allocate the header line buffer
2359        and get the column widths. */
2360     callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2361
2362     /* Find the number of visible columns and the last visible column */
2363     for (i = 0; i < prefs.num_cols; i++) {
2364
2365         clp = g_list_nth(prefs.col_list, i);
2366         if (clp == NULL) /* Sanity check, Invalid column requested */
2367             continue;
2368
2369         cfmt = (fmt_data *) clp->data;
2370         if (cfmt->visible) {
2371             num_visible_col++;
2372             last_visible_col = i;
2373         }
2374     }
2375
2376     /* Find the widths for each of the columns - maximum of the
2377        width of the title and the width of the data - and construct
2378        a buffer with a line containing the column titles. */
2379     callback_args.num_visible_cols = num_visible_col;
2380     callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2381     callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2382     cp = &callback_args.header_line_buf[0];
2383     line_len = 0;
2384     visible_col_count = 0;
2385     for (i = 0; i < cf->cinfo.num_cols; i++) {
2386
2387       clp = g_list_nth(prefs.col_list, i);
2388       if (clp == NULL) /* Sanity check, Invalid column requested */
2389           continue;
2390
2391       cfmt = (fmt_data *) clp->data;
2392       if (cfmt->visible == FALSE)
2393           continue;
2394
2395       /* Save the order of visible columns */
2396       callback_args.visible_cols[visible_col_count] = i;
2397
2398       /* Don't pad the last column. */
2399       if (i == last_visible_col)
2400         callback_args.col_widths[visible_col_count] = 0;
2401       else {
2402         callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2403         data_width = get_column_char_width(get_column_format(i));
2404         if (data_width > callback_args.col_widths[visible_col_count])
2405           callback_args.col_widths[visible_col_count] = data_width;
2406       }
2407
2408       /* Find the length of the string for this column. */
2409       column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2410       if (callback_args.col_widths[i] > column_len)
2411         column_len = callback_args.col_widths[visible_col_count];
2412
2413       /* Make sure there's room in the line buffer for the column; if not,
2414          double its length. */
2415       line_len += column_len + 1;   /* "+1" for space */
2416       if (line_len > callback_args.header_line_buf_len) {
2417         cp_off = (int) (cp - callback_args.header_line_buf);
2418         callback_args.header_line_buf_len = 2 * line_len;
2419         callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2420                                                   callback_args.header_line_buf_len + 1);
2421         cp = callback_args.header_line_buf + cp_off;
2422       }
2423
2424       /* Right-justify the packet number column. */
2425 /*      if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2426         g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2427       else*/
2428       g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2429       cp += column_len;
2430       if (i != cf->cinfo.num_cols - 1)
2431         *cp++ = ' ';
2432
2433       visible_col_count++;
2434     }
2435     *cp = '\0';
2436
2437     /* Now start out the main line buffer with the same length as the
2438        header line buffer. */
2439     callback_args.line_buf_len = callback_args.header_line_buf_len;
2440     callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2441   } /* if (print_summary) */
2442
2443   /* Create the protocol tree, and make it visible, if we're printing
2444      the dissection or the hex data.
2445      XXX - do we need it if we're just printing the hex data? */
2446   proto_tree_needed =
2447       callback_args.print_args->print_dissections != print_dissections_none ||
2448       callback_args.print_args->print_hex ||
2449       have_custom_cols(&cf->cinfo) || have_field_extractors();
2450   epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2451
2452   /* Iterate through the list of packets, printing the packets we were
2453      told to print. */
2454   ret = process_specified_records(cf, &print_args->range, "Printing",
2455                                   "selected packets", TRUE, print_packet,
2456                                   &callback_args, show_progress_bar);
2457   epan_dissect_cleanup(&callback_args.edt);
2458   g_free(callback_args.header_line_buf);
2459   g_free(callback_args.line_buf);
2460   g_free(callback_args.col_widths);
2461   g_free(callback_args.visible_cols);
2462
2463   switch (ret) {
2464
2465   case PSP_FINISHED:
2466     /* Completed successfully. */
2467     break;
2468
2469   case PSP_STOPPED:
2470     /* Well, the user decided to abort the printing.
2471
2472        XXX - note that what got generated before they did that
2473        will get printed if we're piping to a print program; we'd
2474        have to write to a file and then hand that to the print
2475        program to make it actually not print anything. */
2476     break;
2477
2478   case PSP_FAILED:
2479     /* Error while printing.
2480
2481        XXX - note that what got generated before they did that
2482        will get printed if we're piping to a print program; we'd
2483        have to write to a file and then hand that to the print
2484        program to make it actually not print anything. */
2485     destroy_print_stream(print_args->stream);
2486     return CF_PRINT_WRITE_ERROR;
2487   }
2488
2489   if (!print_finale(print_args->stream)) {
2490     destroy_print_stream(print_args->stream);
2491     return CF_PRINT_WRITE_ERROR;
2492   }
2493
2494   if (!destroy_print_stream(print_args->stream))
2495     return CF_PRINT_WRITE_ERROR;
2496
2497   return CF_PRINT_OK;
2498 }
2499
2500 typedef struct {
2501   FILE *fh;
2502   epan_dissect_t edt;
2503   print_args_t *print_args;
2504 } write_packet_callback_args_t;
2505
2506 static gboolean
2507 write_pdml_packet(capture_file *cf, frame_data *fdata,
2508                   struct wtap_pkthdr *phdr, const guint8 *pd,
2509           void *argsp)
2510 {
2511   write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2512
2513   /* Create the protocol tree, but don't fill in the column information. */
2514   epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2515
2516   /* Write out the information in that tree. */
2517   write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, args->fh, FALSE);
2518
2519   epan_dissect_reset(&args->edt);
2520
2521   return !ferror(args->fh);
2522 }
2523
2524 cf_print_status_t
2525 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2526 {
2527   write_packet_callback_args_t callback_args;
2528   FILE         *fh;
2529   psp_return_t  ret;
2530
2531   fh = ws_fopen(print_args->file, "w");
2532   if (fh == NULL)
2533     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2534
2535   write_pdml_preamble(fh, cf->filename);
2536   if (ferror(fh)) {
2537     fclose(fh);
2538     return CF_PRINT_WRITE_ERROR;
2539   }
2540
2541   callback_args.fh = fh;
2542   callback_args.print_args = print_args;
2543   epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2544
2545   /* Iterate through the list of packets, printing the packets we were
2546      told to print. */
2547   ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2548                                   "selected packets", TRUE,
2549                                   write_pdml_packet, &callback_args, TRUE);
2550
2551   epan_dissect_cleanup(&callback_args.edt);
2552
2553   switch (ret) {
2554
2555   case PSP_FINISHED:
2556     /* Completed successfully. */
2557     break;
2558
2559   case PSP_STOPPED:
2560     /* Well, the user decided to abort the printing. */
2561     break;
2562
2563   case PSP_FAILED:
2564     /* Error while printing. */
2565     fclose(fh);
2566     return CF_PRINT_WRITE_ERROR;
2567   }
2568
2569   write_pdml_finale(fh);
2570   if (ferror(fh)) {
2571     fclose(fh);
2572     return CF_PRINT_WRITE_ERROR;
2573   }
2574
2575   /* XXX - check for an error */
2576   fclose(fh);
2577
2578   return CF_PRINT_OK;
2579 }
2580
2581 static gboolean
2582 write_psml_packet(capture_file *cf, frame_data *fdata,
2583                   struct wtap_pkthdr *phdr, const guint8 *pd,
2584           void *argsp)
2585 {
2586   write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2587
2588   /* Fill in the column information */
2589   col_custom_prime_edt(&args->edt, &cf->cinfo);
2590   epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2591   epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2592
2593   /* Write out the column information. */
2594   write_psml_columns(&args->edt, args->fh, FALSE);
2595
2596   epan_dissect_reset(&args->edt);
2597
2598   return !ferror(args->fh);
2599 }
2600
2601 cf_print_status_t
2602 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2603 {
2604   write_packet_callback_args_t callback_args;
2605   FILE         *fh;
2606   psp_return_t  ret;
2607
2608   gboolean proto_tree_needed;
2609
2610   fh = ws_fopen(print_args->file, "w");
2611   if (fh == NULL)
2612     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2613
2614   write_psml_preamble(&cf->cinfo, fh);
2615   if (ferror(fh)) {
2616     fclose(fh);
2617     return CF_PRINT_WRITE_ERROR;
2618   }
2619
2620   callback_args.fh = fh;
2621   callback_args.print_args = print_args;
2622
2623   /* Fill in the column information, only create the protocol tree
2624      if having custom columns or field extractors. */
2625   proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2626   epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2627
2628   /* Iterate through the list of packets, printing the packets we were
2629      told to print. */
2630   ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2631                                   "selected packets", TRUE,
2632                                   write_psml_packet, &callback_args, TRUE);
2633
2634   epan_dissect_cleanup(&callback_args.edt);
2635
2636   switch (ret) {
2637
2638   case PSP_FINISHED:
2639     /* Completed successfully. */
2640     break;
2641
2642   case PSP_STOPPED:
2643     /* Well, the user decided to abort the printing. */
2644     break;
2645
2646   case PSP_FAILED:
2647     /* Error while printing. */
2648     fclose(fh);
2649     return CF_PRINT_WRITE_ERROR;
2650   }
2651
2652   write_psml_finale(fh);
2653   if (ferror(fh)) {
2654     fclose(fh);
2655     return CF_PRINT_WRITE_ERROR;
2656   }
2657
2658   /* XXX - check for an error */
2659   fclose(fh);
2660
2661   return CF_PRINT_OK;
2662 }
2663
2664 static gboolean
2665 write_csv_packet(capture_file *cf, frame_data *fdata,
2666                  struct wtap_pkthdr *phdr, const guint8 *pd,
2667                  void *argsp)
2668 {
2669   write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2670
2671   /* Fill in the column information */
2672   col_custom_prime_edt(&args->edt, &cf->cinfo);
2673   epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2674   epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2675
2676   /* Write out the column information. */
2677   write_csv_columns(&args->edt, args->fh);
2678
2679   epan_dissect_reset(&args->edt);
2680
2681   return !ferror(args->fh);
2682 }
2683
2684 cf_print_status_t
2685 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2686 {
2687   write_packet_callback_args_t callback_args;
2688   gboolean        proto_tree_needed;
2689   FILE         *fh;
2690   psp_return_t  ret;
2691
2692   fh = ws_fopen(print_args->file, "w");
2693   if (fh == NULL)
2694     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2695
2696   write_csv_column_titles(&cf->cinfo, fh);
2697   if (ferror(fh)) {
2698     fclose(fh);
2699     return CF_PRINT_WRITE_ERROR;
2700   }
2701
2702   callback_args.fh = fh;
2703   callback_args.print_args = print_args;
2704
2705   /* only create the protocol tree if having custom columns or field extractors. */
2706   proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2707   epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2708
2709   /* Iterate through the list of packets, printing the packets we were
2710      told to print. */
2711   ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2712                                   "selected packets", TRUE,
2713                                   write_csv_packet, &callback_args, TRUE);
2714
2715   epan_dissect_cleanup(&callback_args.edt);
2716
2717   switch (ret) {
2718
2719   case PSP_FINISHED:
2720     /* Completed successfully. */
2721     break;
2722
2723   case PSP_STOPPED:
2724     /* Well, the user decided to abort the printing. */
2725     break;
2726
2727   case PSP_FAILED:
2728     /* Error while printing. */
2729     fclose(fh);
2730     return CF_PRINT_WRITE_ERROR;
2731   }
2732
2733   /* XXX - check for an error */
2734   fclose(fh);
2735
2736   return CF_PRINT_OK;
2737 }
2738
2739 static gboolean
2740 carrays_write_packet(capture_file *cf, frame_data *fdata,
2741              struct wtap_pkthdr *phdr,
2742              const guint8 *pd, void *argsp)
2743 {
2744   write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2745
2746   epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2747   write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2748   epan_dissect_reset(&args->edt);
2749
2750   return !ferror(args->fh);
2751 }
2752
2753 cf_print_status_t
2754 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2755 {
2756   write_packet_callback_args_t callback_args;
2757   FILE         *fh;
2758   psp_return_t  ret;
2759
2760   fh = ws_fopen(print_args->file, "w");
2761
2762   if (fh == NULL)
2763     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2764
2765   if (ferror(fh)) {
2766     fclose(fh);
2767     return CF_PRINT_WRITE_ERROR;
2768   }
2769
2770   callback_args.fh = fh;
2771   callback_args.print_args = print_args;
2772   epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2773
2774   /* Iterate through the list of packets, printing the packets we were
2775      told to print. */
2776   ret = process_specified_records(cf, &print_args->range,
2777                                   "Writing C Arrays",
2778                                   "selected packets", TRUE,
2779                                   carrays_write_packet, &callback_args, TRUE);
2780
2781   epan_dissect_cleanup(&callback_args.edt);
2782
2783   switch (ret) {
2784   case PSP_FINISHED:
2785     /* Completed successfully. */
2786     break;
2787   case PSP_STOPPED:
2788     /* Well, the user decided to abort the printing. */
2789     break;
2790   case PSP_FAILED:
2791     /* Error while printing. */
2792     fclose(fh);
2793     return CF_PRINT_WRITE_ERROR;
2794   }
2795
2796   fclose(fh);
2797   return CF_PRINT_OK;
2798 }
2799
2800 static gboolean
2801 write_json_packet(capture_file *cf, frame_data *fdata,
2802                   struct wtap_pkthdr *phdr, const guint8 *pd,
2803           void *argsp)
2804 {
2805   write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2806
2807   /* Create the protocol tree, but don't fill in the column information. */
2808   epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2809
2810   /* Write out the information in that tree. */
2811   write_json_proto_tree(NULL, args->print_args->print_dissections,
2812                         args->print_args->print_hex, NULL, PF_NONE,
2813                         &args->edt, proto_node_group_children_by_unique, args->fh);
2814
2815   epan_dissect_reset(&args->edt);
2816
2817   return !ferror(args->fh);
2818 }
2819
2820 cf_print_status_t
2821 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2822 {
2823   write_packet_callback_args_t callback_args;
2824   FILE         *fh;
2825   psp_return_t  ret;
2826
2827   fh = ws_fopen(print_args->file, "w");
2828   if (fh == NULL)
2829     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2830
2831   write_json_preamble(fh);
2832   if (ferror(fh)) {
2833     fclose(fh);
2834     return CF_PRINT_WRITE_ERROR;
2835   }
2836
2837   callback_args.fh = fh;
2838   callback_args.print_args = print_args;
2839   epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2840
2841   /* Iterate through the list of packets, printing the packets we were
2842      told to print. */
2843   ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2844                                   "selected packets", TRUE,
2845                                   write_json_packet, &callback_args, TRUE);
2846
2847   epan_dissect_cleanup(&callback_args.edt);
2848
2849   switch (ret) {
2850
2851   case PSP_FINISHED:
2852     /* Completed successfully. */
2853     break;
2854
2855   case PSP_STOPPED:
2856     /* Well, the user decided to abort the printing. */
2857     break;
2858
2859   case PSP_FAILED:
2860     /* Error while printing. */
2861     fclose(fh);
2862     return CF_PRINT_WRITE_ERROR;
2863   }
2864
2865   write_json_finale(fh);
2866   if (ferror(fh)) {
2867     fclose(fh);
2868     return CF_PRINT_WRITE_ERROR;
2869   }
2870
2871   /* XXX - check for an error */
2872   fclose(fh);
2873
2874   return CF_PRINT_OK;
2875 }
2876
2877 gboolean
2878 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2879                              search_direction dir)
2880 {
2881   match_data mdata;
2882
2883   mdata.string = string;
2884   mdata.string_len = strlen(string);
2885   return find_packet(cf, match_protocol_tree, &mdata, dir);
2886 }
2887
2888 gboolean
2889 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree,  match_data *mdata)
2890 {
2891   mdata->frame_matched = FALSE;
2892   mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2893   mdata->string_len = strlen(mdata->string);
2894   mdata->cf = cf;
2895   /* Iterate through all the nodes looking for matching text */
2896   proto_tree_children_foreach(tree, match_subtree_text, mdata);
2897   return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2898 }
2899
2900 static match_result
2901 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2902 {
2903   match_data     *mdata = (match_data *)criterion;
2904   epan_dissect_t  edt;
2905
2906   /* Load the frame's data. */
2907   if (!cf_read_record(cf, fdata)) {
2908     /* Attempt to get the packet failed. */
2909     return MR_ERROR;
2910   }
2911
2912   /* Construct the protocol tree, including the displayed text */
2913   epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
2914   /* We don't need the column information */
2915   epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
2916
2917   /* Iterate through all the nodes, seeing if they have text that matches. */
2918   mdata->cf = cf;
2919   mdata->frame_matched = FALSE;
2920   proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2921   epan_dissect_cleanup(&edt);
2922   return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2923 }
2924
2925 static void
2926 match_subtree_text(proto_node *node, gpointer data)
2927 {
2928   match_data   *mdata      = (match_data *) data;
2929   const gchar  *string     = mdata->string;
2930   size_t        string_len = mdata->string_len;
2931   capture_file *cf         = mdata->cf;
2932   field_info   *fi         = PNODE_FINFO(node);
2933   gchar         label_str[ITEM_LABEL_LENGTH];
2934   gchar        *label_ptr;
2935   size_t        label_len;
2936   guint32       i;
2937   guint8        c_char;
2938   size_t        c_match    = 0;
2939
2940   /* dissection with an invisible proto tree? */
2941   g_assert(fi);
2942
2943   if (mdata->frame_matched) {
2944     /* We already had a match; don't bother doing any more work. */
2945     return;
2946   }
2947
2948   /* Don't match invisible entries. */
2949   if (PROTO_ITEM_IS_HIDDEN(node))
2950     return;
2951
2952   /* was a free format label produced? */
2953   if (fi->rep) {
2954     label_ptr = fi->rep->representation;
2955   } else {
2956     /* no, make a generic label */
2957     label_ptr = label_str;
2958     proto_item_fill_label(fi, label_str);
2959   }
2960
2961   if (cf->regex) {
2962     if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) {
2963       mdata->frame_matched = TRUE;
2964       mdata->finfo = fi;
2965       return;
2966     }
2967   } else {
2968     /* Does that label match? */
2969     label_len = strlen(label_ptr);
2970     for (i = 0; i < label_len; i++) {
2971       c_char = label_ptr[i];
2972       if (cf->case_type)
2973         c_char = g_ascii_toupper(c_char);
2974       if (c_char == string[c_match]) {
2975         c_match++;
2976         if (c_match == string_len) {
2977           /* No need to look further; we have a match */
2978           mdata->frame_matched = TRUE;
2979           mdata->finfo = fi;
2980           return;
2981         }
2982       } else
2983         c_match = 0;
2984     }
2985   }
2986
2987   /* Recurse into the subtree, if it exists */
2988   if (node->first_child != NULL)
2989     proto_tree_children_foreach(node, match_subtree_text, mdata);
2990 }
2991
2992 gboolean
2993 cf_find_packet_summary_line(capture_file *cf, const char *string,
2994                             search_direction dir)
2995 {
2996   match_data mdata;
2997
2998   mdata.string = string;
2999   mdata.string_len = strlen(string);
3000   return find_packet(cf, match_summary_line, &mdata, dir);
3001 }
3002
3003 static match_result
3004 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3005 {
3006   match_data     *mdata      = (match_data *)criterion;
3007   const gchar    *string     = mdata->string;
3008   size_t          string_len = mdata->string_len;
3009   epan_dissect_t  edt;
3010   const char     *info_column;
3011   size_t          info_column_len;
3012   match_result    result     = MR_NOTMATCHED;
3013   gint            colx;
3014   guint32         i;
3015   guint8          c_char;
3016   size_t          c_match    = 0;
3017
3018   /* Load the frame's data. */
3019   if (!cf_read_record(cf, fdata)) {
3020     /* Attempt to get the packet failed. */
3021     return MR_ERROR;
3022   }
3023
3024   /* Don't bother constructing the protocol tree */
3025   epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3026   /* Get the column information */
3027   epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
3028                    &cf->cinfo);
3029
3030   /* Find the Info column */
3031   for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3032     if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3033       /* Found it.  See if we match. */
3034       info_column = edt.pi.cinfo->columns[colx].col_data;
3035       info_column_len = strlen(info_column);
3036       if (cf->regex) {
3037         if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3038           result = MR_MATCHED;
3039           break;
3040         }
3041       } else {
3042         for (i = 0; i < info_column_len; i++) {
3043           c_char = info_column[i];
3044           if (cf->case_type)
3045             c_char = g_ascii_toupper(c_char);
3046           if (c_char == string[c_match]) {
3047             c_match++;
3048             if (c_match == string_len) {
3049               result = MR_MATCHED;
3050               break;
3051             }
3052           } else
3053             c_match = 0;
3054         }
3055       }
3056       break;
3057     }
3058   }
3059   epan_dissect_cleanup(&edt);
3060   return result;
3061 }
3062
3063 typedef struct {
3064     const guint8 *data;
3065     size_t        data_len;
3066 } cbs_t;    /* "Counted byte string" */
3067
3068
3069 /*
3070  * The current match_* routines only support ASCII case insensitivity and don't
3071  * convert UTF-8 inputs to UTF-16 for matching.
3072  *
3073  * We could modify them to use the GLib Unicode routines or the International
3074  * Components for Unicode library but it's not apparent that we could do so
3075  * without consuming a lot more CPU and memory or that searching would be
3076  * significantly better.
3077  */
3078
3079 gboolean
3080 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3081                     search_direction dir)
3082 {
3083   cbs_t info;
3084
3085   info.data = string;
3086   info.data_len = string_size;
3087
3088   /* Regex, String or hex search? */
3089   if (cf->regex) {
3090     /* Regular Expression search */
3091     return find_packet(cf, match_regex, NULL, dir);
3092   } else if (cf->string) {
3093     /* String search - what type of string? */
3094     switch (cf->scs_type) {
3095
3096     case SCS_NARROW_AND_WIDE:
3097       return find_packet(cf, match_narrow_and_wide, &info, dir);
3098
3099     case SCS_NARROW:
3100       return find_packet(cf, match_narrow, &info, dir);
3101
3102     case SCS_WIDE:
3103       return find_packet(cf, match_wide, &info, dir);
3104
3105     default:
3106       g_assert_not_reached();
3107       return FALSE;
3108     }
3109   } else
3110     return find_packet(cf, match_binary, &info, dir);
3111 }
3112
3113 static match_result
3114 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3115 {
3116   cbs_t        *info       = (cbs_t *)criterion;
3117   const guint8 *ascii_text = info->data;
3118   size_t        textlen    = info->data_len;
3119   match_result  result;
3120   guint32       buf_len;
3121   guint8       *pd;
3122   guint32       i;
3123   guint8        c_char;
3124   size_t        c_match    = 0;
3125
3126   /* Load the frame's data. */
3127   if (!cf_read_record(cf, fdata)) {
3128     /* Attempt to get the packet failed. */
3129     return MR_ERROR;
3130   }
3131
3132   result = MR_NOTMATCHED;
3133   buf_len = fdata->cap_len;
3134   pd = ws_buffer_start_ptr(&cf->buf);
3135   i = 0;
3136   while (i < buf_len) {
3137     c_char = pd[i];
3138     if (cf->case_type)
3139       c_char = g_ascii_toupper(c_char);
3140     if (c_char != '\0') {
3141       if (c_char == ascii_text[c_match]) {
3142         c_match += 1;
3143         if (c_match == textlen) {
3144           result = MR_MATCHED;
3145           cf->search_pos = i; /* Save the position of the last character
3146                                  for highlighting the field. */
3147           cf->search_len = (guint32)textlen;
3148           break;
3149         }
3150       }
3151       else {
3152         g_assert(i>=c_match);
3153         i -= (guint32)c_match;
3154         c_match = 0;
3155       }
3156     }
3157     i += 1;
3158   }
3159   return result;
3160 }
3161
3162 static match_result
3163 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3164 {
3165   guint8       *pd;
3166   cbs_t        *info       = (cbs_t *)criterion;
3167   const guint8 *ascii_text = info->data;
3168   size_t        textlen    = info->data_len;
3169   match_result  result;
3170   guint32       buf_len;
3171   guint32       i;
3172   guint8        c_char;
3173   size_t        c_match    = 0;
3174
3175   /* Load the frame's data. */
3176   if (!cf_read_record(cf, fdata)) {
3177     /* Attempt to get the packet failed. */
3178     return MR_ERROR;
3179   }
3180
3181   result = MR_NOTMATCHED;
3182   buf_len = fdata->cap_len;
3183   pd = ws_buffer_start_ptr(&cf->buf);
3184   i = 0;
3185   while (i < buf_len) {
3186     c_char = pd[i];
3187     if (cf->case_type)
3188       c_char = g_ascii_toupper(c_char);
3189     if (c_char == ascii_text[c_match]) {
3190       c_match += 1;
3191       if (c_match == textlen) {
3192         result = MR_MATCHED;
3193         cf->search_pos = i; /* Save the position of the last character
3194                                for highlighting the field. */
3195         cf->search_len = (guint32)textlen;
3196         break;
3197       }
3198     }
3199     else {
3200       g_assert(i>=c_match);
3201       i -= (guint32)c_match;
3202       c_match = 0;
3203     }
3204     i += 1;
3205   }
3206
3207   return result;
3208 }
3209
3210 static match_result
3211 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3212 {
3213   cbs_t        *info       = (cbs_t *)criterion;
3214   const guint8 *ascii_text = info->data;
3215   size_t        textlen    = info->data_len;
3216   match_result  result;
3217   guint32       buf_len;
3218   guint8       *pd;
3219   guint32       i;
3220   guint8        c_char;
3221   size_t        c_match    = 0;
3222
3223   /* Load the frame's data. */
3224   if (!cf_read_record(cf, fdata)) {
3225     /* Attempt to get the packet failed. */
3226     return MR_ERROR;
3227   }
3228
3229   result = MR_NOTMATCHED;
3230   buf_len = fdata->cap_len;
3231   pd = ws_buffer_start_ptr(&cf->buf);
3232   i = 0;
3233   while (i < buf_len) {
3234     c_char = pd[i];
3235     if (cf->case_type)
3236       c_char = g_ascii_toupper(c_char);
3237     if (c_char == ascii_text[c_match]) {
3238       c_match += 1;
3239       if (c_match == textlen) {
3240         result = MR_MATCHED;
3241         cf->search_pos = i; /* Save the position of the last character
3242                                for highlighting the field. */
3243         cf->search_len = (guint32)textlen;
3244         break;
3245       }
3246       i += 1;
3247     }
3248     else {
3249       g_assert(i>=(c_match*2));
3250       i -= (guint32)c_match*2;
3251       c_match = 0;
3252     }
3253     i += 1;
3254   }
3255   return result;
3256 }
3257
3258 static match_result
3259 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3260 {
3261   cbs_t        *info        = (cbs_t *)criterion;
3262   const guint8 *binary_data = info->data;
3263   size_t        datalen     = info->data_len;
3264   match_result  result;
3265   guint32       buf_len;
3266   guint8       *pd;
3267   guint32       i;
3268   size_t        c_match     = 0;
3269
3270   /* Load the frame's data. */
3271   if (!cf_read_record(cf, fdata)) {
3272     /* Attempt to get the packet failed. */
3273     return MR_ERROR;
3274   }
3275
3276   result = MR_NOTMATCHED;
3277   buf_len = fdata->cap_len;
3278   pd = ws_buffer_start_ptr(&cf->buf);
3279   i = 0;
3280   while (i < buf_len) {
3281     if (pd[i] == binary_data[c_match]) {
3282       c_match += 1;
3283       if (c_match == datalen) {
3284         result = MR_MATCHED;
3285         cf->search_pos = i; /* Save the position of the last character
3286                                for highlighting the field. */
3287         cf->search_len = (guint32)datalen;
3288         break;
3289       }
3290     }
3291     else {
3292       g_assert(i>=c_match);
3293       i -= (guint32)c_match;
3294       c_match = 0;
3295     }
3296     i += 1;
3297   }
3298   return result;
3299 }
3300
3301 static match_result
3302 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3303 {
3304     match_result  result = MR_NOTMATCHED;
3305     GMatchInfo   *match_info = NULL;
3306
3307     /* Load the frame's data. */
3308     if (!cf_read_record(cf, fdata)) {
3309         /* Attempt to get the packet failed. */
3310         return MR_ERROR;
3311     }
3312
3313     if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3314                            0, (GRegexMatchFlags) 0, &match_info, NULL))
3315     {
3316         gint start_pos = 0, end_pos = 0;
3317         g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3318         cf->search_pos = end_pos - 1;
3319         cf->search_len = end_pos - start_pos;
3320         result = MR_MATCHED;
3321     }
3322     return result;
3323 }
3324
3325 gboolean
3326 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3327                        search_direction dir)
3328 {
3329   return find_packet(cf, match_dfilter, sfcode, dir);
3330 }
3331
3332 gboolean
3333 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3334                               search_direction dir)
3335 {
3336   dfilter_t *sfcode;
3337   gboolean   result;
3338
3339   if (!dfilter_compile(filter, &sfcode, NULL)) {
3340      /*
3341       * XXX - this shouldn't happen, as the filter string is machine
3342       * generated
3343       */
3344     return FALSE;
3345   }
3346   if (sfcode == NULL) {
3347     /*
3348      * XXX - this shouldn't happen, as the filter string is machine
3349      * generated.
3350      */
3351     return FALSE;
3352   }
3353   result = find_packet(cf, match_dfilter, sfcode, dir);
3354   dfilter_free(sfcode);
3355   return result;
3356 }
3357
3358 static match_result
3359 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3360 {
3361   dfilter_t      *sfcode = (dfilter_t *)criterion;
3362   epan_dissect_t  edt;
3363   match_result    result;
3364
3365   /* Load the frame's data. */
3366   if (!cf_read_record(cf, fdata)) {
3367     /* Attempt to get the packet failed. */
3368     return MR_ERROR;
3369   }
3370
3371   epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3372   epan_dissect_prime_with_dfilter(&edt, sfcode);
3373   epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3374   result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3375   epan_dissect_cleanup(&edt);
3376   return result;
3377 }
3378
3379 gboolean
3380 cf_find_packet_marked(capture_file *cf, search_direction dir)
3381 {
3382   return find_packet(cf, match_marked, NULL, dir);
3383 }
3384
3385 static match_result
3386 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3387 {
3388   return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3389 }
3390
3391 gboolean
3392 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3393 {
3394   return find_packet(cf, match_time_reference, NULL, dir);
3395 }
3396
3397 static match_result
3398 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3399 {
3400   return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3401 }
3402
3403 static gboolean
3404 find_packet(capture_file *cf,
3405             match_result (*match_function)(capture_file *, frame_data *, void *),
3406             void *criterion, search_direction dir)
3407 {
3408   frame_data  *start_fd;
3409   guint32      framenum;
3410   frame_data  *fdata;
3411   frame_data  *new_fd = NULL;
3412   progdlg_t   *progbar = NULL;
3413   GTimer      *prog_timer = g_timer_new();
3414   int          count;
3415   gboolean     found;
3416   float        progbar_val;
3417   GTimeVal     start_time;
3418   gchar        status_str[100];
3419   const char  *title;
3420   match_result result;
3421
3422   start_fd = cf->current_frame;
3423   if (start_fd != NULL)  {
3424     /* Iterate through the list of packets, starting at the packet we've
3425        picked, calling a routine to run the filter on the packet, see if
3426        it matches, and stop if so.  */
3427     count = 0;
3428     framenum = start_fd->num;
3429
3430     g_timer_start(prog_timer);
3431     /* Progress so far. */
3432     progbar_val = 0.0f;
3433
3434     cf->stop_flag = FALSE;
3435     g_get_current_time(&start_time);
3436
3437     title = cf->sfilter?cf->sfilter:"";
3438     for (;;) {
3439       /* Create the progress bar if necessary.
3440          We check on every iteration of the loop, so that it takes no
3441          longer than the standard time to create it (otherwise, for a
3442          large file, we might take considerably longer than that standard
3443          time in order to get to the next progress bar step). */
3444       if (progbar == NULL)
3445          progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3446            FALSE, &cf->stop_flag, &start_time, progbar_val);
3447
3448       /*
3449        * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3450        * has elapsed. Calling update_progress_dlg and packets_bar_update will
3451        * likely trigger UI paint events, which might take a while depending on
3452        * the platform and display. Reset our timer *after* painting.
3453        */
3454       if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3455         /* let's not divide by zero. I should never be started
3456          * with count == 0, so let's assert that
3457          */
3458         g_assert(cf->count > 0);
3459
3460         progbar_val = (gfloat) count / cf->count;
3461
3462         g_snprintf(status_str, sizeof(status_str),
3463                     "%4u of %u packets", count, cf->count);
3464         update_progress_dlg(progbar, progbar_val, status_str);
3465
3466         g_timer_start(prog_timer);
3467       }
3468
3469       if (cf->stop_flag) {
3470         /* Well, the user decided to abort the search.  Go back to the
3471            frame where we started. */
3472         new_fd = start_fd;
3473         break;
3474       }
3475
3476       /* Go past the current frame. */
3477       if (dir == SD_BACKWARD) {
3478         /* Go on to the previous frame. */
3479         if (framenum == 1) {
3480           /*
3481            * XXX - other apps have a bit more of a detailed message
3482            * for this, and instead of offering "OK" and "Cancel",
3483            * they offer things such as "Continue" and "Cancel";
3484            * we need an API for popping up alert boxes with
3485            * {Verb} and "Cancel".
3486            */
3487
3488           if (prefs.gui_find_wrap)
3489           {
3490               statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3491               framenum = cf->count;     /* wrap around */
3492           }
3493           else
3494           {
3495               statusbar_push_temporary_msg("Search reached the beginning.");
3496               framenum = start_fd->num; /* stay on previous packet */
3497           }
3498         } else
3499           framenum--;
3500       } else {
3501         /* Go on to the next frame. */
3502         if (framenum == cf->count) {
3503           if (prefs.gui_find_wrap)
3504           {
3505               statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3506               framenum = 1;             /* wrap around */
3507           }
3508           else
3509           {
3510               statusbar_push_temporary_msg("Search reached the end.");
3511               framenum = start_fd->num; /* stay on previous packet */
3512           }
3513         } else
3514           framenum++;
3515       }
3516       fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
3517
3518       count++;
3519
3520       /* Is this packet in the display? */
3521       if (fdata->flags.passed_dfilter) {
3522         /* Yes.  Does it match the search criterion? */
3523         result = (*match_function)(cf, fdata, criterion);
3524         if (result == MR_ERROR) {
3525           /* Error; our caller has reported the error.  Go back to the frame
3526              where we started. */
3527           new_fd = start_fd;
3528           break;
3529         } else if (result == MR_MATCHED) {
3530           /* Yes.  Go to the new frame. */
3531           new_fd = fdata;
3532           break;
3533         }
3534       }
3535
3536       if (fdata == start_fd) {
3537         /* We're back to the frame we were on originally, and that frame
3538            doesn't match the search filter.  The search failed. */
3539         break;
3540       }
3541     }
3542
3543     /* We're done scanning the packets; destroy the progress bar if it
3544        was created. */
3545     if (progbar != NULL)
3546       destroy_progress_dlg(progbar);
3547     g_timer_destroy(prog_timer);
3548   }
3549
3550   if (new_fd != NULL) {
3551     /* Find and select */
3552     cf->search_in_progress = TRUE;
3553     found = packet_list_select_row_from_data(new_fd);
3554     cf->search_in_progress = FALSE;
3555     cf->search_pos = 0; /* Reset the position */
3556     cf->search_len = 0; /* Reset length */
3557     if (!found) {
3558       /* We didn't find a row corresponding to this frame.
3559          This means that the frame isn't being displayed currently,
3560          so we can't select it. */
3561       simple_message_box(ESD_TYPE_INFO, NULL,
3562                          "The capture file is probably not fully dissected.",
3563                          "End of capture exceeded.");
3564       return FALSE;
3565     }
3566     return TRUE;    /* success */
3567   } else
3568     return FALSE;   /* failure */
3569 }
3570
3571 gboolean
3572 cf_goto_frame(capture_file *cf, guint fnumber)
3573 {
3574   frame_data *fdata;
3575
3576   if (cf == NULL || cf->frame_set_info.frames == NULL) {
3577     /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3578     statusbar_push_temporary_msg("There is no file loaded");
3579     return FALSE;   /* we failed to go to that packet */
3580   }
3581
3582   fdata = frame_data_sequence_find(cf->frame_set_info.frames, fnumber);
3583
3584   if (fdata == NULL) {
3585     /* we didn't find a packet with that packet number */
3586     statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3587     return FALSE;   /* we failed to go to that packet */
3588   }
3589   if (!fdata->flags.passed_dfilter) {
3590     /* that packet currently isn't displayed */
3591     /* XXX - add it to the set of displayed packets? */
3592     statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3593     return FALSE;   /* we failed to go to that packet */
3594   }
3595
3596   if (!packet_list_select_row_from_data(fdata)) {
3597     /* We didn't find a row corresponding to this frame.
3598        This means that the frame isn't being displayed currently,
3599        so we can't select it. */
3600     simple_message_box(ESD_TYPE_INFO, NULL,
3601                        "The capture file is probably not fully dissected.",
3602                        "End of capture exceeded.");
3603     return FALSE;
3604   }
3605   return TRUE;  /* we got to that packet */
3606 }
3607
3608 /*
3609  * Go to frame specified by currently selected protocol tree item.
3610  */
3611 gboolean
3612 cf_goto_framenum(capture_file *cf)
3613 {
3614   header_field_info *hfinfo;
3615   guint32            framenum;
3616
3617   if (cf->finfo_selected) {
3618     hfinfo = cf->finfo_selected->hfinfo;
3619     g_assert(hfinfo);
3620     if (hfinfo->type == FT_FRAMENUM) {
3621       framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3622       if (framenum != 0)
3623         return cf_goto_frame(cf, framenum);
3624       }
3625   }
3626
3627   return FALSE;
3628 }
3629
3630 /* Select the packet on a given row. */
3631 void
3632 cf_select_packet(capture_file *cf, int row)
3633 {
3634   epan_dissect_t *old_edt;
3635   frame_data     *fdata;
3636
3637   /* Get the frame data struct pointer for this frame */
3638   fdata = packet_list_get_row_data(row);
3639
3640   if (fdata == NULL) {
3641     return;
3642   }
3643
3644   /* Get the data in that frame. */
3645   if (!cf_read_record (cf, fdata)) {
3646     return;
3647   }
3648
3649   /* Record that this frame is the current frame. */
3650   cf->current_frame = fdata;
3651   cf->current_row = row;
3652
3653   old_edt = cf->edt;
3654   /* Create the logical protocol tree. */
3655   /* We don't need the columns here. */
3656   cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3657
3658   tap_build_interesting(cf->edt);
3659   epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3660                    cf->current_frame, NULL);
3661
3662   dfilter_macro_build_ftv_cache(cf->edt->tree);
3663
3664   cf_callback_invoke(cf_cb_packet_selected, cf);
3665
3666   if (old_edt != NULL)
3667     epan_dissect_free(old_edt);
3668
3669 }
3670
3671 /* Unselect the selected packet, if any. */
3672 void
3673 cf_unselect_packet(capture_file *cf)
3674 {
3675   epan_dissect_t *old_edt = cf->edt;
3676
3677   cf->edt = NULL;
3678
3679   /* No packet is selected. */
3680   cf->current_frame = NULL;
3681   cf->current_row = 0;
3682
3683   cf_callback_invoke(cf_cb_packet_unselected, cf);
3684
3685   /* No protocol tree means no selected field. */
3686   cf_unselect_field(cf);
3687
3688   /* Destroy the epan_dissect_t for the unselected packet. */
3689   if (old_edt != NULL)
3690     epan_dissect_free(old_edt);
3691 }
3692
3693 /* Unset the selected protocol tree field, if any. */
3694 void
3695 cf_unselect_field(capture_file *cf)
3696 {
3697   cf->finfo_selected = NULL;
3698
3699   cf_callback_invoke(cf_cb_field_unselected, cf);
3700 }
3701
3702 /*
3703  * Mark a particular frame.
3704  */
3705 void
3706 cf_mark_frame(capture_file *cf, frame_data *frame)
3707 {
3708   if (! frame->flags.marked) {
3709     frame->flags.marked = TRUE;
3710     if (cf->count > cf->marked_count)
3711       cf->marked_count++;
3712   }
3713 }
3714
3715 /*
3716  * Unmark a particular frame.
3717  */
3718 void
3719 cf_unmark_frame(capture_file *cf, frame_data *frame)
3720 {
3721   if (frame->flags.marked) {
3722     frame->flags.marked = FALSE;
3723     if (cf->marked_count > 0)
3724       cf->marked_count--;
3725   }
3726 }
3727
3728 /*
3729  * Ignore a particular frame.
3730  */
3731 void
3732 cf_ignore_frame(capture_file *cf, frame_data *frame)
3733 {
3734   if (! frame->flags.ignored) {
3735     frame->flags.ignored = TRUE;
3736     if (cf->count > cf->ignored_count)
3737       cf->ignored_count++;
3738   }
3739 }
3740
3741 /*
3742  * Un-ignore a particular frame.
3743  */
3744 void
3745 cf_unignore_frame(capture_file *cf, frame_data *frame)
3746 {
3747   if (frame->flags.ignored) {
3748     frame->flags.ignored = FALSE;
3749     if (cf->ignored_count > 0)
3750       cf->ignored_count--;
3751   }
3752 }
3753
3754 /*
3755  * Read the section comment.
3756  */
3757 const gchar *
3758 cf_read_section_comment(capture_file *cf)
3759 {
3760   wtap_block_t shb_inf;
3761   char *shb_comment;
3762
3763   /* Get the SHB. */
3764   /* XXX - support multiple SHBs */
3765   shb_inf = wtap_file_get_shb(cf->frame_set_info.wth);
3766
3767   /* Get the first comment from the SHB. */
3768   /* XXX - support multiple comments */
3769   if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3770     return NULL;
3771   return shb_comment;
3772 }
3773
3774 /*
3775  * Modify the section comment.
3776  */
3777 void
3778 cf_update_section_comment(capture_file *cf, gchar *comment)
3779 {
3780   wtap_block_t shb_inf;
3781   gchar *shb_comment;
3782
3783   /* Get the SHB. */
3784   /* XXX - support multiple SHBs */
3785   shb_inf = wtap_file_get_shb(cf->frame_set_info.wth);
3786
3787   /* Get the first comment from the SHB. */
3788   /* XXX - support multiple comments */
3789   if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3790     /* There's no comment - add one. */
3791     wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3792   } else {
3793     /* See if the comment has changed or not */
3794     if (strcmp(shb_comment, comment) == 0) {
3795       g_free(comment);
3796       return;
3797     }
3798
3799     /* The comment has changed, let's update it */
3800     wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3801   }
3802   /* Mark the file as having unsaved changes */
3803   cf->unsaved_changes = TRUE;
3804 }
3805
3806 static const char *
3807 cf_get_user_packet_comment(frame_set *fs, const frame_data *fd)
3808 {
3809   if (fs->frames_user_comments)
3810      return (const char *)g_tree_lookup(fs->frames_user_comments, fd);
3811
3812   /* g_warning? */
3813   return NULL;
3814 }
3815
3816 /*
3817  * Get the comment on a packet (record).
3818  * If the comment has been edited, it returns the result of the edit,
3819  * otherwise it returns the comment from the file.
3820  */
3821 char *
3822 cf_get_packet_comment(capture_file *cf, const frame_data *fd)
3823 {
3824   char *comment;
3825
3826   /* fetch user comment */
3827   if (fd->flags.has_user_comment)
3828     return g_strdup(cf_get_user_packet_comment(&cf->frame_set_info, fd));
3829
3830   /* fetch phdr comment */
3831   if (fd->flags.has_phdr_comment) {
3832     struct wtap_pkthdr phdr; /* Packet header */
3833     Buffer buf; /* Packet data */
3834
3835     wtap_phdr_init(&phdr);
3836     ws_buffer_init(&buf, 1500);
3837
3838     if (!cf_read_record_r(cf, fd, &phdr, &buf))
3839       { /* XXX, what we can do here? */ }
3840
3841     comment = phdr.opt_comment;
3842     wtap_phdr_cleanup(&phdr);
3843     ws_buffer_free(&buf);
3844     return comment;
3845   }
3846   return NULL;
3847 }
3848
3849 static int
3850 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3851 {
3852   const frame_data *fdata1 = (const frame_data *) a;
3853   const frame_data *fdata2 = (const frame_data *) b;
3854
3855   return (fdata1->num < fdata2->num) ? -1 :
3856     (fdata1->num > fdata2->num) ? 1 :
3857     0;
3858 }
3859
3860 /*
3861  * Update(replace) the comment on a capture from a frame
3862  */
3863 gboolean
3864 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3865 {
3866   char *pkt_comment = cf_get_packet_comment(cf, fd);
3867
3868   /* Check if the comment has changed */
3869   if (!g_strcmp0(pkt_comment, new_comment)) {
3870     g_free(pkt_comment);
3871     return FALSE;
3872   }
3873   g_free(pkt_comment);
3874
3875   if (pkt_comment)
3876     cf->packet_comment_count--;
3877
3878   if (new_comment)
3879     cf->packet_comment_count++;
3880
3881   fd->flags.has_user_comment = TRUE;
3882
3883   if (!cf->frame_set_info.frames_user_comments)
3884     cf->frame_set_info.frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
3885
3886   /* insert new packet comment */
3887   g_tree_replace(cf->frame_set_info.frames_user_comments, fd, g_strdup(new_comment));
3888
3889   expert_update_comment_count(cf->packet_comment_count);
3890
3891   /* OK, we have unsaved changes. */
3892   cf->unsaved_changes = TRUE;
3893   return TRUE;
3894 }
3895
3896 /*
3897  * What types of comments does this capture file have?
3898  */
3899 guint32
3900 cf_comment_types(capture_file *cf)
3901 {
3902   guint32 comment_types = 0;
3903
3904   if (cf_read_section_comment(cf) != NULL)
3905     comment_types |= WTAP_COMMENT_PER_SECTION;
3906   if (cf->packet_comment_count != 0)
3907     comment_types |= WTAP_COMMENT_PER_PACKET;
3908   return comment_types;
3909 }
3910
3911 /*
3912  * Add a resolved address to this file's list of resolved addresses.
3913  */
3914 gboolean
3915 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
3916 {
3917   /*
3918    * XXX - support multiple resolved address lists, and add to the one
3919    * attached to this file?
3920    */
3921   if (!add_ip_name_from_string(addr, name))
3922     return FALSE;
3923
3924   /* OK, we have unsaved changes. */
3925   cf->unsaved_changes = TRUE;
3926   return TRUE;
3927 }
3928
3929 typedef struct {
3930   wtap_dumper *pdh;
3931   const char  *fname;
3932   int          file_type;
3933 } save_callback_args_t;
3934
3935 /*
3936  * Save a capture to a file, in a particular format, saving either
3937  * all packets, all currently-displayed packets, or all marked packets.
3938  *
3939  * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3940  * up a message box for the failure.
3941  */
3942 static gboolean
3943 save_record(capture_file *cf, frame_data *fdata,
3944             struct wtap_pkthdr *phdr, const guint8 *pd,
3945             void *argsp)
3946 {
3947   save_callback_args_t *args = (save_callback_args_t *)argsp;
3948   struct wtap_pkthdr    hdr;
3949   int           err;
3950   gchar        *err_info;
3951   const char   *pkt_comment;
3952
3953   if (fdata->flags.has_user_comment)
3954     pkt_comment = cf_get_user_packet_comment(&cf->frame_set_info, fdata);
3955   else
3956     pkt_comment = phdr->opt_comment;
3957
3958   /* init the wtap header for saving */
3959   /* TODO: reuse phdr */
3960   /* XXX - these are the only flags that correspond to data that we have
3961      in the frame_data structure and that matter on a per-packet basis.
3962
3963      For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
3964      and "on the wire" lengths, or it doesn't.
3965
3966      For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
3967      to its callers.
3968
3969      For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
3970      from the packet flags. */
3971   hdr.rec_type = phdr->rec_type;
3972   hdr.presence_flags = 0;
3973   if (fdata->flags.has_ts)
3974     hdr.presence_flags |= WTAP_HAS_TS;
3975   if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
3976     hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
3977   if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
3978     hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
3979   hdr.ts           = phdr->ts;
3980   hdr.caplen       = phdr->caplen;
3981   hdr.len          = phdr->len;
3982   hdr.pkt_encap    = phdr->pkt_encap;
3983   /* pcapng */
3984   hdr.interface_id = phdr->interface_id;   /* identifier of the interface. */
3985   /* options */
3986   hdr.pack_flags   = phdr->pack_flags;
3987   hdr.opt_comment  = g_strdup(pkt_comment);
3988   hdr.has_comment_changed = fdata->flags.has_user_comment ? TRUE : FALSE;
3989
3990   /* pseudo */
3991   hdr.pseudo_header = phdr->pseudo_header;
3992 #if 0
3993   hdr.drop_count   =
3994   hdr.pack_flags   =     /* XXX - 0 for now (any value for "we don't have it"?) */
3995 #endif
3996   /* and save the packet */
3997   if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
3998     cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
3999                                   args->file_type);
4000     return FALSE;
4001   }
4002
4003   g_free(hdr.opt_comment);
4004   return TRUE;
4005 }
4006
4007 /*
4008  * Can this capture file be written out in any format using Wiretap
4009  * rather than by copying the raw data?
4010  */
4011 gboolean
4012 cf_can_write_with_wiretap(capture_file *cf)
4013 {
4014   /* We don't care whether we support the comments in this file or not;
4015      if we can't, we'll offer the user the option of discarding the
4016      comments. */
4017   return wtap_dump_can_write(cf->linktypes, 0);
4018 }
4019
4020 /*
4021  * Should we let the user do a save?
4022  *
4023  * We should if:
4024  *
4025  *  the file has unsaved changes, and we can save it in some
4026  *  format through Wiretap
4027  *
4028  * or
4029  *
4030  *  the file is a temporary file and has no unsaved changes (so
4031  *  that "saving" it just means copying it).
4032  *
4033  * XXX - we shouldn't allow files to be edited if they can't be saved,
4034  * so cf->unsaved_changes should be true only if the file can be saved.
4035  *
4036  * We don't care whether we support the comments in this file or not;
4037  * if we can't, we'll offer the user the option of discarding the
4038  * comments.
4039  */
4040 gboolean
4041 cf_can_save(capture_file *cf)
4042 {
4043   if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4044     /* Saved changes, and we can write it out with Wiretap. */
4045     return TRUE;
4046   }
4047
4048   if (cf->is_tempfile && !cf->unsaved_changes) {
4049     /*
4050      * Temporary file with no unsaved changes, so we can just do a
4051      * raw binary copy.
4052      */
4053     return TRUE;
4054   }
4055
4056   /* Nothing to save. */
4057   return FALSE;
4058 }
4059
4060 /*
4061  * Should we let the user do a "save as"?
4062  *
4063  * That's true if:
4064  *
4065  *  we can save it in some format through Wiretap
4066  *
4067  * or
4068  *
4069  *  the file is a temporary file and has no unsaved changes (so
4070  *  that "saving" it just means copying it).
4071  *
4072  * XXX - we shouldn't allow files to be edited if they can't be saved,
4073  * so cf->unsaved_changes should be true only if the file can be saved.
4074  *
4075  * We don't care whether we support the comments in this file or not;
4076  * if we can't, we'll offer the user the option of discarding the
4077  * comments.
4078  */
4079 gboolean
4080 cf_can_save_as(capture_file *cf)
4081 {
4082   if (wtap_dump_can_write(cf->linktypes, 0)) {
4083     /* We can write it out with Wiretap. */
4084     return TRUE;
4085   }
4086
4087   if (cf->is_tempfile && !cf->unsaved_changes) {
4088     /*
4089      * Temporary file with no unsaved changes, so we can just do a
4090      * raw binary copy.
4091      */
4092     return TRUE;
4093   }
4094
4095   /* Nothing to save. */
4096   return FALSE;
4097 }
4098
4099 /*
4100  * Does this file have unsaved data?
4101  */
4102 gboolean
4103 cf_has_unsaved_data(capture_file *cf)
4104 {
4105   /*
4106    * If this is a temporary file, or a file with unsaved changes, it
4107    * has unsaved data.
4108    */
4109   return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4110 }
4111
4112 /*
4113  * Quick scan to find packet offsets.
4114  */
4115 static cf_read_status_t
4116 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
4117 {
4118   const struct wtap_pkthdr *phdr;
4119   int                  err;
4120   gchar               *err_info;
4121   gchar               *name_ptr;
4122   gint64               data_offset;
4123   progdlg_t           *progbar        = NULL;
4124   GTimer              *prog_timer = g_timer_new();
4125   gint64               size;
4126   float                progbar_val;
4127   GTimeVal             start_time;
4128   gchar                status_str[100];
4129   guint32              framenum;
4130   frame_data          *fdata;
4131   int                  count          = 0;
4132
4133   /* Close the old handle. */
4134   wtap_close(cf->frame_set_info.wth);
4135
4136   /* Open the new file. */
4137   /* XXX: this will go through all open_routines for a matching one. But right
4138      now rescan_file() is only used when a file is being saved to a different
4139      format than the original, and the user is not given a choice of which
4140      reader to use (only which format to save it in), so doing this makes
4141      sense for now. */
4142   cf->frame_set_info.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4143   if (cf->frame_set_info.wth == NULL) {
4144     cfile_open_failure_alert_box(fname, err, err_info);
4145     return CF_READ_ERROR;
4146   }
4147
4148   /* We're scanning a file whose contents should be the same as what
4149      we had before, so we don't discard dissection state etc.. */
4150   cf->f_datalen = 0;
4151
4152   /* Set the file name because we need it to set the follow stream filter.
4153      XXX - is that still true?  We need it for other reasons, though,
4154      in any case. */
4155   cf->filename = g_strdup(fname);
4156
4157   /* Indicate whether it's a permanent or temporary file. */
4158   cf->is_tempfile = is_tempfile;
4159
4160   /* No user changes yet. */
4161   cf->unsaved_changes = FALSE;
4162
4163   cf->cd_t        = wtap_file_type_subtype(cf->frame_set_info.wth);
4164   cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4165
4166   cf->snap      = wtap_snapshot_length(cf->frame_set_info.wth);
4167
4168   name_ptr = g_filename_display_basename(cf->filename);
4169
4170   cf_callback_invoke(cf_cb_file_rescan_started, cf);
4171
4172   /* Record whether the file is compressed.
4173      XXX - do we know this at open time? */
4174   cf->iscompressed = wtap_iscompressed(cf->frame_set_info.wth);
4175
4176   /* Find the size of the file. */
4177   size = wtap_file_size(cf->frame_set_info.wth, NULL);
4178
4179   g_timer_start(prog_timer);
4180
4181   cf->stop_flag = FALSE;
4182   g_get_current_time(&start_time);
4183
4184   framenum = 0;
4185   phdr = wtap_phdr(cf->frame_set_info.wth);
4186   while ((wtap_read(cf->frame_set_info.wth, &err, &err_info, &data_offset))) {
4187     framenum++;
4188     fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
4189     fdata->file_off = data_offset;
4190     if (size >= 0) {
4191       count++;
4192       cf->f_datalen = wtap_read_so_far(cf->frame_set_info.wth);
4193
4194       /* Create the progress bar if necessary. */
4195       if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4196         progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4197         progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4198                                               TRUE, &cf->stop_flag, &start_time, progbar_val);
4199       }
4200
4201       /*
4202        * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4203        * has elapsed. Calling update_progress_dlg and packets_bar_update will
4204        * likely trigger UI paint events, which might take a while depending on
4205        * the platform and display. Reset our timer *after* painting.
4206        */
4207       if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4208         progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4209         /* update the packet bar content on the first run or frequently on very large files */
4210         update_progress_dlg(progbar, progbar_val, status_str);
4211         compute_elapsed(cf, &start_time);
4212         packets_bar_update();
4213         g_timer_start(prog_timer);
4214       }
4215     }
4216
4217     if (cf->stop_flag) {
4218       /* Well, the user decided to abort the rescan.  Sadly, as this
4219          isn't a reread, recovering is difficult, so we'll just
4220          close the current capture. */
4221       break;
4222     }
4223
4224     /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4225        it's not already there.
4226        XXX - yes, this is O(N), so if every packet had a different
4227        link-layer encapsulation type, it'd be O(N^2) to read the file, but
4228        there are probably going to be a small number of encapsulation types
4229        in a file. */
4230     cf_add_encapsulation_type(cf, phdr->pkt_encap);
4231   }
4232
4233   /* Free the display name */
4234   g_free(name_ptr);
4235
4236   /* We're done reading the file; destroy the progress bar if it was created. */
4237   if (progbar != NULL)
4238     destroy_progress_dlg(progbar);
4239   g_timer_destroy(prog_timer);
4240
4241   /* We're done reading sequentially through the file. */
4242   cf->state = FILE_READ_DONE;
4243
4244   /* Close the sequential I/O side, to free up memory it requires. */
4245   wtap_sequential_close(cf->frame_set_info.wth);
4246
4247   /* compute the time it took to load the file */
4248   compute_elapsed(cf, &start_time);
4249
4250   /* Set the file encapsulation type now; we don't know what it is until
4251      we've looked at all the packets, as we don't know until then whether
4252      there's more than one type (and thus whether it's
4253      WTAP_ENCAP_PER_PACKET). */
4254   cf->lnk_t = wtap_file_encap(cf->frame_set_info.wth);
4255
4256   cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4257
4258   if (cf->stop_flag) {
4259     /* Our caller will give up at this point. */
4260     return CF_READ_ABORTED;
4261   }
4262
4263   if (err != 0) {
4264     /* Put up a message box noting that the read failed somewhere along
4265        the line.  Don't throw out the stuff we managed to read, though,
4266        if any. */
4267     cfile_read_failure_alert_box(NULL, err, err_info);
4268     return CF_READ_ERROR;
4269   } else
4270     return CF_READ_OK;
4271 }
4272
4273 cf_write_status_t
4274 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4275                 gboolean compressed, gboolean discard_comments,
4276                 gboolean dont_reopen)
4277 {
4278   gchar           *err_info;
4279   gchar           *fname_new = NULL;
4280   wtap_dumper     *pdh;
4281   frame_data      *fdata;
4282   addrinfo_lists_t *addr_lists;
4283   guint            framenum;
4284   int              err;
4285 #ifdef _WIN32
4286   gchar           *display_basename;
4287 #endif
4288   enum {
4289      SAVE_WITH_MOVE,
4290      SAVE_WITH_COPY,
4291      SAVE_WITH_WTAP
4292   }                    how_to_save;
4293   save_callback_args_t callback_args;
4294   gboolean needs_reload = FALSE;
4295
4296   cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4297
4298   addr_lists = get_addrinfo_list();
4299
4300   if (save_format == cf->cd_t && compressed == cf->iscompressed
4301       && !discard_comments && !cf->unsaved_changes
4302       && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4303     /* We're saving in the format it's already in, and we're
4304        not discarding comments, and there are no changes we have
4305        in memory that aren't saved to the file, and we have no name
4306        resolution blocks to write, so we can just move or copy the raw data. */
4307
4308     if (cf->is_tempfile) {
4309       /* The file being saved is a temporary file from a live
4310          capture, so it doesn't need to stay around under that name;
4311          first, try renaming the capture buffer file to the new name.
4312          This acts as a "safe save", in that, if the file already
4313          exists, the existing file will be removed only if the rename
4314          succeeds.
4315
4316          Sadly, on Windows, as we have the current capture file
4317          open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4318          (to cause the rename to remove an existing target), as
4319          done by ws_stdio_rename() (ws_rename() is #defined to
4320          be ws_stdio_rename() on Windows) will fail.
4321
4322          According to the MSDN documentation for CreateFile(), if,
4323          when we open a capture file, we were to directly do a CreateFile(),
4324          opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4325          convert it to a file descriptor with _open_osfhandle(),
4326          that would allow the file to be renamed out from under us.
4327
4328          However, that doesn't work in practice.  Perhaps the problem
4329          is that the process doing the rename is the process that
4330          has the file open. */
4331 #ifndef _WIN32
4332       if (ws_rename(cf->filename, fname) == 0) {
4333         /* That succeeded - there's no need to copy the source file. */
4334         how_to_save = SAVE_WITH_MOVE;
4335       } else {
4336         if (errno == EXDEV) {
4337           /* They're on different file systems, so we have to copy the
4338              file. */
4339           how_to_save = SAVE_WITH_COPY;
4340         } else {
4341           /* The rename failed, but not because they're on different
4342              file systems - put up an error message.  (Or should we
4343              just punt and try to copy?  The only reason why I'd
4344              expect the rename to fail and the copy to succeed would
4345              be if we didn't have permission to remove the file from
4346              the temporary directory, and that might be fixable - but
4347              is it worth requiring the user to go off and fix it?) */
4348           cf_rename_failure_alert_box(fname, errno);
4349           goto fail;
4350         }
4351       }
4352 #else
4353       how_to_save = SAVE_WITH_COPY;
4354 #endif
4355     } else {
4356       /* It's a permanent file, so we should copy it, and not remove the
4357          original. */
4358       how_to_save = SAVE_WITH_COPY;
4359     }
4360
4361     if (how_to_save == SAVE_WITH_COPY) {
4362       /* Copy the file, if we haven't moved it.  If we're overwriting
4363          an existing file, we do it with a "safe save", by writing
4364          to a new file and, if the write succeeds, renaming the
4365          new file on top of the old file. */
4366       if (file_exists(fname)) {
4367         fname_new = g_strdup_printf("%s~", fname);
4368         if (!copy_file_binary_mode(cf->filename, fname_new))
4369           goto fail;
4370       } else {
4371         if (!copy_file_binary_mode(cf->filename, fname))
4372           goto fail;
4373       }
4374     }
4375   } else {
4376     /* Either we're saving in a different format or we're saving changes,
4377        such as added, modified, or removed comments, that haven't yet
4378        been written to the underlying file; we can't do that by copying
4379        or moving the capture file, we have to do it by writing the packets
4380        out in Wiretap. */
4381
4382     GArray                      *shb_hdrs = NULL;
4383     wtapng_iface_descriptions_t *idb_inf = NULL;
4384     GArray                      *nrb_hdrs = NULL;
4385     int encap;
4386
4387     /* XXX: what free's this shb_hdr? */
4388     shb_hdrs = wtap_file_get_shb_for_new_file(cf->frame_set_info.wth);
4389     idb_inf = wtap_file_get_idb_info(cf->frame_set_info.wth);
4390     nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->frame_set_info.wth);
4391
4392     /* Determine what file encapsulation type we should use. */
4393     encap = wtap_dump_file_encap_type(cf->linktypes);
4394
4395     if (file_exists(fname)) {
4396       /* We're overwriting an existing file; write out to a new file,
4397          and, if that succeeds, rename the new file on top of the
4398          old file.  That makes this a "safe save", so that we don't
4399          lose the old file if we have a problem writing out the new
4400          file.  (If the existing file is the current capture file,
4401          we *HAVE* to do that, otherwise we're overwriting the file
4402          from which we're reading the packets that we're writing!) */
4403       fname_new = g_strdup_printf("%s~", fname);
4404       pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4405                               compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4406     } else {
4407       pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4408                               compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4409     }
4410     g_free(idb_inf);
4411     idb_inf = NULL;
4412
4413     if (pdh == NULL) {
4414       cfile_dump_open_failure_alert_box(fname, err, save_format);
4415       goto fail;
4416     }
4417
4418     /* Add address resolution */
4419     wtap_dump_set_addrinfo_list(pdh, addr_lists);
4420
4421     /* Iterate through the list of packets, processing all the packets. */
4422     callback_args.pdh = pdh;
4423     callback_args.fname = fname;
4424     callback_args.file_type = save_format;
4425     switch (process_specified_records(cf, NULL, "Saving", "packets",
4426                                       TRUE, save_record, &callback_args, TRUE)) {
4427
4428     case PSP_FINISHED:
4429       /* Completed successfully. */
4430       break;
4431
4432     case PSP_STOPPED:
4433       /* The user decided to abort the saving.
4434          If we're writing to a temporary file, remove it.
4435          XXX - should we do so even if we're not writing to a
4436          temporary file? */
4437       wtap_dump_close(pdh, &err);
4438       if (fname_new != NULL)
4439         ws_unlink(fname_new);
4440       cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4441       return CF_WRITE_ABORTED;
4442
4443     case PSP_FAILED:
4444       /* Error while saving.
4445          If we're writing to a temporary file, remove it. */
4446       if (fname_new != NULL)
4447         ws_unlink(fname_new);
4448       wtap_dump_close(pdh, &err);
4449       goto fail;
4450     }
4451
4452     needs_reload = wtap_dump_get_needs_reload(pdh);
4453
4454     if (!wtap_dump_close(pdh, &err)) {
4455       cfile_close_failure_alert_box(fname, err);
4456       goto fail;
4457     }
4458
4459     how_to_save = SAVE_WITH_WTAP;
4460   }
4461
4462   if (fname_new != NULL) {
4463     /* We wrote out to fname_new, and should rename it on top of
4464        fname.  fname_new is now closed, so that should be possible even
4465        on Windows.  However, on Windows, we first need to close whatever
4466        file descriptors we have open for fname. */
4467 #ifdef _WIN32
4468     wtap_fdclose(cf->frame_set_info.wth);
4469 #endif
4470     /* Now do the rename. */
4471     if (ws_rename(fname_new, fname) == -1) {
4472       /* Well, the rename failed. */
4473       cf_rename_failure_alert_box(fname, errno);
4474 #ifdef _WIN32
4475       /* Attempt to reopen the random file descriptor using the
4476          current file's filename.  (At this point, the sequential
4477          file descriptor is closed.) */
4478       if (!wtap_fdreopen(cf->frame_set_info.wth, cf->filename, &err)) {
4479         /* Oh, well, we're screwed. */
4480         display_basename = g_filename_display_basename(cf->filename);
4481         simple_error_message_box(
4482                       file_open_error_message(err, FALSE), display_basename);
4483         g_free(display_basename);
4484       }
4485 #endif
4486       goto fail;
4487     }
4488   }
4489
4490   cf_callback_invoke(cf_cb_file_save_finished, NULL);
4491   cf->unsaved_changes = FALSE;
4492
4493   if (!dont_reopen) {
4494     switch (how_to_save) {
4495
4496     case SAVE_WITH_MOVE:
4497       /* We just moved the file, so the wtap structure refers to the
4498          new file, and all the information other than the filename
4499          and the "is temporary" status applies to the new file; just
4500          update that. */
4501       g_free(cf->filename);
4502       cf->filename = g_strdup(fname);
4503       cf->is_tempfile = FALSE;
4504       cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4505       break;
4506
4507     case SAVE_WITH_COPY:
4508       /* We just copied the file, s all the information other than
4509          the wtap structure, the filename, and the "is temporary"
4510          status applies to the new file; just update that. */
4511       wtap_close(cf->frame_set_info.wth);
4512       /* Although we're just "copying" and then opening the copy, it will
4513          try all open_routine readers to open the copy, so we need to
4514          reset the cfile's open_type. */
4515       cf->open_type = WTAP_TYPE_AUTO;
4516       cf->frame_set_info.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4517       if (cf->frame_set_info.wth == NULL) {
4518         cfile_open_failure_alert_box(fname, err, err_info);
4519         cf_close(cf);
4520       } else {
4521         g_free(cf->filename);
4522         cf->filename = g_strdup(fname);
4523         cf->is_tempfile = FALSE;
4524       }
4525       cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4526       break;
4527
4528     case SAVE_WITH_WTAP:
4529       /* Open and read the file we saved to.
4530
4531          XXX - this is somewhat of a waste; we already have the
4532          packets, all this gets us is updated file type information
4533          (which we could just stuff into "cf"), and having the new
4534          file be the one we have opened and from which we're reading
4535          the data, and it means we have to spend time opening and
4536          reading the file, which could be a significant amount of
4537          time if the file is large.
4538
4539          If the capture-file-writing code were to return the
4540          seek offset of each packet it writes, we could save that
4541          in the frame_data structure for the frame, and just open
4542          the file without reading it again...
4543
4544          ...as long as, for gzipped files, the process of writing
4545          out the file *also* generates the information needed to
4546          support fast random access to the compressed file. */
4547       /* rescan_file will cause us to try all open_routines, so
4548          reset cfile's open_type */
4549       cf->open_type = WTAP_TYPE_AUTO;
4550       /* There are cases when SAVE_WITH_WTAP can result in new packets
4551          being written to the file, e.g ERF records
4552          In that case, we need to reload the whole file */
4553       if(needs_reload) {
4554         if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) {
4555           if (cf_read(cf, TRUE) != CF_READ_OK) {
4556              /* The rescan failed; just close the file.  Either
4557                a dialog was popped up for the failure, so the
4558                user knows what happened, or they stopped the
4559                rescan, in which case they know what happened.  */
4560             /* XXX: This is inconsistent with normal open/reload behaviour. */
4561             cf_close(cf);
4562           }
4563         }
4564       }
4565       else {
4566         if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
4567            /* The rescan failed; just close the file.  Either
4568              a dialog was popped up for the failure, so the
4569              user knows what happened, or they stopped the
4570              rescan, in which case they know what happened.  */
4571           cf_close(cf);
4572         }
4573       }
4574       break;
4575     }
4576
4577     /* If we were told to discard the comments, do so. */
4578     if (discard_comments) {
4579       /* Remove SHB comment, if any. */
4580       wtap_write_shb_comment(cf->frame_set_info.wth, NULL);
4581
4582       /* remove all user comments */
4583       for (framenum = 1; framenum <= cf->count; framenum++) {
4584         fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
4585
4586         fdata->flags.has_phdr_comment = FALSE;
4587         fdata->flags.has_user_comment = FALSE;
4588       }
4589
4590       if (cf->frame_set_info.frames_user_comments) {
4591         g_tree_destroy(cf->frame_set_info.frames_user_comments);
4592         cf->frame_set_info.frames_user_comments = NULL;
4593       }
4594
4595       cf->packet_comment_count = 0;
4596     }
4597   }
4598   return CF_WRITE_OK;
4599
4600 fail:
4601   if (fname_new != NULL) {
4602     /* We were trying to write to a temporary file; get rid of it if it
4603        exists.  (We don't care whether this fails, as, if it fails,
4604        there's not much we can do about it.  I guess if it failed for
4605        a reason other than "it doesn't exist", we could report an
4606        error, so the user knows there's a junk file that they might
4607        want to clean up.) */
4608     ws_unlink(fname_new);
4609     g_free(fname_new);
4610   }
4611   cf_callback_invoke(cf_cb_file_save_failed, NULL);
4612   return CF_WRITE_ERROR;
4613 }
4614
4615 cf_write_status_t
4616 cf_export_specified_packets(capture_file *cf, const char *fname,
4617                             packet_range_t *range, guint save_format,
4618                             gboolean compressed)
4619 {
4620   gchar                       *fname_new = NULL;
4621   int                          err;
4622   wtap_dumper                 *pdh;
4623   save_callback_args_t         callback_args;
4624   GArray                      *shb_hdrs = NULL;
4625   wtapng_iface_descriptions_t *idb_inf = NULL;
4626   GArray                      *nrb_hdrs = NULL;
4627   int                          encap;
4628
4629   cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4630
4631   packet_range_process_init(range);
4632
4633   /* We're writing out specified packets from the specified capture
4634      file to another file.  Even if all captured packets are to be
4635      written, don't special-case the operation - read each packet
4636      and then write it out if it's one of the specified ones. */
4637
4638   /* XXX: what free's this shb_hdr? */
4639   shb_hdrs = wtap_file_get_shb_for_new_file(cf->frame_set_info.wth);
4640   idb_inf = wtap_file_get_idb_info(cf->frame_set_info.wth);
4641   nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->frame_set_info.wth);
4642
4643   /* Determine what file encapsulation type we should use. */
4644   encap = wtap_dump_file_encap_type(cf->linktypes);
4645
4646   if (file_exists(fname)) {
4647     /* We're overwriting an existing file; write out to a new file,
4648        and, if that succeeds, rename the new file on top of the
4649        old file.  That makes this a "safe save", so that we don't
4650        lose the old file if we have a problem writing out the new
4651        file.  (If the existing file is the current capture file,
4652        we *HAVE* to do that, otherwise we're overwriting the file
4653        from which we're reading the packets that we're writing!) */
4654     fname_new = g_strdup_printf("%s~", fname);
4655     pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4656                             compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4657   } else {
4658     pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4659                             compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4660   }
4661   g_free(idb_inf);
4662   idb_inf = NULL;
4663
4664   if (pdh == NULL) {
4665     cfile_dump_open_failure_alert_box(fname, err, save_format);
4666     goto fail;
4667   }
4668
4669   /* Add address resolution */
4670   wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4671
4672   /* Iterate through the list of packets, processing the packets we were
4673      told to process.
4674
4675      XXX - we've already called "packet_range_process_init(range)", but
4676      "process_specified_records()" will do it again.  Fortunately,
4677      that's harmless in this case, as we haven't done anything to
4678      "range" since we initialized it. */
4679   callback_args.pdh = pdh;
4680   callback_args.fname = fname;
4681   callback_args.file_type = save_format;
4682   switch (process_specified_records(cf, range, "Writing", "specified records",
4683                                     TRUE, save_record, &callback_args, TRUE)) {
4684
4685   case PSP_FINISHED:
4686     /* Completed successfully. */
4687     break;
4688
4689   case PSP_STOPPED:
4690       /* The user decided to abort the saving.
4691          If we're writing to a temporary file, remove it.
4692          XXX - should we do so even if we're not writing to a
4693          temporary file? */
4694       wtap_dump_close(pdh, &err);
4695       if (fname_new != NULL)
4696         ws_unlink(fname_new);
4697       cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4698       return CF_WRITE_ABORTED;
4699     break;
4700
4701   case PSP_FAILED:
4702     /* Error while saving.
4703        If we're writing to a temporary file, remove it. */
4704     if (fname_new != NULL)
4705       ws_unlink(fname_new);
4706     wtap_dump_close(pdh, &err);
4707     goto fail;
4708   }
4709
4710   if (!wtap_dump_close(pdh, &err)) {
4711     cfile_close_failure_alert_box(fname, err);
4712     goto fail;
4713   }
4714
4715   if (fname_new != NULL) {
4716     /* We wrote out to fname_new, and should rename it on top of
4717        fname; fname is now closed, so that should be possible even
4718        on Windows.  Do the rename. */
4719     if (ws_rename(fname_new, fname) == -1) {
4720       /* Well, the rename failed. */
4721       cf_rename_failure_alert_box(fname, errno);
4722       goto fail;
4723     }
4724   }
4725
4726   cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4727   return CF_WRITE_OK;
4728
4729 fail:
4730   if (fname_new != NULL) {
4731     /* We were trying to write to a temporary file; get rid of it if it
4732        exists.  (We don't care whether this fails, as, if it fails,
4733        there's not much we can do about it.  I guess if it failed for
4734        a reason other than "it doesn't exist", we could report an
4735        error, so the user knows there's a junk file that they might
4736        want to clean up.) */
4737     ws_unlink(fname_new);
4738     g_free(fname_new);
4739   }
4740   cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4741   return CF_WRITE_ERROR;
4742 }
4743
4744 /*
4745  * XXX - whether we mention the source pathname, the target pathname,
4746  * or both depends on the error and on what we find if we look for
4747  * one or both of them.
4748  */
4749 static void
4750 cf_rename_failure_alert_box(const char *filename, int err)
4751 {
4752   gchar *display_basename;
4753
4754   display_basename = g_filename_display_basename(filename);
4755   switch (err) {
4756
4757   case ENOENT:
4758     /* XXX - should check whether the source exists and, if not,
4759        report it as the problem and, if so, report the destination
4760        as the problem. */
4761     simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4762                              display_basename);
4763     break;
4764
4765   case EACCES:
4766     /* XXX - if we're doing a rename after a safe save, we should
4767        probably say something else. */
4768     simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4769                              display_basename);
4770     break;
4771
4772   default:
4773     /* XXX - this should probably mention both the source and destination
4774        pathnames. */
4775     simple_error_message_box("The file \"%s\" could not be moved: %s.",
4776                              display_basename, wtap_strerror(err));
4777     break;
4778   }
4779   g_free(display_basename);
4780 }
4781
4782 /* Reload the current capture file. */
4783 void
4784 cf_reload(capture_file *cf) {
4785   gchar    *filename;
4786   gboolean  is_tempfile;
4787   int       err;
4788
4789   /* If the file could be opened, "cf_open()" calls "cf_close()"
4790      to get rid of state for the old capture file before filling in state
4791      for the new capture file.  "cf_close()" will remove the file if
4792      it's a temporary file; we don't want that to happen (for one thing,
4793      it'd prevent subsequent reopens from working).  Remember whether it's
4794      a temporary file, mark it as not being a temporary file, and then
4795      reopen it as the type of file it was.
4796
4797      Also, "cf_close()" will free "cf->filename", so we must make
4798      a copy of it first. */
4799   filename = g_strdup(cf->filename);
4800   is_tempfile = cf->is_tempfile;
4801   cf->is_tempfile = FALSE;
4802   if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
4803     switch (cf_read(cf, TRUE)) {
4804
4805     case CF_READ_OK:
4806     case CF_READ_ERROR:
4807       /* Just because we got an error, that doesn't mean we were unable
4808          to read any of the file; we handle what we could get from the
4809          file. */
4810       break;
4811
4812     case CF_READ_ABORTED:
4813       /* The user bailed out of re-reading the capture file; the
4814          capture file has been closed - just free the capture file name
4815          string and return (without changing the last containing
4816          directory). */
4817       g_free(filename);
4818       return;
4819     }
4820   } else {
4821     /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4822        Instead, the file was left open, so we should restore "cf->is_tempfile"
4823        ourselves.
4824
4825        XXX - change the menu?  Presumably "cf_open()" will do that;
4826        make sure it does! */
4827     cf->is_tempfile = is_tempfile;
4828   }
4829   /* "cf_open()" made a copy of the file name we handed it, so
4830      we should free up our copy. */
4831   g_free(filename);
4832 }
4833
4834 /*
4835  * Editor modelines
4836  *
4837  * Local Variables:
4838  * c-basic-offset: 2
4839  * tab-width: 8
4840  * indent-tabs-mode: nil
4841  * End:
4842  *
4843  * ex: set shiftwidth=2 tabstop=8 expandtab:
4844  * :indentSize=2:tabSize=8:noTabs=true:
4845  */