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