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