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