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