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