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