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