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