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