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