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