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