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