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