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