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