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