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