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