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