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