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