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