From Didier via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=3055 :
[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 #if GLIB_CHECK_VERSION(2,10,0)
403   if (cf->plist_start != NULL)
404     g_slice_free_chain(frame_data, cf->plist_start, next);
405 #else
406   /* memory chunks have been deprecated in favor of the slice allocator,
407    * which has been added in 2.10
408    */
409   if (cf->plist_chunk != NULL) {
410     g_mem_chunk_destroy(cf->plist_chunk);
411     cf->plist_chunk = NULL;
412   }
413 #endif
414   dfilter_free(cf->rfcode);
415   cf->rfcode = NULL;
416   cf->plist_start = NULL;
417   cf->plist_end = NULL;
418   cf_unselect_packet(cf);   /* nothing to select */
419   cf->first_displayed = NULL;
420   cf->last_displayed = NULL;
421
422   /* No frame selected, no field in that frame selected. */
423   cf->current_frame = NULL;
424   cf->current_row = 0;
425   cf->finfo_selected = NULL;
426
427   /* Clear the packet list. */
428   new_packet_list_freeze();
429   new_packet_list_clear();
430   new_packet_list_thaw();
431
432   cf->f_datalen = 0;
433   cf->count = 0;
434   nstime_set_zero(&cf->elapsed_time);
435
436   reset_tap_listeners();
437
438   /* We have no file open. */
439   cf->state = FILE_CLOSED;
440
441   fileset_file_closed();
442 }
443
444 /* Reset everything to a pristine state */
445 void
446 cf_close(capture_file *cf)
447 {
448   /* do GUI things even if file is already closed,
449    * e.g. to cleanup things if a capture couldn't be started */
450   cf_callback_invoke(cf_cb_file_closing, cf);
451
452   /* close things, if not already closed before */
453   if(cf->state != FILE_CLOSED) {
454     color_filters_cleanup();
455     cf_reset_state(cf);
456     cleanup_dissection();
457   }
458
459   cf_callback_invoke(cf_cb_file_closed, cf);
460 }
461
462 /* an out of memory exception occured, wait for a user button press to exit */
463 static void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
464 {
465     main_window_exit();
466 }
467
468 static float
469 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
470 {
471   float   progbar_val;
472
473   progbar_val = (gfloat) file_pos / (gfloat) size;
474   if (progbar_val > 1.0) {
475
476     /*  The file probably grew while we were reading it.
477      *  Update file size, and try again.
478      */
479     size = wtap_file_size(cf->wth, NULL);
480
481     /*  Another possibility is that we're reading a compressed file and we've
482      *  read more (uncompressed) data from the file than exists in the
483      *  (compressed) file.  So check how much data we've actually read.
484      *
485      *  This is inside this "if val > 1.0" check to avoid the lseek() when
486      *  reading uncompressed files.  Testing has (thus far) shown no progress
487      *  bar weirdness resulting from switching from the data offset (when
488      *  reading the first part of the file) to the real file position.
489      */
490     file_pos = wtap_read_so_far(cf->wth, NULL);
491
492     if (size >= 0)
493       progbar_val = (gfloat) file_pos / (gfloat) size;
494
495     /*  If it's still > 1, either "wtap_file_size()" failed (in which
496      *  case there's not much we can do about it), or the file
497      *  *shrank* (in which case there's not much we can do about
498      *  it); just clip the progress value at 1.0.
499      */
500     if (progbar_val > 1.0f)
501       progbar_val = 1.0f;
502   }
503
504   g_snprintf(status_str, status_size,
505              "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
506              file_pos / 1024, size / 1024);
507
508   return progbar_val;
509 }
510
511 cf_read_status_t
512 cf_read(capture_file *cf, gboolean from_save)
513 {
514   int         err;
515   gchar       *err_info;
516   const gchar *name_ptr;
517   const char  *errmsg;
518   char         errmsg_errno[1024+1];
519   gint64       data_offset;
520   progdlg_t *volatile progbar = NULL;
521   gboolean     stop_flag;
522   volatile gint64 size;
523   volatile float progbar_val;
524   GTimeVal     start_time;
525   gchar        status_str[100];
526   volatile gint64 progbar_nextstep;
527   volatile gint64 progbar_quantum;
528   dfilter_t   *dfcode;
529   gboolean    filtering_tap_listeners;
530   guint       tap_flags;
531   volatile int count = 0;
532 #ifdef HAVE_LIBPCAP
533   volatile int displayed_once = 0;
534 #endif
535   gboolean compiled;
536
537   /* Compile the current display filter.
538    * We assume this will not fail since cf->dfilter is only set in
539    * cf_filter IFF the filter was valid.
540    */
541   compiled = dfilter_compile(cf->dfilter, &dfcode);
542   g_assert(!cf->dfilter || (compiled && dfcode));
543
544   /* Do we have any tap listeners with filters? */
545   filtering_tap_listeners = have_filtering_tap_listeners();
546
547   /* Get the union of the flags for all tap listeners. */
548   tap_flags = union_of_tap_listener_flags();
549
550   reset_tap_listeners();
551
552   name_ptr = get_basename(cf->filename);
553
554   if (from_save == FALSE)
555     cf_callback_invoke(cf_cb_file_read_started, cf);
556   else
557     cf_callback_invoke(cf_cb_file_save_started, (gpointer)name_ptr);
558
559   /* Find the size of the file. */
560   size = wtap_file_size(cf->wth, NULL);
561
562   /* Update the progress bar when it gets to this value. */
563   progbar_nextstep = 0;
564   /* When we reach the value that triggers a progress bar update,
565      bump that value by this amount. */
566   if (size >= 0){
567     progbar_quantum = size/N_PROGBAR_UPDATES;
568     if (progbar_quantum < MIN_QUANTUM)
569       progbar_quantum = MIN_QUANTUM;
570   }else
571     progbar_quantum = 0;
572   /* Progress so far. */
573   progbar_val = 0.0f;
574
575   new_packet_list_freeze();
576
577   stop_flag = FALSE;
578   g_get_current_time(&start_time);
579
580   while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
581     if (size >= 0) {
582       count++;
583       /* Create the progress bar if necessary.
584        * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
585        */
586       if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
587         progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str));
588         if (from_save == FALSE)
589           progbar = delayed_create_progress_dlg("Loading", name_ptr,
590                                                 TRUE, &stop_flag, &start_time, progbar_val);
591         else
592           progbar = delayed_create_progress_dlg("Saving", name_ptr,
593                                                 TRUE, &stop_flag, &start_time, progbar_val);
594       }
595
596       /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
597          when we update it, we have to run the GTK+ main loop to get it
598          to repaint what's pending, and doing so may involve an "ioctl()"
599          to see if there's any pending input from an X server, and doing
600          that for every packet can be costly, especially on a big file. */
601       if (data_offset >= progbar_nextstep) {
602         if (progbar != NULL) {
603           progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str));
604           /* update the packet lists content on the first run or frequently on very large files */
605           /* (on smaller files the display update takes longer than reading the file) */
606 #ifdef HAVE_LIBPCAP
607           if (progbar_quantum > 500000 || displayed_once == 0) {
608             if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) {
609               displayed_once = 1;
610               new_packet_list_thaw();
611               if (auto_scroll_live)
612                 new_packet_list_moveto_end();
613               new_packet_list_freeze();
614             }
615           }
616 #endif /* HAVE_LIBPCAP */
617           update_progress_dlg(progbar, progbar_val, status_str);
618         }
619         progbar_nextstep += progbar_quantum;
620       }
621     }
622
623     if (stop_flag) {
624       /* Well, the user decided to abort the read. He/She will be warned and
625          it might be enough for him/her to work with the already loaded
626          packets.
627          This is especially true for very large capture files, where you don't
628          want to wait loading the whole file (which may last minutes or even
629          hours even on fast machines) just to see that it was the wrong file. */
630       break;
631     }
632     TRY {
633       read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
634     }
635     CATCH(OutOfMemoryError) {
636       gpointer dialog;
637
638       dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
639                              "%sOut Of Memory!%s\n"
640                              "\n"
641                              "Sorry, but Wireshark has to terminate now!\n"
642                              "\n"
643                              "Some infos / workarounds can be found at:\n"
644                              "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
645                              simple_dialog_primary_start(), simple_dialog_primary_end());
646       /* we have to terminate, as we cannot recover from the memory error */
647       simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
648       while(1) {
649         main_window_update();
650         /* XXX - how to avoid a busy wait? */
651         /* Sleep(100); */
652       };
653       break;
654     }
655     ENDTRY;
656   }
657
658   /* Cleanup and release all dfilter resources */
659   if (dfcode != NULL){
660     dfilter_free(dfcode);
661   }
662
663   /* We're done reading the file; destroy the progress bar if it was created. */
664   if (progbar != NULL)
665     destroy_progress_dlg(progbar);
666
667   /* We're done reading sequentially through the file. */
668   cf->state = FILE_READ_DONE;
669
670   /* Close the sequential I/O side, to free up memory it requires. */
671   wtap_sequential_close(cf->wth);
672
673   /* Allow the protocol dissectors to free up memory that they
674    * don't need after the sequential run-through of the packets. */
675   postseq_cleanup_all_protocols();
676
677   /* compute the time it took to load the file */
678   compute_elapsed(&start_time);
679
680   /* Set the file encapsulation type now; we don't know what it is until
681      we've looked at all the packets, as we don't know until then whether
682      there's more than one type (and thus whether it's
683      WTAP_ENCAP_PER_PACKET). */
684   cf->lnk_t = wtap_file_encap(cf->wth);
685
686   cf->current_frame = cf->first_displayed;
687   cf->current_row = 0;
688
689   new_packet_list_thaw();
690   if (from_save == FALSE)
691     cf_callback_invoke(cf_cb_file_read_finished, cf);
692   else
693     cf_callback_invoke(cf_cb_file_save_finished, cf);
694
695   /* If we have any displayed packets to select, select the first of those
696      packets by making the first row the selected row. */
697   if (cf->first_displayed != NULL){
698     new_packet_list_select_first_row();
699   }
700
701   if(stop_flag) {
702     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
703                   "%sFile loading was cancelled!%s\n"
704                   "\n"
705                   "The remaining packets in the file were discarded.\n"
706                   "\n"
707                   "As a lot of packets from the original file will be missing,\n"
708                   "remember to be careful when saving the current content to a file.\n",
709                   simple_dialog_primary_start(), simple_dialog_primary_end());
710     return CF_READ_ERROR;
711   }
712
713   if (err != 0) {
714     /* Put up a message box noting that the read failed somewhere along
715        the line.  Don't throw out the stuff we managed to read, though,
716        if any. */
717     switch (err) {
718
719     case WTAP_ERR_UNSUPPORTED_ENCAP:
720       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
721                  "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
722                  err_info);
723       g_free(err_info);
724       errmsg = errmsg_errno;
725       break;
726
727     case WTAP_ERR_CANT_READ:
728       errmsg = "An attempt to read from the capture file failed for"
729         " some unknown reason.";
730       break;
731
732     case WTAP_ERR_SHORT_READ:
733       errmsg = "The capture file appears to have been cut short"
734         " in the middle of a packet.";
735       break;
736
737     case WTAP_ERR_BAD_RECORD:
738       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
739                  "The capture file appears to be damaged or corrupt.\n(%s)",
740                  err_info);
741       g_free(err_info);
742       errmsg = errmsg_errno;
743       break;
744
745     default:
746       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
747                  "An error occurred while reading the"
748                  " capture file: %s.", wtap_strerror(err));
749       errmsg = errmsg_errno;
750       break;
751     }
752     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
753     return CF_READ_ERROR;
754   } else
755     return CF_READ_OK;
756 }
757
758 #ifdef HAVE_LIBPCAP
759 cf_status_t
760 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
761 {
762   cf_status_t cf_status;
763
764   cf_status = cf_open(cf, fname, is_tempfile, err);
765   return cf_status;
766 }
767
768 cf_read_status_t
769 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
770 {
771   gint64 data_offset = 0;
772   gchar *err_info;
773   volatile int newly_displayed_packets = 0;
774   dfilter_t   *dfcode;
775   gboolean filtering_tap_listeners;
776   guint tap_flags;
777   gboolean compiled;
778
779   /* Compile the current display filter.
780    * We assume this will not fail since cf->dfilter is only set in
781    * cf_filter IFF the filter was valid.
782    */
783   compiled = dfilter_compile(cf->dfilter, &dfcode);
784   g_assert(!cf->dfilter || (compiled && dfcode));
785
786   /* Do we have any tap listeners with filters? */
787   filtering_tap_listeners = have_filtering_tap_listeners();
788
789   /* Get the union of the flags for all tap listeners. */
790   tap_flags = union_of_tap_listener_flags();
791
792   *err = 0;
793
794   new_packet_list_check_end();
795   /* Don't freeze/thaw the list when doing live capture */
796   /*new_packet_list_freeze();*/
797
798   /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
799
800   while (to_read != 0) {
801     wtap_cleareof(cf->wth);
802     if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
803       break;
804     }
805     if (cf->state == FILE_READ_ABORTED) {
806       /* Well, the user decided to exit Wireshark.  Break out of the
807          loop, and let the code below (which is called even if there
808          aren't any packets left to read) exit. */
809       break;
810     }
811     TRY{
812       if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
813                       data_offset) != -1) {
814         newly_displayed_packets++;
815       }
816     }
817     CATCH(OutOfMemoryError) {
818       gpointer dialog;
819
820       dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
821                              "%sOut Of Memory!%s\n"
822                              "\n"
823                              "Sorry, but Wireshark has to terminate now!\n"
824                              "\n"
825                              "The capture file is not lost, it can be found at:\n"
826                              "%s\n"
827                              "\n"
828                              "Some infos / workarounds can be found at:\n"
829                              "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
830                              simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
831       /* we have to terminate, as we cannot recover from the memory error */
832       simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
833       while(1) {
834         main_window_update();
835         /* XXX - how to avoid a busy wait? */
836         /* Sleep(100); */
837       };
838       /* Don't freeze/thaw the list when doing live capture */
839       /*new_packet_list_thaw();*/
840       return CF_READ_ABORTED;
841     }
842     ENDTRY;
843     to_read--;
844   }
845
846   /* Cleanup and release all dfilter resources */
847   if (dfcode != NULL){
848     dfilter_free(dfcode);
849   }
850
851   /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
852     cf->count, cf->state, *err);*/
853
854   /* Don't freeze/thaw the list when doing live capture */
855   /*new_packet_list_thaw();*/
856   /* With the new packet list the first packet
857    * isn't automatically selected.
858    */
859   if(!cf->current_frame)
860     new_packet_list_select_first_row();
861
862   /* moving to the end of the packet list - if the user requested so and
863      we have some new packets. */
864   if (newly_displayed_packets && auto_scroll_live && cf->plist_end != NULL)
865       new_packet_list_moveto_end();
866
867   if (cf->state == FILE_READ_ABORTED) {
868     /* Well, the user decided to exit Wireshark.  Return CF_READ_ABORTED
869        so that our caller can kill off the capture child process;
870        this will cause an EOF on the pipe from the child, so
871        "cf_finish_tail()" will be called, and it will clean up
872        and exit. */
873     return CF_READ_ABORTED;
874   } else if (*err != 0) {
875     /* We got an error reading the capture file.
876        XXX - pop up a dialog box instead? */
877     g_warning("Error \"%s\" while reading: \"%s\"\n",
878         wtap_strerror(*err), cf->filename);
879
880     return CF_READ_ERROR;
881   } else
882     return CF_READ_OK;
883 }
884
885 void
886 cf_fake_continue_tail(capture_file *cf) {
887   cf->state = FILE_READ_DONE;
888 }
889
890 cf_read_status_t
891 cf_finish_tail(capture_file *cf, int *err)
892 {
893   gchar *err_info;
894   gint64 data_offset;
895   dfilter_t   *dfcode;
896   gboolean filtering_tap_listeners;
897   guint tap_flags;
898   gboolean compiled;
899
900   /* Compile the current display filter.
901    * We assume this will not fail since cf->dfilter is only set in
902    * cf_filter IFF the filter was valid.
903    */
904   compiled = dfilter_compile(cf->dfilter, &dfcode);
905   g_assert(!cf->dfilter || (compiled && dfcode));
906
907   /* Do we have any tap listeners with filters? */
908   filtering_tap_listeners = have_filtering_tap_listeners();
909
910   /* Get the union of the flags for all tap listeners. */
911   tap_flags = union_of_tap_listener_flags();
912
913   if(cf->wth == NULL) {
914     cf_close(cf);
915     return CF_READ_ERROR;
916   }
917
918   new_packet_list_check_end();
919   /* Don't freeze/thaw the list when doing live capture */
920   /*new_packet_list_freeze();*/
921
922   while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
923     if (cf->state == FILE_READ_ABORTED) {
924       /* Well, the user decided to abort the read.  Break out of the
925          loop, and let the code below (which is called even if there
926      aren't any packets left to read) exit. */
927       break;
928     }
929     read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
930   }
931
932   /* Cleanup and release all dfilter resources */
933   if (dfcode != NULL){
934     dfilter_free(dfcode);
935   }
936
937   /* Don't freeze/thaw the list when doing live capture */
938   /*new_packet_list_thaw();*/
939
940   if (cf->state == FILE_READ_ABORTED) {
941     /* Well, the user decided to abort the read.  We're only called
942        when the child capture process closes the pipe to us (meaning
943        it's probably exited), so we can just close the capture
944        file; we return CF_READ_ABORTED so our caller can do whatever
945        is appropriate when that happens. */
946     cf_close(cf);
947     return CF_READ_ABORTED;
948   }
949
950   if (auto_scroll_live && cf->plist_end != NULL)
951     new_packet_list_moveto_end();
952
953   /* We're done reading sequentially through the file. */
954   cf->state = FILE_READ_DONE;
955
956   /* We're done reading sequentially through the file; close the
957      sequential I/O side, to free up memory it requires. */
958   wtap_sequential_close(cf->wth);
959
960   /* Allow the protocol dissectors to free up memory that they
961    * don't need after the sequential run-through of the packets. */
962   postseq_cleanup_all_protocols();
963
964   /* Set the file encapsulation type now; we don't know what it is until
965      we've looked at all the packets, as we don't know until then whether
966      there's more than one type (and thus whether it's
967      WTAP_ENCAP_PER_PACKET). */
968   cf->lnk_t = wtap_file_encap(cf->wth);
969
970   if (*err != 0) {
971     /* We got an error reading the capture file.
972        XXX - pop up a dialog box? */
973     return CF_READ_ERROR;
974   } else {
975     return CF_READ_OK;
976   }
977 }
978 #endif /* HAVE_LIBPCAP */
979
980 const gchar *
981 cf_get_display_name(capture_file *cf)
982 {
983   const gchar *displayname;
984
985   /* Return a name to use in displays */
986   if (!cf->is_tempfile) {
987     /* Get the last component of the file name, and use that. */
988     if (cf->filename){
989       displayname = get_basename(cf->filename);
990     } else {
991       displayname="(No file)";
992     }
993   } else {
994     /* The file we read is a temporary file from a live capture;
995        we don't mention its name. */
996     if (cf->source) {
997       displayname = cf->source;
998     } else {
999       displayname = "(Untitled)";
1000     }
1001   }
1002   return displayname;
1003 }
1004
1005 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1006   if (cf->source) {
1007     g_free(cf->source);
1008   }
1009
1010   if (source) {
1011     cf->source = g_strdup(source);
1012   } else {
1013     cf->source = g_strdup("");
1014   }
1015 }
1016
1017 const gchar *cf_get_tempfile_source(capture_file *cf) {
1018   if (!cf->source) {
1019     return "";
1020   }
1021
1022   return cf->source;
1023 }
1024
1025 /* XXX - use a macro instead? */
1026 int
1027 cf_get_packet_count(capture_file *cf)
1028 {
1029   return cf->count;
1030 }
1031
1032 /* XXX - use a macro instead? */
1033 void
1034 cf_set_packet_count(capture_file *cf, int packet_count)
1035 {
1036   cf->count = packet_count;
1037 }
1038
1039 /* XXX - use a macro instead? */
1040 gboolean
1041 cf_is_tempfile(capture_file *cf)
1042 {
1043   return cf->is_tempfile;
1044 }
1045
1046 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1047 {
1048   cf->is_tempfile = is_tempfile;
1049 }
1050
1051
1052 /* XXX - use a macro instead? */
1053 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1054 {
1055   cf->drops_known = drops_known;
1056 }
1057
1058 /* XXX - use a macro instead? */
1059 void cf_set_drops(capture_file *cf, guint32 drops)
1060 {
1061   cf->drops = drops;
1062 }
1063
1064 /* XXX - use a macro instead? */
1065 gboolean cf_get_drops_known(capture_file *cf)
1066 {
1067   return cf->drops_known;
1068 }
1069
1070 /* XXX - use a macro instead? */
1071 guint32 cf_get_drops(capture_file *cf)
1072 {
1073   return cf->drops;
1074 }
1075
1076 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1077 {
1078   cf->rfcode = rfcode;
1079 }
1080
1081 static int
1082 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1083     dfilter_t *dfcode, gboolean filtering_tap_listeners,
1084     guint tap_flags,
1085     union wtap_pseudo_header *pseudo_header, const guchar *buf,
1086     gboolean refilter,
1087     gboolean add_to_packet_list)
1088 {
1089   gboolean  create_proto_tree = FALSE;
1090   epan_dissect_t edt;
1091   column_info *cinfo;
1092   gint row = -1;
1093
1094   cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1095
1096   frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1097                                 &first_ts, &prev_dis_ts, &prev_cap_ts);
1098
1099   /* If either
1100     + we have a display filter and are re-applying it;
1101     + we have tap listeners with filters;
1102     + we have tap listeners that require a protocol tree;
1103
1104      allocate a protocol tree root node, so that we'll construct
1105      a protocol tree against which a filter expression can be
1106      evaluated. */
1107   if ((dfcode != NULL && refilter) ||
1108       filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1109       create_proto_tree = TRUE;
1110
1111   /* Dissect the frame. */
1112   epan_dissect_init(&edt, create_proto_tree, FALSE);
1113
1114   if (dfcode != NULL && refilter) {
1115       epan_dissect_prime_dfilter(&edt, dfcode);
1116   }
1117
1118   tap_queue_init(&edt);
1119   epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1120   tap_push_tapped_queue(&edt);
1121
1122   /* If we have a display filter, apply it if we're refiltering, otherwise
1123      leave the "passed_dfilter" flag alone.
1124
1125      If we don't have a display filter, set "passed_dfilter" to 1. */
1126   if (dfcode != NULL) {
1127     if (refilter) {
1128       fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1129     }
1130   } else
1131     fdata->flags.passed_dfilter = 1;
1132
1133   if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1134     cf->displayed_count++;
1135
1136   if (add_to_packet_list) {
1137     /* We fill the needed columns from new_packet_list */
1138       row = new_packet_list_append(cinfo, fdata, &edt.pi);
1139   }
1140
1141   if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1142   {
1143     frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
1144
1145     /* If we haven't yet seen the first frame, this is it.
1146
1147        XXX - we must do this before we add the row to the display,
1148        as, if the display's GtkCList's selection mode is
1149        GTK_SELECTION_BROWSE, when the first entry is added to it,
1150        "cf_select_packet()" will be called, and it will fetch the row
1151        data for the 0th row, and will get a null pointer rather than
1152        "fdata", as "gtk_clist_append()" won't yet have returned and
1153        thus "gtk_clist_set_row_data()" won't yet have been called.
1154
1155        We thus need to leave behind bread crumbs so that
1156        "cf_select_packet()" can find this frame.  See the comment
1157        in "cf_select_packet()". */
1158     if (cf->first_displayed == NULL)
1159       cf->first_displayed = fdata;
1160
1161     /* This is the last frame we've seen so far. */
1162     cf->last_displayed = fdata;
1163   }
1164
1165   epan_dissect_cleanup(&edt);
1166   return row;
1167 }
1168
1169 /*
1170  * Initialize the col_text and col_text_len arrays.
1171  */
1172 static void
1173 init_col_text(frame_data *fdata, gint num_cols)
1174 {
1175   fdata->col_text_len = se_alloc0(sizeof(*fdata->col_text_len) * num_cols);
1176   fdata->col_text = se_alloc0(sizeof(*fdata->col_text) * num_cols);
1177 }
1178
1179 /* read in a new packet */
1180 /* returns the row of the new packet in the packet list or -1 if not displayed */
1181 static int
1182 read_packet(capture_file *cf, dfilter_t *dfcode,
1183             gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
1184 {
1185   const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1186   union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1187   const guchar *buf = wtap_buf_ptr(cf->wth);
1188   frame_data   *fdata;
1189   int           passed;
1190   int           row = -1;
1191
1192   cf->count++;
1193
1194   /* Allocate the next list entry, and add it to the list.
1195    * memory chunks have been deprecated in favor of the slice allocator,
1196    * which has been added in 2.10
1197    */
1198 #if GLIB_CHECK_VERSION(2,10,0)
1199   fdata = g_slice_new(frame_data);
1200 #else
1201   fdata = g_mem_chunk_alloc(cf->plist_chunk);
1202 #endif
1203
1204   frame_data_init(fdata, cf->count, phdr, offset, cum_bytes);
1205   init_col_text(fdata, cf->cinfo.num_cols);
1206
1207   passed = TRUE;
1208   if (cf->rfcode) {
1209     epan_dissect_t edt;
1210     epan_dissect_init(&edt, TRUE, FALSE);
1211     epan_dissect_prime_dfilter(&edt, cf->rfcode);
1212     epan_dissect_run(&edt, pseudo_header, buf, fdata, NULL);
1213     passed = dfilter_apply_edt(cf->rfcode, &edt);
1214     epan_dissect_cleanup(&edt);
1215   }
1216
1217   if (passed) {
1218     cap_file_add_fdata(cf, fdata);
1219
1220     cf->f_datalen = offset + fdata->cap_len;
1221
1222     if (!cf->redissecting) {
1223       row = add_packet_to_packet_list(fdata, cf, dfcode,
1224                                       filtering_tap_listeners, tap_flags,
1225                                       pseudo_header, buf, TRUE, TRUE);
1226     }
1227   } else {
1228     /* We didn't pass read filter so roll back count */
1229     cf->count--;
1230
1231     /* XXX - if we didn't have read filters, or if we could avoid
1232        allocating the "frame_data" structure until we knew whether
1233        the frame passed the read filter, we could use a G_ALLOC_ONLY
1234        memory chunk...
1235
1236        ...but, at least in one test I did, where I just made the chunk
1237        a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
1238        seem to save a noticeable amount of time or space. */
1239 #if GLIB_CHECK_VERSION(2,10,0)
1240   /* memory chunks have been deprecated in favor of the slice allocator,
1241    * which has been added in 2.10
1242    */
1243     g_slice_free(frame_data,fdata);
1244 #else
1245     g_mem_chunk_free(cf->plist_chunk, fdata);
1246 #endif
1247   }
1248
1249   return row;
1250 }
1251
1252 cf_status_t
1253 cf_merge_files(char **out_filenamep, int in_file_count,
1254                char *const *in_filenames, int file_type, gboolean do_append)
1255 {
1256   merge_in_file_t  *in_files;
1257   wtap             *wth;
1258   char             *out_filename;
1259   char             *tmpname;
1260   int               out_fd;
1261   wtap_dumper      *pdh;
1262   int               open_err, read_err, write_err, close_err;
1263   gchar            *err_info;
1264   int               err_fileno;
1265   int               i;
1266   char              errmsg_errno[1024+1];
1267   const char       *errmsg;
1268   gboolean          got_read_error = FALSE, got_write_error = FALSE;
1269   gint64            data_offset;
1270   progdlg_t        *progbar = NULL;
1271   gboolean          stop_flag;
1272   gint64            f_len, file_pos;
1273   float             progbar_val;
1274   GTimeVal          start_time;
1275   gchar             status_str[100];
1276   gint64            progbar_nextstep;
1277   gint64            progbar_quantum;
1278
1279   /* open the input files */
1280   if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1281                            &open_err, &err_info, &err_fileno)) {
1282     g_free(in_files);
1283     cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1284                               FALSE, 0);
1285     return CF_ERROR;
1286   }
1287
1288   if (*out_filenamep != NULL) {
1289     out_filename = *out_filenamep;
1290     out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1291     if (out_fd == -1)
1292       open_err = errno;
1293   } else {
1294     out_fd = create_tempfile(&tmpname, "wireshark");
1295     if (out_fd == -1)
1296       open_err = errno;
1297     out_filename = g_strdup(tmpname);
1298     *out_filenamep = out_filename;
1299   }
1300   if (out_fd == -1) {
1301     err_info = NULL;
1302     merge_close_in_files(in_file_count, in_files);
1303     g_free(in_files);
1304     cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1305     return CF_ERROR;
1306   }
1307
1308   pdh = wtap_dump_fdopen(out_fd, file_type,
1309       merge_select_frame_type(in_file_count, in_files),
1310       merge_max_snapshot_length(in_file_count, in_files),
1311       FALSE /* compressed */, &open_err);
1312   if (pdh == NULL) {
1313     ws_close(out_fd);
1314     merge_close_in_files(in_file_count, in_files);
1315     g_free(in_files);
1316     cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1317                               file_type);
1318     return CF_ERROR;
1319   }
1320
1321   /* Get the sum of the sizes of all the files. */
1322   f_len = 0;
1323   for (i = 0; i < in_file_count; i++)
1324     f_len += in_files[i].size;
1325
1326   /* Update the progress bar when it gets to this value. */
1327   progbar_nextstep = 0;
1328   /* When we reach the value that triggers a progress bar update,
1329      bump that value by this amount. */
1330   progbar_quantum = f_len/N_PROGBAR_UPDATES;
1331   /* Progress so far. */
1332   progbar_val = 0.0f;
1333
1334   stop_flag = FALSE;
1335   g_get_current_time(&start_time);
1336
1337   /* do the merge (or append) */
1338   for (;;) {
1339     if (do_append)
1340       wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1341                                      &err_info);
1342     else
1343       wth = merge_read_packet(in_file_count, in_files, &read_err,
1344                               &err_info);
1345     if (wth == NULL) {
1346       if (read_err != 0)
1347         got_read_error = TRUE;
1348       break;
1349     }
1350
1351     /* Get the sum of the data offsets in all of the files. */
1352     data_offset = 0;
1353     for (i = 0; i < in_file_count; i++)
1354       data_offset += in_files[i].data_offset;
1355
1356     /* Create the progress bar if necessary.
1357        We check on every iteration of the loop, so that it takes no
1358        longer than the standard time to create it (otherwise, for a
1359        large file, we might take considerably longer than that standard
1360        time in order to get to the next progress bar step). */
1361     if (progbar == NULL) {
1362       progbar = delayed_create_progress_dlg("Merging", "files",
1363         FALSE, &stop_flag, &start_time, progbar_val);
1364     }
1365
1366     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1367        when we update it, we have to run the GTK+ main loop to get it
1368        to repaint what's pending, and doing so may involve an "ioctl()"
1369        to see if there's any pending input from an X server, and doing
1370        that for every packet can be costly, especially on a big file. */
1371     if (data_offset >= progbar_nextstep) {
1372         /* Get the sum of the seek positions in all of the files. */
1373         file_pos = 0;
1374         for (i = 0; i < in_file_count; i++)
1375           file_pos += wtap_read_so_far(in_files[i].wth, NULL);
1376         progbar_val = (gfloat) file_pos / (gfloat) f_len;
1377         if (progbar_val > 1.0f) {
1378           /* Some file probably grew while we were reading it.
1379              That "shouldn't happen", so we'll just clip the progress
1380              value at 1.0. */
1381           progbar_val = 1.0f;
1382         }
1383         if (progbar != NULL) {
1384           g_snprintf(status_str, sizeof(status_str),
1385                      "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1386                      file_pos / 1024, f_len / 1024);
1387           update_progress_dlg(progbar, progbar_val, status_str);
1388         }
1389         progbar_nextstep += progbar_quantum;
1390     }
1391
1392     if (stop_flag) {
1393       /* Well, the user decided to abort the merge. */
1394       break;
1395     }
1396
1397     if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1398          wtap_buf_ptr(wth), &write_err)) {
1399       got_write_error = TRUE;
1400       break;
1401     }
1402   }
1403
1404   /* We're done merging the files; destroy the progress bar if it was created. */
1405   if (progbar != NULL)
1406     destroy_progress_dlg(progbar);
1407
1408   merge_close_in_files(in_file_count, in_files);
1409   if (!got_read_error && !got_write_error) {
1410     if (!wtap_dump_close(pdh, &write_err))
1411       got_write_error = TRUE;
1412   } else
1413     wtap_dump_close(pdh, &close_err);
1414
1415   if (got_read_error) {
1416     /*
1417      * Find the file on which we got the error, and report the error.
1418      */
1419     for (i = 0; i < in_file_count; i++) {
1420       if (in_files[i].state == GOT_ERROR) {
1421     /* Put up a message box noting that a read failed somewhere along
1422        the line. */
1423     switch (read_err) {
1424
1425     case WTAP_ERR_UNSUPPORTED_ENCAP:
1426       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1427            "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1428            err_info);
1429       g_free(err_info);
1430       errmsg = errmsg_errno;
1431       break;
1432
1433     case WTAP_ERR_CANT_READ:
1434       errmsg = "An attempt to read from the capture file %s failed for"
1435            " some unknown reason.";
1436       break;
1437
1438     case WTAP_ERR_SHORT_READ:
1439       errmsg = "The capture file %s appears to have been cut short"
1440            " in the middle of a packet.";
1441       break;
1442
1443     case WTAP_ERR_BAD_RECORD:
1444       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1445            "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1446            err_info);
1447       g_free(err_info);
1448       errmsg = errmsg_errno;
1449       break;
1450
1451     default:
1452       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1453            "An error occurred while reading the"
1454            " capture file %%s: %s.", wtap_strerror(read_err));
1455       errmsg = errmsg_errno;
1456       break;
1457     }
1458         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
1459       }
1460     }
1461   }
1462
1463   if (got_write_error) {
1464     /* Put up an alert box for the write error. */
1465     cf_write_failure_alert_box(out_filename, write_err);
1466   }
1467
1468   if (got_read_error || got_write_error || stop_flag) {
1469     /* Callers aren't expected to treat an error or an explicit abort
1470        differently - we put up error dialogs ourselves, so they don't
1471        have to. */
1472     return CF_ERROR;
1473   } else
1474     return CF_OK;
1475 }
1476
1477 cf_status_t
1478 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1479 {
1480   const char *filter_new = dftext ? dftext : "";
1481   const char *filter_old = cf->dfilter ? cf->dfilter : "";
1482   dfilter_t   *dfcode;
1483   GTimeVal     start_time;
1484
1485   /* if new filter equals old one, do nothing unless told to do so */
1486   if (!force && strcmp(filter_new, filter_old) == 0) {
1487     return CF_OK;
1488   }
1489
1490   dfcode=NULL;
1491
1492   if (dftext == NULL) {
1493     /* The new filter is an empty filter (i.e., display all packets).
1494      * so leave dfcode==NULL
1495      */
1496   } else {
1497     /*
1498      * We have a filter; make a copy of it (as we'll be saving it),
1499      * and try to compile it.
1500      */
1501     dftext = g_strdup(dftext);
1502     if (!dfilter_compile(dftext, &dfcode)) {
1503       /* The attempt failed; report an error. */
1504       gchar *safe_dftext = simple_dialog_format_message(dftext);
1505       gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1506       dfilter_error_msg);
1507       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1508           "%s%s%s\n"
1509           "\n"
1510           "The following display filter isn't a valid display filter:\n%s\n"
1511           "See the help for a description of the display filter syntax.",
1512           simple_dialog_primary_start(), safe_dfilter_error_msg,
1513           simple_dialog_primary_end(), safe_dftext);
1514       g_free(safe_dfilter_error_msg);
1515       g_free(safe_dftext);
1516       g_free(dftext);
1517       return CF_ERROR;
1518     }
1519
1520     /* Was it empty? */
1521     if (dfcode == NULL) {
1522       /* Yes - free the filter text, and set it to null. */
1523       g_free(dftext);
1524       dftext = NULL;
1525     }
1526   }
1527
1528   /* We have a valid filter.  Replace the current filter. */
1529   g_free(cf->dfilter);
1530   cf->dfilter = dftext;
1531   g_get_current_time(&start_time);
1532
1533
1534   /* Now rescan the packet list, applying the new filter, but not
1535      throwing away information constructed on a previous pass. */
1536   if (dftext == NULL) {
1537     rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1538   } else {
1539     rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1540   }
1541
1542   /* Cleanup and release all dfilter resources */
1543   dfilter_free(dfcode);
1544
1545   return CF_OK;
1546 }
1547
1548 void
1549 cf_reftime_packets(capture_file *cf)
1550 {
1551
1552   ref_time_packets(cf);
1553 }
1554
1555 void
1556 cf_redissect_packets(capture_file *cf)
1557 {
1558   rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1559 }
1560
1561 gboolean
1562 cf_read_frame_r(capture_file *cf, frame_data *fdata,
1563                 union wtap_pseudo_header *pseudo_header, guint8 *pd)
1564 {
1565   int err;
1566   gchar *err_info;
1567   char errmsg_errno[1024+1];
1568
1569   if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
1570                       fdata->cap_len, &err, &err_info)) {
1571     switch (err) {
1572
1573     case WTAP_ERR_UNSUPPORTED_ENCAP:
1574       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1575                  "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
1576                  err_info);
1577       g_free(err_info);
1578       break;
1579
1580     case WTAP_ERR_BAD_RECORD:
1581       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1582                  "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
1583                  wtap_strerror(err), err_info);
1584       g_free(err_info);
1585       break;
1586
1587     default:
1588       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1589                  "An error occurred while reading from the file \"%%s\": %s.",
1590                  wtap_strerror(err));
1591       break;
1592     }
1593     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg_errno, cf->filename);
1594     return FALSE;
1595   }
1596   return TRUE;
1597 }
1598
1599 gboolean
1600 cf_read_frame(capture_file *cf, frame_data *fdata)
1601 {
1602   return cf_read_frame_r(cf, fdata, &cf->pseudo_header, cf->pd);
1603 }
1604
1605 /* Rescan the list of packets, reconstructing the CList.
1606
1607    "action" describes why we're doing this; it's used in the progress
1608    dialog box.
1609
1610    "action_item" describes what we're doing; it's used in the progress
1611    dialog box.
1612
1613    "refilter" is TRUE if we need to re-evaluate the filter expression.
1614
1615    "redissect" is TRUE if we need to make the dissectors reconstruct
1616    any state information they have (because a preference that affects
1617    some dissector has changed, meaning some dissector might construct
1618    its state differently from the way it was constructed the last time). */
1619 static void
1620 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1621         gboolean refilter, gboolean redissect)
1622 {
1623     /* Rescan packets new packet list */
1624   frame_data *fdata;
1625   progdlg_t  *progbar = NULL;
1626   gboolean    stop_flag;
1627   int         count;
1628   frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1629   int         selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1630   gboolean    selected_frame_seen;
1631   float       progbar_val;
1632   GTimeVal    start_time;
1633   gchar       status_str[100];
1634   int         progbar_nextstep;
1635   int         progbar_quantum;
1636   dfilter_t   *dfcode;
1637   gboolean    filtering_tap_listeners;
1638   guint       tap_flags;
1639   gboolean    add_to_packet_list = FALSE;
1640   gboolean compiled;
1641
1642   /* Compile the current display filter.
1643    * We assume this will not fail since cf->dfilter is only set in
1644    * cf_filter IFF the filter was valid.
1645    */
1646   compiled = dfilter_compile(cf->dfilter, &dfcode);
1647   g_assert(!cf->dfilter || (compiled && dfcode));
1648
1649   /* Do we have any tap listeners with filters? */
1650   filtering_tap_listeners = have_filtering_tap_listeners();
1651
1652   /* Get the union of the flags for all tap listeners. */
1653   tap_flags = union_of_tap_listener_flags();
1654
1655   reset_tap_listeners();
1656   /* Which frame, if any, is the currently selected frame?
1657      XXX - should the selected frame or the focus frame be the "current"
1658      frame, that frame being the one from which "Find Frame" searches
1659      start? */
1660   selected_frame = cf->current_frame;
1661
1662   /* Mark frame num as not found */
1663   selected_frame_num = -1;
1664
1665   /* Freeze the packet list while we redo it, so we don't get any
1666      screen updates while it happens. */
1667   new_packet_list_freeze();
1668
1669   if (redissect) {
1670     /* We need to re-initialize all the state information that protocols
1671        keep, because some preference that controls a dissector has changed,
1672        which might cause the state information to be constructed differently
1673        by that dissector. */
1674
1675     /* We might receive new packets while redissecting, and we don't
1676        want to dissect those before their time. */
1677     cf->redissecting = TRUE;
1678
1679     /* Cleanup all data structures used for dissection. */
1680     cleanup_dissection();
1681     /* Initialize all data structures used for dissection. */
1682     init_dissection();
1683
1684     /* We need to redissect the packets so we have to discard our old
1685      * packet list store. */
1686     new_packet_list_clear();
1687     add_to_packet_list = TRUE;
1688   }
1689
1690   /* We don't yet know which will be the first and last frames displayed. */
1691   cf->first_displayed = NULL;
1692   cf->last_displayed = NULL;
1693
1694   /* We currently don't display any packets */
1695   cf->displayed_count = 0;
1696
1697   /* Iterate through the list of frames.  Call a routine for each frame
1698      to check whether it should be displayed and, if so, add it to
1699      the display list. */
1700   nstime_set_unset(&first_ts);
1701   nstime_set_unset(&prev_dis_ts);
1702   nstime_set_unset(&prev_cap_ts);
1703   cum_bytes = 0;
1704
1705   /* Update the progress bar when it gets to this value. */
1706   progbar_nextstep = 0;
1707   /* When we reach the value that triggers a progress bar update,
1708      bump that value by this amount. */
1709   progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1710   /* Count of packets at which we've looked. */
1711   count = 0;
1712   /* Progress so far. */
1713   progbar_val = 0.0f;
1714
1715   stop_flag = FALSE;
1716   g_get_current_time(&start_time);
1717
1718   /* no previous row yet */
1719   prev_frame_num = -1;
1720   prev_frame = NULL;
1721
1722   preceding_frame_num = -1;
1723   preceding_frame = NULL;
1724   following_frame_num = -1;
1725   following_frame = NULL;
1726
1727   selected_frame_seen = FALSE;
1728
1729   for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
1730     /* Create the progress bar if necessary.
1731        We check on every iteration of the loop, so that it takes no
1732        longer than the standard time to create it (otherwise, for a
1733        large file, we might take considerably longer than that standard
1734        time in order to get to the next progress bar step). */
1735     if (progbar == NULL)
1736       progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1737                                             &stop_flag, &start_time,
1738                                             progbar_val);
1739
1740     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1741        when we update it, we have to run the GTK+ main loop to get it
1742        to repaint what's pending, and doing so may involve an "ioctl()"
1743        to see if there's any pending input from an X server, and doing
1744        that for every packet can be costly, especially on a big file. */
1745     if (count >= progbar_nextstep) {
1746       /* let's not divide by zero. I should never be started
1747        * with count == 0, so let's assert that
1748        */
1749       g_assert(cf->count > 0);
1750       progbar_val = (gfloat) count / cf->count;
1751
1752       if (progbar != NULL) {
1753         g_snprintf(status_str, sizeof(status_str),
1754                   "%4u of %u frames", count, cf->count);
1755         update_progress_dlg(progbar, progbar_val, status_str);
1756       }
1757
1758       progbar_nextstep += progbar_quantum;
1759     }
1760
1761     if (stop_flag) {
1762       /* Well, the user decided to abort the filtering.  Just stop.
1763
1764          XXX - go back to the previous filter?  Users probably just
1765          want not to wait for a filtering operation to finish;
1766          unless we cancel by having no filter, reverting to the
1767          previous filter will probably be even more expensive than
1768          continuing the filtering, as it involves going back to the
1769          beginning and filtering, and even with no filter we currently
1770          have to re-generate the entire clist, which is also expensive.
1771
1772          I'm not sure what Network Monitor does, but it doesn't appear
1773          to give you an unfiltered display if you cancel. */
1774       break;
1775     }
1776
1777     count++;
1778
1779     if (redissect) {
1780       /* Since all state for the frame was destroyed, mark the frame
1781        * as not visited, free the GSList referring to the state
1782        * data (the per-frame data itself was freed by
1783        * "init_dissection()"), and null out the GSList pointer. */
1784       fdata->flags.visited = 0;
1785       frame_data_cleanup(fdata);
1786
1787       /* cleanup_dissection() calls se_free_all();
1788        * And after that fdata->col_text (which is allocated using se_alloc0())
1789        * no longer points to valid memory.
1790        */
1791       init_col_text(fdata, cf->cinfo.num_cols);
1792     }
1793
1794     if (!cf_read_frame(cf, fdata))
1795       break; /* error reading the frame */
1796
1797     /* If the previous frame is displayed, and we haven't yet seen the
1798        selected frame, remember that frame - it's the closest one we've
1799        yet seen before the selected frame. */
1800     if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1801       preceding_frame_num = prev_frame_num;
1802       preceding_frame = prev_frame;
1803     }
1804     add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1805                                     tap_flags, &cf->pseudo_header, cf->pd,
1806                                     refilter,
1807                                     add_to_packet_list);
1808
1809     /* If this frame is displayed, and this is the first frame we've
1810        seen displayed after the selected frame, remember this frame -
1811        it's the closest one we've yet seen at or after the selected
1812        frame. */
1813     if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1814       following_frame_num = fdata->num;
1815       following_frame = fdata;
1816     }
1817     if (fdata == selected_frame) {
1818       selected_frame_seen = TRUE;
1819       if (fdata->flags.passed_dfilter)
1820           selected_frame_num = fdata->num;
1821     }
1822
1823     /* Remember this frame - it'll be the previous frame
1824        on the next pass through the loop. */
1825     prev_frame_num = fdata->num;
1826     prev_frame = fdata;
1827   }
1828
1829   /* We are done redissecting the packet list. */
1830   cf->redissecting = FALSE;
1831
1832   if (redissect) {
1833     /* Clear out what remains of the visited flags and per-frame data
1834        pointers.
1835
1836        XXX - that may cause various forms of bogosity when dissecting
1837        these frames, as they won't have been seen by this sequential
1838        pass, but the only alternative I see is to keep scanning them
1839        even though the user requested that the scan stop, and that
1840        would leave the user stuck with an Wireshark grinding on
1841        until it finishes.  Should we just stick them with that? */
1842     for (; fdata != NULL; fdata = fdata->next) {
1843       fdata->flags.visited = 0;
1844       frame_data_cleanup(fdata);
1845     }
1846   }
1847
1848   /* We're done filtering the packets; destroy the progress bar if it
1849      was created. */
1850   if (progbar != NULL)
1851     destroy_progress_dlg(progbar);
1852
1853   /* Unfreeze the packet list. */
1854   if (!add_to_packet_list)
1855     new_packet_list_recreate_visible_rows();
1856
1857   /* Compute the time it took to filter the file */
1858   compute_elapsed(&start_time);
1859
1860   new_packet_list_thaw();
1861
1862   if (selected_frame_num == -1) {
1863     /* The selected frame didn't pass the filter. */
1864     if (selected_frame == NULL) {
1865       /* That's because there *was* no selected frame.  Make the first
1866          displayed frame the current frame. */
1867       selected_frame_num = 0;
1868     } else {
1869       /* Find the nearest displayed frame to the selected frame (whether
1870          it's before or after that frame) and make that the current frame.
1871          If the next and previous displayed frames are equidistant from the
1872          selected frame, choose the next one. */
1873       g_assert(following_frame == NULL ||
1874                following_frame->num >= selected_frame->num);
1875       g_assert(preceding_frame == NULL ||
1876                preceding_frame->num <= selected_frame->num);
1877       if (following_frame == NULL) {
1878         /* No frame after the selected frame passed the filter, so we
1879            have to select the last displayed frame before the selected
1880            frame. */
1881         selected_frame_num = preceding_frame_num;
1882         selected_frame = preceding_frame;
1883       } else if (preceding_frame == NULL) {
1884         /* No frame before the selected frame passed the filter, so we
1885            have to select the first displayed frame after the selected
1886            frame. */
1887         selected_frame_num = following_frame_num;
1888         selected_frame = following_frame;
1889       } else {
1890         /* Frames before and after the selected frame passed the filter, so
1891            we'll select the previous frame */
1892         selected_frame_num = preceding_frame_num;
1893         selected_frame = preceding_frame;
1894       }
1895     }
1896   }
1897
1898   if (selected_frame_num == -1) {
1899     /* There are no frames displayed at all. */
1900     cf_unselect_packet(cf);
1901   } else {
1902     /* Either the frame that was selected passed the filter, or we've
1903        found the nearest displayed frame to that frame.  Select it, make
1904        it the focus row, and make it visible. */
1905     /* Set to invalid to force update of packet list and packet details */
1906     cf->current_row = -1;
1907     if (selected_frame_num == 0) {
1908       new_packet_list_select_first_row();
1909     }else{
1910       new_packet_list_find_row_from_data(selected_frame, TRUE);
1911     }
1912   }
1913
1914   /* Cleanup and release all dfilter resources */
1915   dfilter_free(dfcode);
1916 }
1917
1918
1919 /*
1920  * Scan trough all frame data and recalculate the ref time
1921  * without rereading the file.
1922  * XXX - do we need a progres bar or is this fast enough?
1923  */
1924 static void
1925 ref_time_packets(capture_file *cf)
1926 {
1927   frame_data *fdata;
1928
1929   nstime_set_unset(&first_ts);
1930   nstime_set_unset(&prev_dis_ts);
1931   cum_bytes = 0;
1932
1933   for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
1934     /* just add some value here until we know if it is being displayed or not */
1935     fdata->cum_bytes = cum_bytes + fdata->pkt_len;
1936
1937     /*
1938      *Timestamps
1939      */
1940
1941     /* If we don't have the time stamp of the first packet in the
1942      capture, it's because this is the first packet.  Save the time
1943      stamp of this packet as the time stamp of the first packet. */
1944     if (nstime_is_unset(&first_ts)) {
1945         first_ts  = fdata->abs_ts;
1946     }
1947       /* if this frames is marked as a reference time frame, reset
1948         firstsec and firstusec to this frame */
1949     if(fdata->flags.ref_time){
1950         first_ts = fdata->abs_ts;
1951     }
1952
1953     /* If we don't have the time stamp of the previous displayed packet,
1954      it's because this is the first displayed packet.  Save the time
1955      stamp of this packet as the time stamp of the previous displayed
1956      packet. */
1957     if (nstime_is_unset(&prev_dis_ts)) {
1958         prev_dis_ts = fdata->abs_ts;
1959     }
1960
1961     /* Get the time elapsed between the first packet and this packet. */
1962     nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
1963
1964     /* If it's greater than the current elapsed time, set the elapsed time
1965      to it (we check for "greater than" so as not to be confused by
1966      time moving backwards). */
1967     if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
1968         || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
1969         cf->elapsed_time = fdata->rel_ts;
1970     }
1971
1972     /* Get the time elapsed between the previous displayed packet and
1973      this packet. */
1974     nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
1975
1976     prev_dis_ts = fdata->abs_ts;
1977
1978     /*
1979      * Byte counts
1980      */
1981     if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
1982         /* This frame either passed the display filter list or is marked as
1983         a time reference frame.  All time reference frames are displayed
1984         even if they dont pass the display filter */
1985         if(fdata->flags.ref_time){
1986             /* if this was a TIME REF frame we should reset the cum_bytes field */
1987             cum_bytes = fdata->pkt_len;
1988             fdata->cum_bytes =  cum_bytes;
1989         } else {
1990             /* increase cum_bytes with this packets length */
1991             cum_bytes += fdata->pkt_len;
1992         }
1993     }
1994   }
1995 }
1996
1997 typedef enum {
1998   PSP_FINISHED,
1999   PSP_STOPPED,
2000   PSP_FAILED
2001 } psp_return_t;
2002
2003 static psp_return_t
2004 process_specified_packets(capture_file *cf, packet_range_t *range,
2005     const char *string1, const char *string2, gboolean terminate_is_stop,
2006     gboolean (*callback)(capture_file *, frame_data *,
2007                          union wtap_pseudo_header *, const guint8 *, void *),
2008     void *callback_args)
2009 {
2010   frame_data *fdata;
2011   union wtap_pseudo_header pseudo_header;
2012   guint8      pd[WTAP_MAX_PACKET_SIZE+1];
2013   psp_return_t ret = PSP_FINISHED;
2014
2015   progdlg_t  *progbar = NULL;
2016   int         progbar_count;
2017   float       progbar_val;
2018   gboolean    progbar_stop_flag;
2019   GTimeVal    progbar_start_time;
2020   gchar       progbar_status_str[100];
2021   int         progbar_nextstep;
2022   int         progbar_quantum;
2023   range_process_e process_this;
2024
2025   /* Update the progress bar when it gets to this value. */
2026   progbar_nextstep = 0;
2027   /* When we reach the value that triggers a progress bar update,
2028      bump that value by this amount. */
2029   progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2030   /* Count of packets at which we've looked. */
2031   progbar_count = 0;
2032   /* Progress so far. */
2033   progbar_val = 0.0f;
2034
2035   progbar_stop_flag = FALSE;
2036   g_get_current_time(&progbar_start_time);
2037
2038   packet_range_process_init(range);
2039
2040   /* Iterate through the list of packets, printing the packets that
2041      were selected by the current display filter.  */
2042   for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
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   frame_data  *fdata;
3197   frame_data  *new_fd = NULL;
3198   progdlg_t   *progbar = NULL;
3199   gboolean     stop_flag;
3200   int          count;
3201   int          row;
3202   float        progbar_val;
3203   GTimeVal     start_time;
3204   gchar        status_str[100];
3205   int          progbar_nextstep;
3206   int          progbar_quantum;
3207   const char  *title;
3208   match_result result;
3209
3210   start_fd = cf->current_frame;
3211   if (start_fd != NULL)  {
3212     /* Iterate through the list of packets, starting at the packet we've
3213        picked, calling a routine to run the filter on the packet, see if
3214        it matches, and stop if so.  */
3215     count = 0;
3216     fdata = start_fd;
3217
3218     /* Update the progress bar when it gets to this value. */
3219     progbar_nextstep = 0;
3220     /* When we reach the value that triggers a progress bar update,
3221        bump that value by this amount. */
3222     progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3223     /* Progress so far. */
3224     progbar_val = 0.0f;
3225
3226     stop_flag = FALSE;
3227     g_get_current_time(&start_time);
3228
3229     title = cf->sfilter?cf->sfilter:"";
3230     for (;;) {
3231       /* Create the progress bar if necessary.
3232          We check on every iteration of the loop, so that it takes no
3233          longer than the standard time to create it (otherwise, for a
3234          large file, we might take considerably longer than that standard
3235          time in order to get to the next progress bar step). */
3236       if (progbar == NULL)
3237          progbar = delayed_create_progress_dlg("Searching", title,
3238            FALSE, &stop_flag, &start_time, progbar_val);
3239
3240       /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3241          when we update it, we have to run the GTK+ main loop to get it
3242          to repaint what's pending, and doing so may involve an "ioctl()"
3243          to see if there's any pending input from an X server, and doing
3244          that for every packet can be costly, especially on a big file. */
3245       if (count >= progbar_nextstep) {
3246         /* let's not divide by zero. I should never be started
3247          * with count == 0, so let's assert that
3248          */
3249         g_assert(cf->count > 0);
3250
3251         progbar_val = (gfloat) count / cf->count;
3252
3253         if (progbar != NULL) {
3254           g_snprintf(status_str, sizeof(status_str),
3255                      "%4u of %u packets", count, cf->count);
3256           update_progress_dlg(progbar, progbar_val, status_str);
3257         }
3258
3259         progbar_nextstep += progbar_quantum;
3260       }
3261
3262       if (stop_flag) {
3263         /* Well, the user decided to abort the search.  Go back to the
3264            frame where we started. */
3265         new_fd = start_fd;
3266         break;
3267       }
3268
3269       /* Go past the current frame. */
3270       if (dir == SD_BACKWARD) {
3271         /* Go on to the previous frame. */
3272         fdata = fdata->prev;
3273         if (fdata == NULL) {
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               fdata = cf->plist_end;    /* wrap around */
3286           }
3287           else
3288           {
3289               statusbar_push_temporary_msg("Search reached the beginning.");
3290               fdata = start_fd;        /* stay on previous packet */
3291           }
3292         }
3293       } else {
3294         /* Go on to the next frame. */
3295         fdata = fdata->next;
3296         if (fdata == NULL) {
3297           if (prefs.gui_find_wrap)
3298           {
3299               statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3300               fdata = cf->plist_start;    /* wrap around */
3301           }
3302           else
3303           {
3304               statusbar_push_temporary_msg("Search reached the end.");
3305               fdata = start_fd;     /* stay on previous packet */
3306           }
3307         }
3308       }
3309
3310       count++;
3311
3312       /* Is this packet in the display? */
3313       if (fdata->flags.passed_dfilter) {
3314         /* Yes.  Does it match the search criterion? */
3315         result = (*match_function)(cf, fdata, criterion);
3316         if (result == MR_ERROR) {
3317           /* Error; our caller has reported the error.  Go back to the frame
3318              where we started. */
3319           new_fd = start_fd;
3320           break;
3321         } else if (result == MR_MATCHED) {
3322           /* Yes.  Go to the new frame. */
3323           new_fd = fdata;
3324           break;
3325         }
3326       }
3327
3328       if (fdata == start_fd) {
3329         /* We're back to the frame we were on originally, and that frame
3330            doesn't match the search filter.  The search failed. */
3331         break;
3332       }
3333     }
3334
3335     /* We're done scanning the packets; destroy the progress bar if it
3336        was created. */
3337     if (progbar != NULL)
3338       destroy_progress_dlg(progbar);
3339   }
3340
3341   if (new_fd != NULL) {
3342     /* Find and select */
3343     cf->search_in_progress = TRUE;
3344     row = new_packet_list_find_row_from_data(fdata, TRUE);
3345     cf->search_in_progress = FALSE;
3346     cf->search_pos = 0; /* Reset the position */
3347     if (row == -1) {
3348       /* We didn't find a row even though we know that a frame
3349        * exists that satifies the search criteria. This means that the
3350        * frame isn't being displayed currently so we can't select it. */
3351       simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3352                     "%sEnd of capture exceeded!%s\n\n"
3353                     "The capture file is probably not fully loaded.",
3354                     simple_dialog_primary_start(), simple_dialog_primary_end());
3355       return FALSE;
3356     }
3357     return TRUE;    /* success */
3358   } else
3359     return FALSE;   /* failure */
3360 }
3361
3362 gboolean
3363 cf_goto_frame(capture_file *cf, guint fnumber)
3364 {
3365   frame_data *fdata;
3366
3367   for (fdata = cf->plist_start; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
3368     ;
3369
3370   if (fdata == NULL) {
3371     /* we didn't find a packet with that packet number */
3372     statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3373     return FALSE;   /* we failed to go to that packet */
3374   }
3375   if (!fdata->flags.passed_dfilter) {
3376     /* that packet currently isn't displayed */
3377     /* XXX - add it to the set of displayed packets? */
3378     statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3379     return FALSE;   /* we failed to go to that packet */
3380   }
3381
3382   new_packet_list_find_row_from_data(fdata, TRUE);
3383   return TRUE;  /* we got to that packet */
3384 }
3385
3386 gboolean
3387 cf_goto_top_frame()
3388 {
3389   /* Find and select */
3390   new_packet_list_select_first_row();
3391   return TRUE;  /* we got to that packet */
3392 }
3393
3394 gboolean
3395 cf_goto_bottom_frame()
3396 {
3397   /* Find and select */
3398   new_packet_list_select_last_row();
3399   return TRUE;  /* we got to that packet */
3400 }
3401
3402 /*
3403  * Go to frame specified by currently selected protocol tree item.
3404  */
3405 gboolean
3406 cf_goto_framenum(capture_file *cf)
3407 {
3408   header_field_info       *hfinfo;
3409   guint32                 framenum;
3410
3411   if (cf->finfo_selected) {
3412     hfinfo = cf->finfo_selected->hfinfo;
3413     g_assert(hfinfo);
3414     if (hfinfo->type == FT_FRAMENUM) {
3415       framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3416       if (framenum != 0)
3417         return cf_goto_frame(cf, framenum);
3418       }
3419   }
3420
3421   return FALSE;
3422 }
3423
3424 /* Select the packet on a given row. */
3425 void
3426 cf_select_packet(capture_file *cf, int row)
3427 {
3428   frame_data *fdata;
3429
3430   /* Get the frame data struct pointer for this frame */
3431   fdata = new_packet_list_get_row_data(row);
3432
3433   if (fdata == NULL) {
3434     /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3435        the first entry is added to it by "real_insert_row()", that row
3436        is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
3437        our version and the vanilla GTK+ version).
3438
3439        This means that a "select-row" signal is emitted; this causes
3440        "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3441        to be called.
3442
3443        "cf_select_packet()" fetches, above, the data associated with the
3444        row that was selected; however, as "gtk_clist_append()", which
3445        called "real_insert_row()", hasn't yet returned, we haven't yet
3446        associated any data with that row, so we get back a null pointer.
3447
3448        We can't assume that there's only one frame in the frame list,
3449        either, as we may be filtering the display.
3450
3451        We therefore assume that, if "row" is 0, i.e. the first row
3452        is being selected, and "cf->first_displayed" equals
3453        "cf->last_displayed", i.e. there's only one frame being
3454        displayed, that frame is the frame we want.
3455
3456        This means we have to set "cf->first_displayed" and
3457        "cf->last_displayed" before adding the row to the
3458        GtkCList; see the comment in "add_packet_to_packet_list()". */
3459
3460        if (row == 0 && cf->first_displayed == cf->last_displayed)
3461          fdata = cf->first_displayed;
3462   }
3463
3464   /* If fdata _still_ isn't set simply give up. */
3465   if (fdata == NULL) {
3466     return;
3467   }
3468
3469   /* Get the data in that frame. */
3470   if (!cf_read_frame (cf, fdata)) {
3471     return;
3472   }
3473
3474   /* Record that this frame is the current frame. */
3475   cf->current_frame = fdata;
3476   cf->current_row = row;
3477
3478   /* Create the logical protocol tree. */
3479   if (cf->edt != NULL)
3480     epan_dissect_free(cf->edt);
3481
3482   /* We don't need the columns here. */
3483   cf->edt = epan_dissect_new(TRUE, TRUE);
3484
3485   tap_build_interesting(cf->edt);
3486   epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3487           NULL);
3488
3489   dfilter_macro_build_ftv_cache(cf->edt->tree);
3490
3491   cf_callback_invoke(cf_cb_packet_selected, cf);
3492 }
3493
3494 /* Unselect the selected packet, if any. */
3495 void
3496 cf_unselect_packet(capture_file *cf)
3497 {
3498   /* Destroy the epan_dissect_t for the unselected packet. */
3499   if (cf->edt != NULL) {
3500     epan_dissect_free(cf->edt);
3501     cf->edt = NULL;
3502   }
3503
3504   /* No packet is selected. */
3505   cf->current_frame = NULL;
3506   cf->current_row = 0;
3507
3508   cf_callback_invoke(cf_cb_packet_unselected, cf);
3509
3510   /* No protocol tree means no selected field. */
3511   cf_unselect_field(cf);
3512 }
3513
3514 /* Unset the selected protocol tree field, if any. */
3515 void
3516 cf_unselect_field(capture_file *cf)
3517 {
3518   cf->finfo_selected = NULL;
3519
3520   cf_callback_invoke(cf_cb_field_unselected, cf);
3521 }
3522
3523 /*
3524  * Mark a particular frame.
3525  */
3526 void
3527 cf_mark_frame(capture_file *cf, frame_data *frame)
3528 {
3529   if (! frame->flags.marked) {
3530     frame->flags.marked = TRUE;
3531     if (cf->count > cf->marked_count)
3532       cf->marked_count++;
3533   }
3534 }
3535
3536 /*
3537  * Unmark a particular frame.
3538  */
3539 void
3540 cf_unmark_frame(capture_file *cf, frame_data *frame)
3541 {
3542   if (frame->flags.marked) {
3543     frame->flags.marked = FALSE;
3544     if (cf->marked_count > 0)
3545       cf->marked_count--;
3546   }
3547 }
3548
3549 /*
3550  * Ignore a particular frame.
3551  */
3552 void
3553 cf_ignore_frame(capture_file *cf, frame_data *frame)
3554 {
3555   if (! frame->flags.ignored) {
3556     frame->flags.ignored = TRUE;
3557     if (cf->count > cf->ignored_count)
3558       cf->ignored_count++;
3559   }
3560 }
3561
3562 /*
3563  * Un-ignore a particular frame.
3564  */
3565 void
3566 cf_unignore_frame(capture_file *cf, frame_data *frame)
3567 {
3568   if (frame->flags.ignored) {
3569     frame->flags.ignored = FALSE;
3570     if (cf->ignored_count > 0)
3571       cf->ignored_count--;
3572   }
3573 }
3574
3575 typedef struct {
3576   wtap_dumper *pdh;
3577   const char  *fname;
3578 } save_callback_args_t;
3579
3580 /*
3581  * Save a capture to a file, in a particular format, saving either
3582  * all packets, all currently-displayed packets, or all marked packets.
3583  *
3584  * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3585  * up a message box for the failure.
3586  */
3587 static gboolean
3588 save_packet(capture_file *cf _U_, frame_data *fdata,
3589             union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3590             void *argsp)
3591 {
3592   save_callback_args_t *args = argsp;
3593   struct wtap_pkthdr hdr;
3594   int           err;
3595
3596   /* init the wtap header for saving */
3597   hdr.ts.secs    = fdata->abs_ts.secs;
3598   hdr.ts.nsecs   = fdata->abs_ts.nsecs;
3599   hdr.caplen     = fdata->cap_len;
3600   hdr.len        = fdata->pkt_len;
3601   hdr.pkt_encap  = fdata->lnk_t;
3602
3603   /* and save the packet */
3604   if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3605     cf_write_failure_alert_box(args->fname, err);
3606     return FALSE;
3607   }
3608   return TRUE;
3609 }
3610
3611 /*
3612  * Can this capture file be saved in any format except by copying the raw data?
3613  */
3614 gboolean
3615 cf_can_save_as(capture_file *cf)
3616 {
3617   int ft;
3618
3619   for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
3620     /* To save a file with Wiretap, Wiretap has to handle that format,
3621        and its code to handle that format must be able to write a file
3622        with this file's encapsulation type. */
3623     if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
3624       /* OK, we can write it out in this type. */
3625       return TRUE;
3626     }
3627   }
3628
3629   /* No, we couldn't save it in any format. */
3630   return FALSE;
3631 }
3632
3633 cf_status_t
3634 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3635 {
3636   gchar        *from_filename;
3637   int           err;
3638   gboolean      do_copy;
3639   wtap_dumper  *pdh;
3640   save_callback_args_t callback_args;
3641
3642   cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
3643
3644   /* don't write over an existing file. */
3645   /* this should've been already checked by our caller, just to be sure... */
3646   if (file_exists(fname)) {
3647     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3648       "%sCapture file: \"%s\" already exists!%s\n\n"
3649       "Please choose a different filename.",
3650       simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3651     goto fail;
3652   }
3653
3654   packet_range_process_init(range);
3655
3656   if (packet_range_process_all(range) && save_format == cf->cd_t) {
3657     /* We're not filtering packets, and we're saving it in the format
3658        it's already in, so we can just move or copy the raw data. */
3659
3660     if (cf->is_tempfile) {
3661       /* The file being saved is a temporary file from a live
3662          capture, so it doesn't need to stay around under that name;
3663          first, try renaming the capture buffer file to the new name. */
3664 #ifndef _WIN32
3665       if (ws_rename(cf->filename, fname) == 0) {
3666         /* That succeeded - there's no need to copy the source file. */
3667         from_filename = NULL;
3668     do_copy = FALSE;
3669       } else {
3670         if (errno == EXDEV) {
3671           /* They're on different file systems, so we have to copy the
3672              file. */
3673           do_copy = TRUE;
3674           from_filename = cf->filename;
3675         } else {
3676           /* The rename failed, but not because they're on different
3677              file systems - put up an error message.  (Or should we
3678              just punt and try to copy?  The only reason why I'd
3679              expect the rename to fail and the copy to succeed would
3680              be if we didn't have permission to remove the file from
3681              the temporary directory, and that might be fixable - but
3682              is it worth requiring the user to go off and fix it?) */
3683           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3684                         file_rename_error_message(errno), fname);
3685           goto fail;
3686         }
3687       }
3688 #else
3689       do_copy = TRUE;
3690       from_filename = cf->filename;
3691 #endif
3692     } else {
3693       /* It's a permanent file, so we should copy it, and not remove the
3694          original. */
3695       do_copy = TRUE;
3696       from_filename = cf->filename;
3697     }
3698
3699     if (do_copy) {
3700       /* Copy the file, if we haven't moved it. */
3701       if (!copy_file_binary_mode(from_filename, fname))
3702     goto fail;
3703     }
3704   } else {
3705     /* Either we're filtering packets, or we're saving in a different
3706        format; we can't do that by copying or moving the capture file,
3707        we have to do it by writing the packets out in Wiretap. */
3708     pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
3709         compressed, &err);
3710     if (pdh == NULL) {
3711       cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3712       goto fail;
3713     }
3714
3715     /* XXX - we let the user save a subset of the packets.
3716
3717        If we do that, should we make that file the current file?  If so,
3718        it means we can no longer get at the other packets.  What does
3719        NetMon do? */
3720
3721     /* Iterate through the list of packets, processing the packets we were
3722        told to process.
3723
3724        XXX - we've already called "packet_range_process_init(range)", but
3725        "process_specified_packets()" will do it again.  Fortunately,
3726        that's harmless in this case, as we haven't done anything to
3727        "range" since we initialized it. */
3728     callback_args.pdh = pdh;
3729     callback_args.fname = fname;
3730     switch (process_specified_packets(cf, range, "Saving", "selected packets",
3731                                       TRUE, save_packet, &callback_args)) {
3732
3733     case PSP_FINISHED:
3734       /* Completed successfully. */
3735       break;
3736
3737     case PSP_STOPPED:
3738       /* The user decided to abort the saving.
3739          XXX - remove the output file? */
3740       break;
3741
3742     case PSP_FAILED:
3743       /* Error while saving. */
3744       wtap_dump_close(pdh, &err);
3745       goto fail;
3746     }
3747
3748     if (!wtap_dump_close(pdh, &err)) {
3749       cf_close_failure_alert_box(fname, err);
3750       goto fail;
3751     }
3752   }
3753
3754   cf_callback_invoke(cf_cb_file_save_finished, NULL);
3755
3756   if (packet_range_process_all(range)) {
3757     /* We saved the entire capture, not just some packets from it.
3758        Open and read the file we saved it to.
3759
3760        XXX - this is somewhat of a waste; we already have the
3761        packets, all this gets us is updated file type information
3762        (which we could just stuff into "cf"), and having the new
3763        file be the one we have opened and from which we're reading
3764        the data, and it means we have to spend time opening and
3765        reading the file, which could be a significant amount of
3766        time if the file is large. */
3767     cf->user_saved = TRUE;
3768
3769     if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3770       /* XXX - report errors if this fails?
3771          What should we return if it fails or is aborted? */
3772
3773       switch (cf_read(cf, TRUE)) {
3774
3775       case CF_READ_OK:
3776       case CF_READ_ERROR:
3777     /* Just because we got an error, that doesn't mean we were unable
3778        to read any of the file; we handle what we could get from the
3779        file. */
3780     break;
3781
3782       case CF_READ_ABORTED:
3783     /* The user bailed out of re-reading the capture file; the
3784        capture file has been closed - just return (without
3785        changing any menu settings; "cf_close()" set them
3786        correctly for the "no capture file open" state). */
3787     break;
3788       }
3789       cf_callback_invoke(cf_cb_file_save_reload_finished, cf);
3790     }
3791   }
3792   return CF_OK;
3793
3794 fail:
3795   cf_callback_invoke(cf_cb_file_save_failed, NULL);
3796   return CF_ERROR;
3797 }
3798
3799 static void
3800 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3801                           gboolean for_writing, int file_type)
3802 {
3803   if (err < 0) {
3804     /* Wiretap error. */
3805     switch (err) {
3806
3807     case WTAP_ERR_NOT_REGULAR_FILE:
3808       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3809             "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3810             filename);
3811       break;
3812
3813     case WTAP_ERR_RANDOM_OPEN_PIPE:
3814       /* Seen only when opening a capture file for reading. */
3815       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3816             "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
3817             filename);
3818       break;
3819
3820     case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3821       /* Seen only when opening a capture file for reading. */
3822       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3823             "The file \"%s\" isn't a capture file in a format Wireshark understands.",
3824             filename);
3825       break;
3826
3827     case WTAP_ERR_UNSUPPORTED:
3828       /* Seen only when opening a capture file for reading. */
3829       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3830             "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
3831             "(%s)",
3832             filename, err_info);
3833       g_free(err_info);
3834       break;
3835
3836     case WTAP_ERR_CANT_WRITE_TO_PIPE:
3837       /* Seen only when opening a capture file for writing. */
3838       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3839             "The file \"%s\" is a pipe, and %s capture files can't be "
3840             "written to a pipe.",
3841             filename, wtap_file_type_string(file_type));
3842       break;
3843
3844     case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3845       /* Seen only when opening a capture file for writing. */
3846       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3847             "Wireshark doesn't support writing capture files in that format.");
3848       break;
3849
3850     case WTAP_ERR_UNSUPPORTED_ENCAP:
3851       if (for_writing) {
3852         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3853               "Wireshark can't save this capture in that format.");
3854       } else {
3855         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3856               "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
3857               "(%s)",
3858               filename, err_info);
3859         g_free(err_info);
3860       }
3861       break;
3862
3863     case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3864       if (for_writing) {
3865         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3866               "Wireshark can't save this capture in that format.");
3867       } else {
3868         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3869               "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
3870               filename);
3871       }
3872       break;
3873
3874     case WTAP_ERR_BAD_RECORD:
3875       /* Seen only when opening a capture file for reading. */
3876       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3877             "The file \"%s\" appears to be damaged or corrupt.\n"
3878             "(%s)",
3879             filename, err_info);
3880       g_free(err_info);
3881       break;
3882
3883     case WTAP_ERR_CANT_OPEN:
3884       if (for_writing) {
3885         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3886               "The file \"%s\" could not be created for some unknown reason.",
3887               filename);
3888       } else {
3889         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3890               "The file \"%s\" could not be opened for some unknown reason.",
3891               filename);
3892       }
3893       break;
3894
3895     case WTAP_ERR_SHORT_READ:
3896       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3897             "The file \"%s\" appears to have been cut short"
3898             " in the middle of a packet or other data.",
3899             filename);
3900       break;
3901
3902     case WTAP_ERR_SHORT_WRITE:
3903       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3904             "A full header couldn't be written to the file \"%s\".",
3905             filename);
3906       break;
3907
3908     case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
3909       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3910             "Gzip compression not supported by this file type.");
3911       break;
3912
3913     default:
3914       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3915             "The file \"%s\" could not be %s: %s.",
3916             filename,
3917             for_writing ? "created" : "opened",
3918             wtap_strerror(err));
3919       break;
3920     }
3921   } else {
3922     /* OS error. */
3923     open_failure_alert_box(filename, err, for_writing);
3924   }
3925 }
3926
3927 static const char *
3928 file_rename_error_message(int err)
3929 {
3930   const char *errmsg;
3931   static char errmsg_errno[1024+1];
3932
3933   switch (err) {
3934
3935   case ENOENT:
3936     errmsg = "The path to the file \"%s\" doesn't exist.";
3937     break;
3938
3939   case EACCES:
3940     errmsg = "You don't have permission to move the capture file to \"%s\".";
3941     break;
3942
3943   default:
3944     g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3945             "The file \"%%s\" could not be moved: %s.",
3946                 wtap_strerror(err));
3947     errmsg = errmsg_errno;
3948     break;
3949   }
3950   return errmsg;
3951 }
3952
3953 static void
3954 cf_write_failure_alert_box(const char *filename, int err)
3955 {
3956   if (err < 0) {
3957     /* Wiretap error. */
3958     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3959           "An error occurred while writing to the file \"%s\": %s.",
3960           filename, wtap_strerror(err));
3961   } else {
3962     /* OS error. */
3963     write_failure_alert_box(filename, err);
3964   }
3965 }
3966
3967 /* Check for write errors - if the file is being written to an NFS server,
3968    a write error may not show up until the file is closed, as NFS clients
3969    might not send writes to the server until the "write()" call finishes,
3970    so that the write may fail on the server but the "write()" may succeed. */
3971 static void
3972 cf_close_failure_alert_box(const char *filename, int err)
3973 {
3974   if (err < 0) {
3975     /* Wiretap error. */
3976     switch (err) {
3977
3978     case WTAP_ERR_CANT_CLOSE:
3979       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3980             "The file \"%s\" couldn't be closed for some unknown reason.",
3981             filename);
3982       break;
3983
3984     case WTAP_ERR_SHORT_WRITE:
3985       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3986             "Not all the packets could be written to the file \"%s\".",
3987                     filename);
3988       break;
3989
3990     default:
3991       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3992             "An error occurred while closing the file \"%s\": %s.",
3993             filename, wtap_strerror(err));
3994       break;
3995     }
3996   } else {
3997     /* OS error.
3998        We assume that a close error from the OS is really a write error. */
3999     write_failure_alert_box(filename, err);
4000   }
4001 }
4002
4003 /* Reload the current capture file. */
4004 void
4005 cf_reload(capture_file *cf) {
4006   gchar *filename;
4007   gboolean is_tempfile;
4008   int err;
4009
4010   /* If the file could be opened, "cf_open()" calls "cf_close()"
4011      to get rid of state for the old capture file before filling in state
4012      for the new capture file.  "cf_close()" will remove the file if
4013      it's a temporary file; we don't want that to happen (for one thing,
4014      it'd prevent subsequent reopens from working).  Remember whether it's
4015      a temporary file, mark it as not being a temporary file, and then
4016      reopen it as the type of file it was.
4017
4018      Also, "cf_close()" will free "cf->filename", so we must make
4019      a copy of it first. */
4020   filename = g_strdup(cf->filename);
4021   is_tempfile = cf->is_tempfile;
4022   cf->is_tempfile = FALSE;
4023   if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
4024     switch (cf_read(cf, FALSE)) {
4025
4026     case CF_READ_OK:
4027     case CF_READ_ERROR:
4028       /* Just because we got an error, that doesn't mean we were unable
4029          to read any of the file; we handle what we could get from the
4030          file. */
4031       break;
4032
4033     case CF_READ_ABORTED:
4034       /* The user bailed out of re-reading the capture file; the
4035          capture file has been closed - just free the capture file name
4036          string and return (without changing the last containing
4037          directory). */
4038       g_free(filename);
4039       return;
4040     }
4041   } else {
4042     /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4043        Instead, the file was left open, so we should restore "cf->is_tempfile"
4044        ourselves.
4045
4046        XXX - change the menu?  Presumably "cf_open()" will do that;
4047        make sure it does! */
4048     cf->is_tempfile = is_tempfile;
4049   }
4050   /* "cf_open()" made a copy of the file name we handed it, so
4051      we should free up our copy. */
4052   g_free(filename);
4053 }
4054
4055 /*
4056  * Editor modelines
4057  *
4058  * Local Variables:
4059  * c-basic-offset: 2
4060  * tab-width: 8
4061  * indent-tabs-mode: nil
4062  * End:
4063  *
4064  * ex: set shiftwidth=2 tabstop=8 expandtab
4065  * :indentSize=2:tabSize=8:noTabs=true:
4066  */