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