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