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