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