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