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