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