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