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