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