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