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