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