From: Hannes Gredler
[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 Wireshark 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 Wireshark.  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 Wireshark.  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 Wireshark 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 Wireshark 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       }
1524     }
1525   }
1526
1527   if (selected_row == -1) {
1528     /* There are no frames displayed at all. */
1529     cf_unselect_packet(cf);
1530   } else {
1531     /* Either the frame that was selected passed the filter, or we've
1532        found the nearest displayed frame to that frame.  Select it, make
1533        it the focus row, and make it visible. */
1534     packet_list_set_selected_row(selected_row);
1535   }
1536 }
1537
1538 typedef enum {
1539   PSP_FINISHED,
1540   PSP_STOPPED,
1541   PSP_FAILED
1542 } psp_return_t;
1543
1544 static psp_return_t
1545 process_specified_packets(capture_file *cf, packet_range_t *range,
1546     const char *string1, const char *string2, gboolean terminate_is_stop,
1547     gboolean (*callback)(capture_file *, frame_data *,
1548                          union wtap_pseudo_header *, const guint8 *, void *),
1549     void *callback_args)
1550 {
1551   frame_data *fdata;
1552   int         err;
1553   gchar      *err_info;
1554   union wtap_pseudo_header pseudo_header;
1555   guint8      pd[WTAP_MAX_PACKET_SIZE+1];
1556   psp_return_t ret = PSP_FINISHED;
1557
1558   progdlg_t  *progbar = NULL;
1559   int         progbar_count;
1560   float       progbar_val;
1561   gboolean    progbar_stop_flag;
1562   GTimeVal    progbar_start_time;
1563   gchar       progbar_status_str[100];
1564   int         progbar_nextstep;
1565   int         progbar_quantum;
1566   range_process_e process_this;
1567
1568   /* Update the progress bar when it gets to this value. */
1569   progbar_nextstep = 0;
1570   /* When we reach the value that triggers a progress bar update,
1571      bump that value by this amount. */
1572   progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1573   /* Count of packets at which we've looked. */
1574   progbar_count = 0;
1575   /* Progress so far. */
1576   progbar_val = 0.0;
1577
1578   progbar_stop_flag = FALSE;
1579   g_get_current_time(&progbar_start_time);
1580
1581   packet_range_process_init(range);
1582
1583   /* Iterate through the list of packets, printing the packets that
1584      were selected by the current display filter.  */
1585   for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1586     /* Create the progress bar if necessary.
1587        We check on every iteration of the loop, so that it takes no
1588        longer than the standard time to create it (otherwise, for a
1589        large file, we might take considerably longer than that standard
1590        time in order to get to the next progress bar step). */
1591     if (progbar == NULL)
1592       progbar = delayed_create_progress_dlg(string1, string2,
1593                                             terminate_is_stop,
1594                                             &progbar_stop_flag,
1595                                             &progbar_start_time,
1596                                             progbar_val);
1597
1598     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1599        when we update it, we have to run the GTK+ main loop to get it
1600        to repaint what's pending, and doing so may involve an "ioctl()"
1601        to see if there's any pending input from an X server, and doing
1602        that for every packet can be costly, especially on a big file. */
1603     if (progbar_count >= progbar_nextstep) {
1604       /* let's not divide by zero. I should never be started
1605        * with count == 0, so let's assert that
1606        */
1607       g_assert(cf->count > 0);
1608       progbar_val = (gfloat) progbar_count / cf->count;
1609
1610       if (progbar != NULL) {
1611         g_snprintf(progbar_status_str, sizeof(progbar_status_str),
1612                    "%4u of %u packets", progbar_count, cf->count);
1613         update_progress_dlg(progbar, progbar_val, progbar_status_str);
1614       }
1615
1616       progbar_nextstep += progbar_quantum;
1617     }
1618
1619     if (progbar_stop_flag) {
1620       /* Well, the user decided to abort the operation.  Just stop,
1621          and arrange to return PSP_STOPPED to our caller, so they know
1622          it was stopped explicitly. */
1623       ret = PSP_STOPPED;
1624       break;
1625     }
1626
1627     progbar_count++;
1628
1629     /* do we have to process this packet? */
1630     process_this = packet_range_process_packet(range, fdata);
1631     if (process_this == range_process_next) {
1632         /* this packet uninteresting, continue with next one */
1633         continue;
1634     } else if (process_this == range_processing_finished) {
1635         /* all interesting packets processed, stop the loop */
1636         break;
1637     }
1638
1639     /* Get the packet */
1640     if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1641                         pd, fdata->cap_len, &err, &err_info)) {
1642       /* Attempt to get the packet failed. */
1643       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1644                     cf_read_error_message(err, err_info), cf->filename);
1645       ret = PSP_FAILED;
1646       break;
1647     }
1648     /* Process the packet */
1649     if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
1650       /* Callback failed.  We assume it reported the error appropriately. */
1651       ret = PSP_FAILED;
1652       break;
1653     }
1654   }
1655
1656   /* We're done printing the packets; destroy the progress bar if
1657      it was created. */
1658   if (progbar != NULL)
1659     destroy_progress_dlg(progbar);
1660
1661   return ret;
1662 }
1663
1664 static gboolean
1665 retap_packet(capture_file *cf _U_, frame_data *fdata,
1666              union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1667              void *argsp)
1668 {
1669   column_info *cinfo = argsp;
1670   epan_dissect_t *edt;
1671
1672   /* If we have tap listeners, allocate a protocol tree root node, so that
1673      we'll construct a protocol tree against which a filter expression can
1674      be evaluated. */
1675   edt = epan_dissect_new(num_tap_filters != 0, FALSE);
1676   tap_queue_init(edt);
1677   epan_dissect_run(edt, pseudo_header, pd, fdata, cinfo);
1678   tap_push_tapped_queue(edt);
1679   epan_dissect_free(edt);
1680
1681   return TRUE;
1682 }
1683
1684 cf_read_status_t
1685 cf_retap_packets(capture_file *cf, gboolean do_columns)
1686 {
1687   packet_range_t range;
1688
1689   /* Reset the tap listeners. */
1690   reset_tap_listeners();
1691
1692   /* Iterate through the list of packets, dissecting all packets and
1693      re-running the taps. */
1694   packet_range_init(&range);
1695   packet_range_process_init(&range);
1696   switch (process_specified_packets(cf, &range, "Refiltering statistics on",
1697                                     "all packets", TRUE, retap_packet,
1698                                     do_columns ? &cf->cinfo : NULL)) {
1699   case PSP_FINISHED:
1700     /* Completed successfully. */
1701     return CF_OK;
1702
1703   case PSP_STOPPED:
1704     /* Well, the user decided to abort the refiltering.
1705        Return CF_READ_ABORTED so our caller knows they did that. */
1706     return CF_READ_ABORTED;
1707
1708   case PSP_FAILED:
1709     /* Error while retapping. */
1710     return CF_READ_ERROR;
1711   }
1712
1713   g_assert_not_reached();
1714   return CF_READ_OK;
1715 }
1716
1717 typedef struct {
1718   print_args_t *print_args;
1719   gboolean      print_header_line;
1720   char         *header_line_buf;
1721   int           header_line_buf_len;
1722   gboolean      print_formfeed;
1723   gboolean      print_separator;
1724   char         *line_buf;
1725   int           line_buf_len;
1726   gint         *col_widths;
1727 } print_callback_args_t;
1728
1729 static gboolean
1730 print_packet(capture_file *cf, frame_data *fdata,
1731              union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1732              void *argsp)
1733 {
1734   print_callback_args_t *args = argsp;
1735   epan_dissect_t *edt;
1736   int             i;
1737   char           *cp;
1738   int             line_len;
1739   int             column_len;
1740   int             cp_off;
1741   gboolean        proto_tree_needed;
1742   char            bookmark_name[9+10+1];        /* "__frameNNNNNNNNNN__\0" */
1743   char            bookmark_title[6+10+1];       /* "Frame NNNNNNNNNN__\0" */
1744
1745   /* Create the protocol tree, and make it visible, if we're printing
1746      the dissection or the hex data.
1747      XXX - do we need it if we're just printing the hex data? */
1748   proto_tree_needed =
1749       args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex;
1750   edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
1751
1752   /* Fill in the column information if we're printing the summary
1753      information. */
1754   if (args->print_args->print_summary) {
1755     epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
1756     epan_dissect_fill_in_columns(edt);
1757   } else
1758     epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1759
1760   if (args->print_formfeed) {
1761     if (!new_page(args->print_args->stream))
1762       goto fail;
1763   } else {
1764       if (args->print_separator) {
1765         if (!print_line(args->print_args->stream, 0, ""))
1766           goto fail;
1767       }
1768   }
1769
1770   /*
1771    * We generate bookmarks, if the output format supports them.
1772    * The name is "__frameN__".
1773    */
1774   g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
1775
1776   if (args->print_args->print_summary) {
1777     if (args->print_header_line) {
1778       if (!print_line(args->print_args->stream, 0, args->header_line_buf))
1779         goto fail;
1780       args->print_header_line = FALSE;  /* we might not need to print any more */
1781     }
1782     cp = &args->line_buf[0];
1783     line_len = 0;
1784     for (i = 0; i < cf->cinfo.num_cols; i++) {
1785       /* Find the length of the string for this column. */
1786       column_len = strlen(cf->cinfo.col_data[i]);
1787       if (args->col_widths[i] > column_len)
1788          column_len = args->col_widths[i];
1789
1790       /* Make sure there's room in the line buffer for the column; if not,
1791          double its length. */
1792       line_len += column_len + 1;       /* "+1" for space */
1793       if (line_len > args->line_buf_len) {
1794         cp_off = cp - args->line_buf;
1795         args->line_buf_len = 2 * line_len;
1796         args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
1797         cp = args->line_buf + cp_off;
1798       }
1799
1800       /* Right-justify the packet number column. */
1801       if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1802         sprintf(cp, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
1803       else
1804         sprintf(cp, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
1805       cp += column_len;
1806       if (i != cf->cinfo.num_cols - 1)
1807         *cp++ = ' ';
1808     }
1809     *cp = '\0';
1810
1811     /*
1812      * Generate a bookmark, using the summary line as the title.
1813      */
1814     if (!print_bookmark(args->print_args->stream, bookmark_name,
1815                         args->line_buf))
1816       goto fail;
1817
1818     if (!print_line(args->print_args->stream, 0, args->line_buf))
1819       goto fail;
1820   } else {
1821     /*
1822      * Generate a bookmark, using "Frame N" as the title, as we're not
1823      * printing the summary line.
1824      */
1825     g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
1826     if (!print_bookmark(args->print_args->stream, bookmark_name,
1827                         bookmark_title))
1828       goto fail;
1829   } /* if (print_summary) */
1830
1831   if (args->print_args->print_dissections != print_dissections_none) {
1832     if (args->print_args->print_summary) {
1833       /* Separate the summary line from the tree with a blank line. */
1834       if (!print_line(args->print_args->stream, 0, ""))
1835         goto fail;
1836     }
1837
1838     /* Print the information in that tree. */
1839     if (!proto_tree_print(args->print_args, edt, args->print_args->stream))
1840       goto fail;
1841
1842     /* Print a blank line if we print anything after this (aka more than one packet). */
1843     args->print_separator = TRUE;
1844
1845     /* Print a header line if we print any more packet summaries */
1846     args->print_header_line = TRUE;
1847   }
1848
1849   if (args->print_args->print_hex) {
1850     /* Print the full packet data as hex. */
1851     if (!print_hex_data(args->print_args->stream, edt))
1852       goto fail;
1853
1854     /* Print a blank line if we print anything after this (aka more than one packet). */
1855     args->print_separator = TRUE;
1856
1857     /* Print a header line if we print any more packet summaries */
1858     args->print_header_line = TRUE;
1859   } /* if (args->print_args->print_dissections != print_dissections_none) */
1860
1861   epan_dissect_free(edt);
1862
1863   /* do we want to have a formfeed between each packet from now on? */
1864   if(args->print_args->print_formfeed) {
1865     args->print_formfeed = TRUE;
1866   }
1867
1868   return TRUE;
1869
1870 fail:
1871   epan_dissect_free(edt);
1872   return FALSE;
1873 }
1874
1875 cf_print_status_t
1876 cf_print_packets(capture_file *cf, print_args_t *print_args)
1877 {
1878   int         i;
1879   print_callback_args_t callback_args;
1880   gint        data_width;
1881   char        *cp;
1882   int         cp_off;
1883   int         column_len;
1884   int         line_len;
1885   psp_return_t ret;
1886
1887   callback_args.print_args = print_args;
1888   callback_args.print_header_line = TRUE;
1889   callback_args.header_line_buf = NULL;
1890   callback_args.header_line_buf_len = 256;
1891   callback_args.print_formfeed = FALSE;
1892   callback_args.print_separator = FALSE;
1893   callback_args.line_buf = NULL;
1894   callback_args.line_buf_len = 256;
1895   callback_args.col_widths = NULL;
1896
1897   if (!print_preamble(print_args->stream, cf->filename)) {
1898     destroy_print_stream(print_args->stream);
1899     return CF_PRINT_WRITE_ERROR;
1900   }
1901
1902   if (print_args->print_summary) {
1903     /* We're printing packet summaries.  Allocate the header line buffer
1904        and get the column widths. */
1905     callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
1906
1907     /* Find the widths for each of the columns - maximum of the
1908        width of the title and the width of the data - and construct
1909        a buffer with a line containing the column titles. */
1910     callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1911     cp = &callback_args.header_line_buf[0];
1912     line_len = 0;
1913     for (i = 0; i < cf->cinfo.num_cols; i++) {
1914       /* Don't pad the last column. */
1915       if (i == cf->cinfo.num_cols - 1)
1916         callback_args.col_widths[i] = 0;
1917       else {
1918         callback_args.col_widths[i] = strlen(cf->cinfo.col_title[i]);
1919         data_width = get_column_char_width(get_column_format(i));
1920         if (data_width > callback_args.col_widths[i])
1921           callback_args.col_widths[i] = data_width;
1922       }
1923
1924       /* Find the length of the string for this column. */
1925       column_len = strlen(cf->cinfo.col_title[i]);
1926       if (callback_args.col_widths[i] > column_len)
1927         column_len = callback_args.col_widths[i];
1928
1929       /* Make sure there's room in the line buffer for the column; if not,
1930          double its length. */
1931       line_len += column_len + 1;       /* "+1" for space */
1932       if (line_len > callback_args.header_line_buf_len) {
1933         cp_off = cp - callback_args.header_line_buf;
1934         callback_args.header_line_buf_len = 2 * line_len;
1935         callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
1936                                                   callback_args.header_line_buf_len + 1);
1937         cp = callback_args.header_line_buf + cp_off;
1938       }
1939
1940       /* Right-justify the packet number column. */
1941 /*      if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1942         sprintf(cp, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1943       else*/
1944         sprintf(cp, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1945       cp += column_len;
1946       if (i != cf->cinfo.num_cols - 1)
1947         *cp++ = ' ';
1948     }
1949     *cp = '\0';
1950
1951     /* Now start out the main line buffer with the same length as the
1952        header line buffer. */
1953     callback_args.line_buf_len = callback_args.header_line_buf_len;
1954     callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
1955   } /* if (print_summary) */
1956
1957   /* Iterate through the list of packets, printing the packets we were
1958      told to print. */
1959   ret = process_specified_packets(cf, &print_args->range, "Printing",
1960                                   "selected packets", TRUE, print_packet,
1961                                   &callback_args);
1962
1963   if (callback_args.header_line_buf != NULL)
1964     g_free(callback_args.header_line_buf);
1965   if (callback_args.line_buf != NULL)
1966     g_free(callback_args.line_buf);
1967   if (callback_args.col_widths != NULL)
1968     g_free(callback_args.col_widths);
1969
1970   switch (ret) {
1971
1972   case PSP_FINISHED:
1973     /* Completed successfully. */
1974     break;
1975
1976   case PSP_STOPPED:
1977     /* Well, the user decided to abort the printing.
1978
1979        XXX - note that what got generated before they did that
1980        will get printed if we're piping to a print program; we'd
1981        have to write to a file and then hand that to the print
1982        program to make it actually not print anything. */
1983     break;
1984
1985   case PSP_FAILED:
1986     /* Error while printing.
1987
1988        XXX - note that what got generated before they did that
1989        will get printed if we're piping to a print program; we'd
1990        have to write to a file and then hand that to the print
1991        program to make it actually not print anything. */
1992     destroy_print_stream(print_args->stream);
1993     return CF_PRINT_WRITE_ERROR;
1994   }
1995
1996   if (!print_finale(print_args->stream)) {
1997     destroy_print_stream(print_args->stream);
1998     return CF_PRINT_WRITE_ERROR;
1999   }
2000
2001   if (!destroy_print_stream(print_args->stream))
2002     return CF_PRINT_WRITE_ERROR;
2003
2004   return CF_PRINT_OK;
2005 }
2006
2007 static gboolean
2008 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2009                   union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2010                   void *argsp)
2011 {
2012   FILE *fh = argsp;
2013   epan_dissect_t *edt;
2014
2015   /* Create the protocol tree, but don't fill in the column information. */
2016   edt = epan_dissect_new(TRUE, TRUE);
2017   epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
2018
2019   /* Write out the information in that tree. */
2020   proto_tree_write_pdml(edt, fh);
2021
2022   epan_dissect_free(edt);
2023
2024   return !ferror(fh);
2025 }
2026
2027 cf_print_status_t
2028 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2029 {
2030   FILE        *fh;
2031   psp_return_t ret;
2032
2033   fh = eth_fopen(print_args->file, "w");
2034   if (fh == NULL)
2035     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2036
2037   write_pdml_preamble(fh);
2038   if (ferror(fh)) {
2039     fclose(fh);
2040     return CF_PRINT_WRITE_ERROR;
2041   }
2042
2043   /* Iterate through the list of packets, printing the packets we were
2044      told to print. */
2045   ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2046                                   "selected packets", TRUE,
2047                                   write_pdml_packet, fh);
2048
2049   switch (ret) {
2050
2051   case PSP_FINISHED:
2052     /* Completed successfully. */
2053     break;
2054
2055   case PSP_STOPPED:
2056     /* Well, the user decided to abort the printing. */
2057     break;
2058
2059   case PSP_FAILED:
2060     /* Error while printing. */
2061     fclose(fh);
2062     return CF_PRINT_WRITE_ERROR;
2063   }
2064
2065   write_pdml_finale(fh);
2066   if (ferror(fh)) {
2067     fclose(fh);
2068     return CF_PRINT_WRITE_ERROR;
2069   }
2070
2071   /* XXX - check for an error */
2072   fclose(fh);
2073
2074   return CF_PRINT_OK;
2075 }
2076
2077 static gboolean
2078 write_psml_packet(capture_file *cf, frame_data *fdata,
2079                   union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2080                   void *argsp)
2081 {
2082   FILE *fh = argsp;
2083   epan_dissect_t *edt;
2084
2085   /* Fill in the column information, but don't create the protocol tree. */
2086   edt = epan_dissect_new(FALSE, FALSE);
2087   epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2088   epan_dissect_fill_in_columns(edt);
2089
2090   /* Write out the information in that tree. */
2091   proto_tree_write_psml(edt, fh);
2092
2093   epan_dissect_free(edt);
2094
2095   return !ferror(fh);
2096 }
2097
2098 cf_print_status_t
2099 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2100 {
2101   FILE        *fh;
2102   psp_return_t ret;
2103
2104   fh = eth_fopen(print_args->file, "w");
2105   if (fh == NULL)
2106     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2107
2108   write_psml_preamble(fh);
2109   if (ferror(fh)) {
2110     fclose(fh);
2111     return CF_PRINT_WRITE_ERROR;
2112   }
2113
2114   /* Iterate through the list of packets, printing the packets we were
2115      told to print. */
2116   ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2117                                   "selected packets", TRUE,
2118                                   write_psml_packet, fh);
2119
2120   switch (ret) {
2121
2122   case PSP_FINISHED:
2123     /* Completed successfully. */
2124     break;
2125
2126   case PSP_STOPPED:
2127     /* Well, the user decided to abort the printing. */
2128     break;
2129
2130   case PSP_FAILED:
2131     /* Error while printing. */
2132     fclose(fh);
2133     return CF_PRINT_WRITE_ERROR;
2134   }
2135
2136   write_psml_finale(fh);
2137   if (ferror(fh)) {
2138     fclose(fh);
2139     return CF_PRINT_WRITE_ERROR;
2140   }
2141
2142   /* XXX - check for an error */
2143   fclose(fh);
2144
2145   return CF_PRINT_OK;
2146 }
2147
2148 static gboolean
2149 write_csv_packet(capture_file *cf, frame_data *fdata,
2150                  union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2151                  void *argsp)
2152 {
2153   FILE *fh = argsp;
2154   epan_dissect_t *edt;
2155
2156   /* Fill in the column information, but don't create the protocol tree. */
2157   edt = epan_dissect_new(FALSE, FALSE);
2158   epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2159   epan_dissect_fill_in_columns(edt);
2160
2161   /* Write out the information in that tree. */
2162   proto_tree_write_csv(edt, fh);
2163
2164   epan_dissect_free(edt);
2165
2166   return !ferror(fh);
2167 }
2168
2169 cf_print_status_t
2170 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2171 {
2172   FILE        *fh;
2173   psp_return_t ret;
2174
2175   fh = eth_fopen(print_args->file, "w");
2176   if (fh == NULL)
2177     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2178
2179   write_csv_preamble(fh);
2180   if (ferror(fh)) {
2181     fclose(fh);
2182     return CF_PRINT_WRITE_ERROR;
2183   }
2184
2185   /* Iterate through the list of packets, printing the packets we were
2186      told to print. */
2187   ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2188                                   "selected packets", TRUE,
2189                                   write_csv_packet, fh);
2190
2191   switch (ret) {
2192
2193   case PSP_FINISHED:
2194     /* Completed successfully. */
2195     break;
2196
2197   case PSP_STOPPED:
2198     /* Well, the user decided to abort the printing. */
2199     break;
2200
2201   case PSP_FAILED:
2202     /* Error while printing. */
2203     fclose(fh);
2204     return CF_PRINT_WRITE_ERROR;
2205   }
2206
2207   write_csv_finale(fh);
2208   if (ferror(fh)) {
2209     fclose(fh);
2210     return CF_PRINT_WRITE_ERROR;
2211   }
2212
2213   /* XXX - check for an error */
2214   fclose(fh);
2215
2216   return CF_PRINT_OK;
2217 }
2218
2219 /* Scan through the packet list and change all columns that use the
2220    "command-line-specified" time stamp format to use the current
2221    value of that format. */
2222 void
2223 cf_change_time_formats(capture_file *cf)
2224 {
2225   frame_data *fdata;
2226   progdlg_t  *progbar = NULL;
2227   gboolean    stop_flag;
2228   int         count;
2229   int         row;
2230   int         i;
2231   float       progbar_val;
2232   GTimeVal    start_time;
2233   gchar       status_str[100];
2234   int         progbar_nextstep;
2235   int         progbar_quantum;
2236   int         first, last;
2237   gboolean    sorted_by_frame_column;
2238
2239
2240   /* adjust timestamp precision if auto is selected */
2241   cf_timestamp_auto_precision(cf);
2242
2243   /* Are there any columns with time stamps in the "command-line-specified"
2244      format?
2245
2246      XXX - we have to force the "column is writable" flag on, as it
2247      might be off from the last frame that was dissected. */
2248   col_set_writable(&cf->cinfo, TRUE);
2249   if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
2250     /* No, there aren't any columns in that format, so we have no work
2251        to do. */
2252     return;
2253   }
2254   first = cf->cinfo.col_first[COL_CLS_TIME];
2255   g_assert(first >= 0);
2256   last = cf->cinfo.col_last[COL_CLS_TIME];
2257
2258   /* Freeze the packet list while we redo it, so we don't get any
2259      screen updates while it happens. */
2260   packet_list_freeze();
2261
2262   /* Update the progress bar when it gets to this value. */
2263   progbar_nextstep = 0;
2264   /* When we reach the value that triggers a progress bar update,
2265      bump that value by this amount. */
2266   progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2267   /* Count of packets at which we've looked. */
2268   count = 0;
2269   /* Progress so far. */
2270   progbar_val = 0.0;
2271
2272   /*  If the rows are currently sorted by the frame column then we know
2273    *  the row number of each packet: it's the row number of the previously
2274    *  displayed packet + 1.
2275    *
2276    *  Otherwise, if the display is sorted by a different column then we have
2277    *  to use the O(N) packet_list_find_row_from_data() (thus making the job
2278    *  of changing the time display format O(N**2)).
2279    *
2280    *  (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
2281    *  the row number and walks that many elements down the clist to find
2282    *  the appropriate element.)
2283    */
2284   sorted_by_frame_column = FALSE;
2285   for (i = 0; i < cf->cinfo.num_cols; i++) {
2286     if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2287     {
2288       sorted_by_frame_column = (i == packet_list_get_sort_column());
2289       break;
2290     }
2291   }
2292
2293   stop_flag = FALSE;
2294   g_get_current_time(&start_time);
2295
2296   /* Iterate through the list of packets, checking whether the packet
2297      is in a row of the summary list and, if so, whether there are
2298      any columns that show the time in the "command-line-specified"
2299      format and, if so, update that row. */
2300   for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
2301     /* Create the progress bar if necessary.
2302        We check on every iteration of the loop, so that it takes no
2303        longer than the standard time to create it (otherwise, for a
2304        large file, we might take considerably longer than that standard
2305        time in order to get to the next progress bar step). */
2306     if (progbar == NULL)
2307       progbar = delayed_create_progress_dlg("Changing", "time display",
2308         TRUE, &stop_flag, &start_time, progbar_val);
2309
2310     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2311        when we update it, we have to run the GTK+ main loop to get it
2312        to repaint what's pending, and doing so may involve an "ioctl()"
2313        to see if there's any pending input from an X server, and doing
2314        that for every packet can be costly, especially on a big file. */
2315     if (count >= progbar_nextstep) {
2316       /* let's not divide by zero. I should never be started
2317        * with count == 0, so let's assert that
2318        */
2319       g_assert(cf->count > 0);
2320
2321       progbar_val = (gfloat) count / cf->count;
2322
2323       if (progbar != NULL) {
2324         g_snprintf(status_str, sizeof(status_str),
2325                    "%4u of %u packets", count, cf->count);
2326         update_progress_dlg(progbar, progbar_val, status_str);
2327       }
2328
2329       progbar_nextstep += progbar_quantum;
2330     }
2331
2332     if (stop_flag) {
2333       /* Well, the user decided to abort the redisplay.  Just stop.
2334
2335          XXX - this leaves the time field in the old format in
2336          frames we haven't yet processed.  So it goes; should we
2337          simply not offer them the option of stopping? */
2338       break;
2339     }
2340
2341     count++;
2342
2343     /* Find what row this packet is in. */
2344     if (!sorted_by_frame_column) {
2345       /* This function is O(N), so we try to avoid using it... */
2346       row = packet_list_find_row_from_data(fdata);
2347     } else {
2348       /* ...which we do by maintaining a count of packets that are
2349          being displayed (i.e., that have passed the display filter),
2350          and using the current value of that count as the row number
2351          (which is why we can only do it when the display is sorted
2352          by the frame number). */
2353       if (fdata->flags.passed_dfilter)
2354         row++;
2355       else
2356         continue;
2357     }
2358
2359     if (row != -1) {
2360       /* This packet is in the summary list, on row "row". */
2361
2362       for (i = first; i <= last; i++) {
2363         if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2364           /* This is one of the columns that shows the time in
2365              "command-line-specified" format; update it. */
2366           cf->cinfo.col_buf[i][0] = '\0';
2367           col_set_cls_time(fdata, &cf->cinfo, i);
2368           packet_list_set_text(row, i, cf->cinfo.col_data[i]);
2369         }
2370       }
2371     }
2372   }
2373
2374   /* We're done redisplaying the packets; destroy the progress bar if it
2375      was created. */
2376   if (progbar != NULL)
2377     destroy_progress_dlg(progbar);
2378
2379   /* Set the column widths of those columns that show the time in
2380      "command-line-specified" format. */
2381   for (i = first; i <= last; i++) {
2382     if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2383       packet_list_set_cls_time_width(i);
2384     }
2385   }
2386
2387   /* Unfreeze the packet list. */
2388   packet_list_thaw();
2389 }
2390
2391 typedef struct {
2392         const char      *string;
2393         size_t          string_len;
2394         capture_file    *cf;
2395         gboolean        frame_matched;
2396 } match_data;
2397
2398 gboolean
2399 cf_find_packet_protocol_tree(capture_file *cf, const char *string)
2400 {
2401   match_data            mdata;
2402
2403   mdata.string = string;
2404   mdata.string_len = strlen(string);
2405   return find_packet(cf, match_protocol_tree, &mdata);
2406 }
2407
2408 static gboolean
2409 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2410 {
2411   match_data            *mdata = criterion;
2412   epan_dissect_t        *edt;
2413
2414   /* Construct the protocol tree, including the displayed text */
2415   edt = epan_dissect_new(TRUE, TRUE);
2416   /* We don't need the column information */
2417   epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2418
2419   /* Iterate through all the nodes, seeing if they have text that matches. */
2420   mdata->cf = cf;
2421   mdata->frame_matched = FALSE;
2422   proto_tree_children_foreach(edt->tree, match_subtree_text, mdata);
2423   epan_dissect_free(edt);
2424   return mdata->frame_matched;
2425 }
2426
2427 static void
2428 match_subtree_text(proto_node *node, gpointer data)
2429 {
2430   match_data    *mdata = (match_data*) data;
2431   const gchar   *string = mdata->string;
2432   size_t        string_len = mdata->string_len;
2433   capture_file  *cf = mdata->cf;
2434   field_info    *fi = PITEM_FINFO(node);
2435   gchar         label_str[ITEM_LABEL_LENGTH];
2436   gchar         *label_ptr;
2437   size_t        label_len;
2438   guint32       i;
2439   guint8        c_char;
2440   size_t        c_match = 0;
2441
2442   if (mdata->frame_matched) {
2443     /* We already had a match; don't bother doing any more work. */
2444     return;
2445   }
2446
2447   /* Don't match invisible entries. */
2448   if (PROTO_ITEM_IS_HIDDEN(node))
2449     return;
2450
2451   /* was a free format label produced? */
2452   if (fi->rep) {
2453     label_ptr = fi->rep->representation;
2454   } else {
2455     /* no, make a generic label */
2456     label_ptr = label_str;
2457     proto_item_fill_label(fi, label_str);
2458   }
2459
2460   /* Does that label match? */
2461   label_len = strlen(label_ptr);
2462   for (i = 0; i < label_len; i++) {
2463     c_char = label_ptr[i];
2464     if (cf->case_type)
2465       c_char = toupper(c_char);
2466     if (c_char == string[c_match]) {
2467       c_match++;
2468       if (c_match == string_len) {
2469         /* No need to look further; we have a match */
2470         mdata->frame_matched = TRUE;
2471         return;
2472       }
2473     } else
2474       c_match = 0;
2475   }
2476
2477   /* Recurse into the subtree, if it exists */
2478   if (node->first_child != NULL)
2479     proto_tree_children_foreach(node, match_subtree_text, mdata);
2480 }
2481
2482 gboolean
2483 cf_find_packet_summary_line(capture_file *cf, const char *string)
2484 {
2485   match_data            mdata;
2486
2487   mdata.string = string;
2488   mdata.string_len = strlen(string);
2489   return find_packet(cf, match_summary_line, &mdata);
2490 }
2491
2492 static gboolean
2493 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2494 {
2495   match_data            *mdata = criterion;
2496   const gchar           *string = mdata->string;
2497   size_t                string_len = mdata->string_len;
2498   epan_dissect_t        *edt;
2499   const char            *info_column;
2500   size_t                info_column_len;
2501   gboolean              frame_matched = FALSE;
2502   gint                  colx;
2503   guint32               i;
2504   guint8                c_char;
2505   size_t                c_match = 0;
2506
2507   /* Don't bother constructing the protocol tree */
2508   edt = epan_dissect_new(FALSE, FALSE);
2509   /* Get the column information */
2510   epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2511
2512   /* Find the Info column */
2513   for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2514     if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2515       /* Found it.  See if we match. */
2516       info_column = edt->pi.cinfo->col_data[colx];
2517       info_column_len = strlen(info_column);
2518       for (i = 0; i < info_column_len; i++) {
2519         c_char = info_column[i];
2520         if (cf->case_type)
2521           c_char = toupper(c_char);
2522         if (c_char == string[c_match]) {
2523           c_match++;
2524           if (c_match == string_len) {
2525             frame_matched = TRUE;
2526             break;
2527           }
2528         } else
2529           c_match = 0;
2530       }
2531       break;
2532     }
2533   }
2534   epan_dissect_free(edt);
2535   return frame_matched;
2536 }
2537
2538 typedef struct {
2539         const guint8 *data;
2540         size_t data_len;
2541 } cbs_t;        /* "Counted byte string" */
2542
2543 gboolean
2544 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
2545 {
2546   cbs_t info;
2547
2548   info.data = string;
2549   info.data_len = string_size;
2550
2551   /* String or hex search? */
2552   if (cf->string) {
2553     /* String search - what type of string? */
2554     switch (cf->scs_type) {
2555
2556     case SCS_ASCII_AND_UNICODE:
2557       return find_packet(cf, match_ascii_and_unicode, &info);
2558
2559     case SCS_ASCII:
2560       return find_packet(cf, match_ascii, &info);
2561
2562     case SCS_UNICODE:
2563       return find_packet(cf, match_unicode, &info);
2564
2565     default:
2566       g_assert_not_reached();
2567       return FALSE;
2568     }
2569   } else
2570     return find_packet(cf, match_binary, &info);
2571 }
2572
2573 static gboolean
2574 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2575 {
2576   cbs_t         *info = criterion;
2577   const char    *ascii_text = info->data;
2578   size_t        textlen = info->data_len;
2579   gboolean      frame_matched;
2580   guint32       buf_len;
2581   guint32       i;
2582   guint8        c_char;
2583   size_t        c_match = 0;
2584
2585   frame_matched = FALSE;
2586   buf_len = fdata->pkt_len;
2587   for (i = 0; i < buf_len; i++) {
2588     c_char = cf->pd[i];
2589     if (cf->case_type)
2590       c_char = toupper(c_char);
2591     if (c_char != 0) {
2592       if (c_char == ascii_text[c_match]) {
2593         c_match++;
2594         if (c_match == textlen) {
2595           frame_matched = TRUE;
2596           break;
2597         }
2598       } else
2599         c_match = 0;
2600     }
2601   }
2602   return frame_matched;
2603 }
2604
2605 static gboolean
2606 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2607 {
2608   cbs_t         *info = criterion;
2609   const char    *ascii_text = info->data;
2610   size_t        textlen = info->data_len;
2611   gboolean      frame_matched;
2612   guint32       buf_len;
2613   guint32       i;
2614   guint8        c_char;
2615   size_t        c_match = 0;
2616
2617   frame_matched = FALSE;
2618   buf_len = fdata->pkt_len;
2619   for (i = 0; i < buf_len; i++) {
2620     c_char = cf->pd[i];
2621     if (cf->case_type)
2622       c_char = toupper(c_char);
2623     if (c_char == ascii_text[c_match]) {
2624       c_match++;
2625       if (c_match == textlen) {
2626         frame_matched = TRUE;
2627         break;
2628       }
2629     } else
2630       c_match = 0;
2631   }
2632   return frame_matched;
2633 }
2634
2635 static gboolean
2636 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2637 {
2638   cbs_t         *info = criterion;
2639   const char    *ascii_text = info->data;
2640   size_t        textlen = info->data_len;
2641   gboolean      frame_matched;
2642   guint32       buf_len;
2643   guint32       i;
2644   guint8        c_char;
2645   size_t        c_match = 0;
2646
2647   frame_matched = FALSE;
2648   buf_len = fdata->pkt_len;
2649   for (i = 0; i < buf_len; i++) {
2650     c_char = cf->pd[i];
2651     if (cf->case_type)
2652       c_char = toupper(c_char);
2653     if (c_char == ascii_text[c_match]) {
2654       c_match++;
2655       i++;
2656       if (c_match == textlen) {
2657         frame_matched = TRUE;
2658         break;
2659       }
2660     } else
2661       c_match = 0;
2662   }
2663   return frame_matched;
2664 }
2665
2666 static gboolean
2667 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
2668 {
2669   cbs_t         *info = criterion;
2670   const guint8  *binary_data = info->data;
2671   size_t        datalen = info->data_len;
2672   gboolean      frame_matched;
2673   guint32       buf_len;
2674   guint32       i;
2675   size_t        c_match = 0;
2676
2677   frame_matched = FALSE;
2678   buf_len = fdata->pkt_len;
2679   for (i = 0; i < buf_len; i++) {
2680     if (cf->pd[i] == binary_data[c_match]) {
2681       c_match++;
2682       if (c_match == datalen) {
2683         frame_matched = TRUE;
2684         break;
2685       }
2686     } else
2687       c_match = 0;
2688   }
2689   return frame_matched;
2690 }
2691
2692 gboolean
2693 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
2694 {
2695   return find_packet(cf, match_dfilter, sfcode);
2696 }
2697
2698 static gboolean
2699 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
2700 {
2701   dfilter_t             *sfcode = criterion;
2702   epan_dissect_t        *edt;
2703   gboolean              frame_matched;
2704
2705   edt = epan_dissect_new(TRUE, FALSE);
2706   epan_dissect_prime_dfilter(edt, sfcode);
2707   epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2708   frame_matched = dfilter_apply_edt(sfcode, edt);
2709   epan_dissect_free(edt);
2710   return frame_matched;
2711 }
2712
2713 static gboolean
2714 find_packet(capture_file *cf,
2715             gboolean (*match_function)(capture_file *, frame_data *, void *),
2716             void *criterion)
2717 {
2718   frame_data *start_fd;
2719   frame_data *fdata;
2720   frame_data *new_fd = NULL;
2721   progdlg_t  *progbar = NULL;
2722   gboolean    stop_flag;
2723   int         count;
2724   int         err;
2725   gchar      *err_info;
2726   int         row;
2727   float       progbar_val;
2728   GTimeVal    start_time;
2729   gchar       status_str[100];
2730   int         progbar_nextstep;
2731   int         progbar_quantum;
2732   char       *title;
2733
2734   start_fd = cf->current_frame;
2735   if (start_fd != NULL)  {
2736     /* Iterate through the list of packets, starting at the packet we've
2737        picked, calling a routine to run the filter on the packet, see if
2738        it matches, and stop if so.  */
2739     count = 0;
2740     fdata = start_fd;
2741
2742     /* Update the progress bar when it gets to this value. */
2743     progbar_nextstep = 0;
2744     /* When we reach the value that triggers a progress bar update,
2745        bump that value by this amount. */
2746     progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2747     /* Progress so far. */
2748     progbar_val = 0.0;
2749
2750     stop_flag = FALSE;
2751     g_get_current_time(&start_time);
2752
2753     fdata = start_fd;
2754     title = cf->sfilter?cf->sfilter:"";
2755     for (;;) {
2756       /* Create the progress bar if necessary.
2757          We check on every iteration of the loop, so that it takes no
2758          longer than the standard time to create it (otherwise, for a
2759          large file, we might take considerably longer than that standard
2760          time in order to get to the next progress bar step). */
2761       if (progbar == NULL)
2762          progbar = delayed_create_progress_dlg("Searching", title,
2763            FALSE, &stop_flag, &start_time, progbar_val);
2764
2765       /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2766          when we update it, we have to run the GTK+ main loop to get it
2767          to repaint what's pending, and doing so may involve an "ioctl()"
2768          to see if there's any pending input from an X server, and doing
2769          that for every packet can be costly, especially on a big file. */
2770       if (count >= progbar_nextstep) {
2771         /* let's not divide by zero. I should never be started
2772          * with count == 0, so let's assert that
2773          */
2774         g_assert(cf->count > 0);
2775
2776         progbar_val = (gfloat) count / cf->count;
2777
2778         if (progbar != NULL) {
2779           g_snprintf(status_str, sizeof(status_str),
2780                      "%4u of %u packets", count, cf->count);
2781           update_progress_dlg(progbar, progbar_val, status_str);
2782         }
2783
2784         progbar_nextstep += progbar_quantum;
2785       }
2786
2787       if (stop_flag) {
2788         /* Well, the user decided to abort the search.  Go back to the
2789            frame where we started. */
2790         new_fd = start_fd;
2791         break;
2792       }
2793
2794       /* Go past the current frame. */
2795       if (cf->sbackward) {
2796         /* Go on to the previous frame. */
2797         fdata = fdata->prev;
2798         if (fdata == NULL) {
2799           /*
2800            * XXX - other apps have a bit more of a detailed message
2801            * for this, and instead of offering "OK" and "Cancel",
2802            * they offer things such as "Continue" and "Cancel";
2803            * we need an API for popping up alert boxes with
2804            * {Verb} and "Cancel".
2805            */
2806
2807           if (prefs.gui_find_wrap)
2808           {
2809               simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2810                             "%sBeginning of capture exceeded!%s\n\n"
2811                             "Search is continued from the end of the capture.",
2812                             simple_dialog_primary_start(), simple_dialog_primary_end());
2813               fdata = cf->plist_end;    /* wrap around */
2814           }
2815           else
2816           {
2817               simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2818                             "%sBeginning of capture exceeded!%s\n\n"
2819                             "Try searching forwards.",
2820                             simple_dialog_primary_start(), simple_dialog_primary_end());
2821               fdata = start_fd;        /* stay on previous packet */
2822           }
2823         }
2824       } else {
2825         /* Go on to the next frame. */
2826         fdata = fdata->next;
2827         if (fdata == NULL) {
2828           if (prefs.gui_find_wrap)
2829           {
2830               simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2831                             "%sEnd of capture exceeded!%s\n\n"
2832                             "Search is continued from the start of the capture.",
2833                             simple_dialog_primary_start(), simple_dialog_primary_end());
2834               fdata = cf->plist;        /* wrap around */
2835           }
2836           else
2837           {
2838               simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2839                             "%sEnd of capture exceeded!%s\n\n"
2840                             "Try searching backwards.",
2841                             simple_dialog_primary_start(), simple_dialog_primary_end());
2842               fdata = start_fd;     /* stay on previous packet */
2843           }
2844         }
2845       }
2846
2847       count++;
2848
2849       /* Is this packet in the display? */
2850       if (fdata->flags.passed_dfilter) {
2851         /* Yes.  Load its data. */
2852         if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
2853                         cf->pd, fdata->cap_len, &err, &err_info)) {
2854           /* Read error.  Report the error, and go back to the frame
2855              where we started. */
2856           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2857                         cf_read_error_message(err, err_info), cf->filename);
2858           new_fd = start_fd;
2859           break;
2860         }
2861
2862         /* Does it match the search criterion? */
2863         if ((*match_function)(cf, fdata, criterion)) {
2864           new_fd = fdata;
2865           break;        /* found it! */
2866         }
2867       }
2868
2869       if (fdata == start_fd) {
2870         /* We're back to the frame we were on originally, and that frame
2871            doesn't match the search filter.  The search failed. */
2872         break;
2873       }
2874     }
2875
2876     /* We're done scanning the packets; destroy the progress bar if it
2877        was created. */
2878     if (progbar != NULL)
2879       destroy_progress_dlg(progbar);
2880   }
2881
2882   if (new_fd != NULL) {
2883     /* We found a frame.  Find what row it's in. */
2884     row = packet_list_find_row_from_data(new_fd);
2885     g_assert(row != -1);
2886
2887     /* Select that row, make it the focus row, and make it visible. */
2888     packet_list_set_selected_row(row);
2889     return TRUE;        /* success */
2890   } else
2891     return FALSE;       /* failure */
2892 }
2893
2894 gboolean
2895 cf_goto_frame(capture_file *cf, guint fnumber)
2896 {
2897   frame_data *fdata;
2898   int row;
2899
2900   for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
2901     ;
2902
2903   if (fdata == NULL) {
2904     /* we didn't find a packet with that packet number */
2905     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2906                   "There is no packet with the packet number %u.", fnumber);
2907     return FALSE;       /* we failed to go to that packet */
2908   }
2909   if (!fdata->flags.passed_dfilter) {
2910     /* that packet currently isn't displayed */
2911     /* XXX - add it to the set of displayed packets? */
2912     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2913                   "The packet number %u isn't currently being displayed.", fnumber);
2914     return FALSE;       /* we failed to go to that packet */
2915   }
2916
2917   /* We found that packet, and it's currently being displayed.
2918      Find what row it's in. */
2919   row = packet_list_find_row_from_data(fdata);
2920   g_assert(row != -1);
2921
2922   /* Select that row, make it the focus row, and make it visible. */
2923   packet_list_set_selected_row(row);
2924   return TRUE;  /* we got to that packet */
2925 }
2926
2927 gboolean
2928 cf_goto_top_frame(capture_file *cf)
2929 {
2930   frame_data *fdata;
2931   int row;
2932   frame_data *lowest_fdata = NULL;
2933
2934   for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2935     if (fdata->flags.passed_dfilter) {
2936         lowest_fdata = fdata;
2937         break;
2938     }
2939   }
2940
2941   if (lowest_fdata == NULL) {
2942       return FALSE;
2943   }
2944
2945   /* We found that packet, and it's currently being displayed.
2946      Find what row it's in. */
2947   row = packet_list_find_row_from_data(lowest_fdata);
2948   g_assert(row != -1);
2949
2950   /* Select that row, make it the focus row, and make it visible. */
2951   packet_list_set_selected_row(row);
2952   return TRUE;  /* we got to that packet */
2953 }
2954
2955 gboolean
2956 cf_goto_bottom_frame(capture_file *cf)
2957 {
2958   frame_data *fdata;
2959   int row;
2960   frame_data *highest_fdata = NULL;
2961
2962   for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2963     if (fdata->flags.passed_dfilter) {
2964         highest_fdata = fdata;
2965     }
2966   }
2967
2968   if (highest_fdata == NULL) {
2969       return FALSE;
2970   }
2971
2972   /* We found that packet, and it's currently being displayed.
2973      Find what row it's in. */
2974   row = packet_list_find_row_from_data(highest_fdata);
2975   g_assert(row != -1);
2976
2977   /* Select that row, make it the focus row, and make it visible. */
2978   packet_list_set_selected_row(row);
2979   return TRUE;  /* we got to that packet */
2980 }
2981
2982 /*
2983  * Go to frame specified by currently selected protocol tree item.
2984  */
2985 gboolean
2986 cf_goto_framenum(capture_file *cf)
2987 {
2988   header_field_info       *hfinfo;
2989   guint32                 framenum;
2990
2991   if (cf->finfo_selected) {
2992     hfinfo = cf->finfo_selected->hfinfo;
2993     g_assert(hfinfo);
2994     if (hfinfo->type == FT_FRAMENUM) {
2995       framenum = fvalue_get_integer(&cf->finfo_selected->value);
2996       if (framenum != 0)
2997         return cf_goto_frame(cf, framenum);
2998       }
2999   }
3000
3001   return FALSE;
3002 }
3003
3004 /* Select the packet on a given row. */
3005 void
3006 cf_select_packet(capture_file *cf, int row)
3007 {
3008   frame_data *fdata;
3009   int err;
3010   gchar *err_info;
3011
3012   /* Get the frame data struct pointer for this frame */
3013   fdata = (frame_data *)packet_list_get_row_data(row);
3014
3015   if (fdata == NULL) {
3016     /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3017        the first entry is added to it by "real_insert_row()", that row
3018        is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
3019        our version and the vanilla GTK+ version).
3020
3021        This means that a "select-row" signal is emitted; this causes
3022        "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3023        to be called.
3024
3025        "cf_select_packet()" fetches, above, the data associated with the
3026        row that was selected; however, as "gtk_clist_append()", which
3027        called "real_insert_row()", hasn't yet returned, we haven't yet
3028        associated any data with that row, so we get back a null pointer.
3029
3030        We can't assume that there's only one frame in the frame list,
3031        either, as we may be filtering the display.
3032
3033        We therefore assume that, if "row" is 0, i.e. the first row
3034        is being selected, and "cf->first_displayed" equals
3035        "cf->last_displayed", i.e. there's only one frame being
3036        displayed, that frame is the frame we want.
3037
3038        This means we have to set "cf->first_displayed" and
3039        "cf->last_displayed" before adding the row to the
3040        GtkCList; see the comment in "add_packet_to_packet_list()". */
3041
3042        if (row == 0 && cf->first_displayed == cf->last_displayed)
3043          fdata = cf->first_displayed;
3044   }
3045
3046   /* If fdata _still_ isn't set simply give up. */
3047   if (fdata == NULL) {
3048     return;
3049   }
3050
3051   /* Get the data in that frame. */
3052   if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
3053                        cf->pd, fdata->cap_len, &err, &err_info)) {
3054     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3055                   cf_read_error_message(err, err_info), cf->filename);
3056     return;
3057   }
3058
3059   /* Record that this frame is the current frame. */
3060   cf->current_frame = fdata;
3061
3062   /* Create the logical protocol tree. */
3063   if (cf->edt != NULL) {
3064     epan_dissect_free(cf->edt);
3065     cf->edt = NULL;
3066   }
3067   /* We don't need the columns here. */
3068   cf->edt = epan_dissect_new(TRUE, TRUE);
3069   epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3070           NULL);
3071
3072   cf_callback_invoke(cf_cb_packet_selected, cf);
3073 }
3074
3075 /* Unselect the selected packet, if any. */
3076 void
3077 cf_unselect_packet(capture_file *cf)
3078 {
3079   /* Destroy the epan_dissect_t for the unselected packet. */
3080   if (cf->edt != NULL) {
3081     epan_dissect_free(cf->edt);
3082     cf->edt = NULL;
3083   }
3084
3085   /* No packet is selected. */
3086   cf->current_frame = NULL;
3087
3088   cf_callback_invoke(cf_cb_packet_unselected, cf);
3089
3090   /* No protocol tree means no selected field. */
3091   cf_unselect_field(cf);
3092 }
3093
3094 /* Unset the selected protocol tree field, if any. */
3095 void
3096 cf_unselect_field(capture_file *cf)
3097 {
3098   cf->finfo_selected = NULL;
3099
3100   cf_callback_invoke(cf_cb_field_unselected, cf);
3101 }
3102
3103 /*
3104  * Mark a particular frame.
3105  */
3106 void
3107 cf_mark_frame(capture_file *cf, frame_data *frame)
3108 {
3109   if (! frame->flags.marked) {
3110     frame->flags.marked = TRUE;
3111     if (cf->count > cf->marked_count)
3112       cf->marked_count++;
3113   }
3114 }
3115
3116 /*
3117  * Unmark a particular frame.
3118  */
3119 void
3120 cf_unmark_frame(capture_file *cf, frame_data *frame)
3121 {
3122   if (frame->flags.marked) {
3123     frame->flags.marked = FALSE;
3124     if (cf->marked_count > 0)
3125       cf->marked_count--;
3126   }
3127 }
3128
3129 typedef struct {
3130   wtap_dumper *pdh;
3131   const char  *fname;
3132 } save_callback_args_t;
3133
3134 /*
3135  * Save a capture to a file, in a particular format, saving either
3136  * all packets, all currently-displayed packets, or all marked packets.
3137  *
3138  * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3139  * up a message box for the failure.
3140  */
3141 static gboolean
3142 save_packet(capture_file *cf _U_, frame_data *fdata,
3143             union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3144             void *argsp)
3145 {
3146   save_callback_args_t *args = argsp;
3147   struct wtap_pkthdr hdr;
3148   int           err;
3149
3150   /* init the wtap header for saving */
3151   hdr.ts         = *(struct wtap_nstime *) &fdata->abs_ts;
3152   hdr.caplen     = fdata->cap_len;
3153   hdr.len        = fdata->pkt_len;
3154   hdr.pkt_encap  = fdata->lnk_t;
3155
3156   /* and save the packet */
3157   if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3158     cf_write_failure_alert_box(args->fname, err);
3159     return FALSE;
3160   }
3161   return TRUE;
3162 }
3163
3164 cf_status_t
3165 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3166 {
3167   gchar        *from_filename;
3168   int           err;
3169   gboolean      do_copy;
3170   wtap_dumper  *pdh;
3171   save_callback_args_t callback_args;
3172
3173   cf_callback_invoke(cf_cb_file_safe_started, (gpointer) fname);
3174
3175   /* don't write over an existing file. */
3176   /* this should've been already checked by our caller, just to be sure... */
3177   if (file_exists(fname)) {
3178     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3179       "%sCapture file: \"%s\" already exists!%s\n\n"
3180       "Please choose a different filename.",
3181       simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3182     goto fail;
3183   }
3184
3185   packet_range_process_init(range);
3186
3187
3188   if (packet_range_process_all(range) && save_format == cf->cd_t) {
3189     /* We're not filtering packets, and we're saving it in the format
3190        it's already in, so we can just move or copy the raw data. */
3191
3192     if (cf->is_tempfile) {
3193       /* The file being saved is a temporary file from a live
3194          capture, so it doesn't need to stay around under that name;
3195          first, try renaming the capture buffer file to the new name. */
3196 #ifndef _WIN32
3197       if (eth_rename(cf->filename, fname) == 0) {
3198         /* That succeeded - there's no need to copy the source file. */
3199         from_filename = NULL;
3200         do_copy = FALSE;
3201       } else {
3202         if (errno == EXDEV) {
3203           /* They're on different file systems, so we have to copy the
3204              file. */
3205           do_copy = TRUE;
3206           from_filename = cf->filename;
3207         } else {
3208           /* The rename failed, but not because they're on different
3209              file systems - put up an error message.  (Or should we
3210              just punt and try to copy?  The only reason why I'd
3211              expect the rename to fail and the copy to succeed would
3212              be if we didn't have permission to remove the file from
3213              the temporary directory, and that might be fixable - but
3214              is it worth requiring the user to go off and fix it?) */
3215           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3216                                 file_rename_error_message(errno), fname);
3217           goto fail;
3218         }
3219       }
3220 #else
3221       do_copy = TRUE;
3222       from_filename = cf->filename;
3223 #endif
3224     } else {
3225       /* It's a permanent file, so we should copy it, and not remove the
3226          original. */
3227       do_copy = TRUE;
3228       from_filename = cf->filename;
3229     }
3230
3231     if (do_copy) {
3232       /* Copy the file, if we haven't moved it. */
3233       if (!copy_binary_file(from_filename, fname))
3234         goto fail;
3235     }
3236   } else {
3237     /* Either we're filtering packets, or we're saving in a different
3238        format; we can't do that by copying or moving the capture file,
3239        we have to do it by writing the packets out in Wiretap. */
3240     pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
3241                 compressed, &err);
3242     if (pdh == NULL) {
3243       cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3244       goto fail;
3245     }
3246
3247     /* XXX - we let the user save a subset of the packets.
3248
3249        If we do that, should we make that file the current file?  If so,
3250        it means we can no longer get at the other packets.  What does
3251        NetMon do? */
3252
3253     /* Iterate through the list of packets, processing the packets we were
3254        told to process.
3255
3256        XXX - we've already called "packet_range_process_init(range)", but
3257        "process_specified_packets()" will do it again.  Fortunately,
3258        that's harmless in this case, as we haven't done anything to
3259        "range" since we initialized it. */
3260     callback_args.pdh = pdh;
3261     callback_args.fname = fname;
3262     switch (process_specified_packets(cf, range, "Saving", "selected packets",
3263                                       TRUE, save_packet, &callback_args)) {
3264
3265     case PSP_FINISHED:
3266       /* Completed successfully. */
3267       break;
3268
3269     case PSP_STOPPED:
3270       /* The user decided to abort the saving.
3271          XXX - remove the output file? */
3272       break;
3273
3274     case PSP_FAILED:
3275       /* Error while saving. */
3276       wtap_dump_close(pdh, &err);
3277       goto fail;
3278     }
3279
3280     if (!wtap_dump_close(pdh, &err)) {
3281       cf_close_failure_alert_box(fname, err);
3282       goto fail;
3283     }
3284   }
3285
3286   cf_callback_invoke(cf_cb_file_safe_finished, NULL);
3287
3288   if (packet_range_process_all(range)) {
3289     /* We saved the entire capture, not just some packets from it.
3290        Open and read the file we saved it to.
3291
3292        XXX - this is somewhat of a waste; we already have the
3293        packets, all this gets us is updated file type information
3294        (which we could just stuff into "cf"), and having the new
3295        file be the one we have opened and from which we're reading
3296        the data, and it means we have to spend time opening and
3297        reading the file, which could be a significant amount of
3298        time if the file is large. */
3299     cf->user_saved = TRUE;
3300
3301     if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3302       /* XXX - report errors if this fails?
3303          What should we return if it fails or is aborted? */
3304       switch (cf_read(cf)) {
3305
3306       case CF_READ_OK:
3307       case CF_READ_ERROR:
3308         /* Just because we got an error, that doesn't mean we were unable
3309            to read any of the file; we handle what we could get from the
3310            file. */
3311         break;
3312
3313       case CF_READ_ABORTED:
3314         /* The user bailed out of re-reading the capture file; the
3315            capture file has been closed - just return (without
3316            changing any menu settings; "cf_close()" set them
3317            correctly for the "no capture file open" state). */
3318         break;
3319       }
3320       cf_callback_invoke(cf_cb_file_safe_reload_finished, NULL);
3321     }
3322   }
3323   return CF_OK;
3324
3325 fail:
3326   cf_callback_invoke(cf_cb_file_safe_failed, NULL);
3327   return CF_ERROR;
3328 }
3329
3330 static void
3331 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3332                           gboolean for_writing, int file_type)
3333 {
3334   if (err < 0) {
3335     /* Wiretap error. */
3336     switch (err) {
3337
3338     case WTAP_ERR_NOT_REGULAR_FILE:
3339       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3340                     "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3341                     filename);
3342       break;
3343
3344     case WTAP_ERR_RANDOM_OPEN_PIPE:
3345       /* Seen only when opening a capture file for reading. */
3346       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3347                     "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
3348                     filename);
3349       break;
3350
3351     case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3352       /* Seen only when opening a capture file for reading. */
3353       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3354                     "The file \"%s\" isn't a capture file in a format Wireshark understands.",
3355                     filename);
3356       break;
3357
3358     case WTAP_ERR_UNSUPPORTED:
3359       /* Seen only when opening a capture file for reading. */
3360       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3361                     "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
3362                     "(%s)",
3363                     filename, err_info);
3364       g_free(err_info);
3365       break;
3366
3367     case WTAP_ERR_CANT_WRITE_TO_PIPE:
3368       /* Seen only when opening a capture file for writing. */
3369       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3370                     "The file \"%s\" is a pipe, and %s capture files can't be "
3371                     "written to a pipe.",
3372                     filename, wtap_file_type_string(file_type));
3373       break;
3374
3375     case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3376       /* Seen only when opening a capture file for writing. */
3377       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3378                     "Wireshark doesn't support writing capture files in that format.");
3379       break;
3380
3381     case WTAP_ERR_UNSUPPORTED_ENCAP:
3382       if (for_writing) {
3383         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3384                       "Wireshark can't save this capture in that format.");
3385       } else {
3386         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3387                       "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
3388                       "(%s)",
3389                       filename, err_info);
3390         g_free(err_info);
3391       }
3392       break;
3393
3394     case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3395       if (for_writing) {
3396         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3397                       "Wireshark 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 Wireshark doesn't support.",
3401                       filename);
3402       }
3403       break;
3404
3405     case WTAP_ERR_BAD_RECORD:
3406       /* Seen only when opening a capture file for reading. */
3407       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3408                     "The file \"%s\" appears to be damaged or corrupt.\n"
3409                     "(%s)",
3410                     filename, err_info);
3411       g_free(err_info);
3412       break;
3413
3414     case WTAP_ERR_CANT_OPEN:
3415       if (for_writing) {
3416         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3417                       "The file \"%s\" could not be created for some unknown reason.",
3418                       filename);
3419       } else {
3420         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3421                       "The file \"%s\" could not be opened for some unknown reason.",
3422                       filename);
3423       }
3424       break;
3425
3426     case WTAP_ERR_SHORT_READ:
3427       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3428                     "The file \"%s\" appears to have been cut short"
3429                     " in the middle of a packet or other data.",
3430                     filename);
3431       break;
3432
3433     case WTAP_ERR_SHORT_WRITE:
3434       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3435                     "A full header couldn't be written to the file \"%s\".",
3436                     filename);
3437       break;
3438
3439     case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
3440       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3441                     "Gzip compression not supported by this file type.");
3442       break;
3443
3444     default:
3445       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3446                     "The file \"%s\" could not be %s: %s.",
3447                     filename,
3448                     for_writing ? "created" : "opened",
3449                     wtap_strerror(err));
3450       break;
3451     }
3452   } else {
3453     /* OS error. */
3454     open_failure_alert_box(filename, err, for_writing);
3455   }
3456 }
3457
3458 static const char *
3459 file_rename_error_message(int err)
3460 {
3461   const char *errmsg;
3462   static char errmsg_errno[1024+1];
3463
3464   switch (err) {
3465
3466   case ENOENT:
3467     errmsg = "The path to the file \"%s\" doesn't exist.";
3468     break;
3469
3470   case EACCES:
3471     errmsg = "You don't have permission to move the capture file to \"%s\".";
3472     break;
3473
3474   default:
3475     g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3476                     "The file \"%%s\" could not be moved: %s.",
3477                                 wtap_strerror(err));
3478     errmsg = errmsg_errno;
3479     break;
3480   }
3481   return errmsg;
3482 }
3483
3484 char *
3485 cf_read_error_message(int err, const gchar *err_info)
3486 {
3487   static char errmsg_errno[1024+1];
3488
3489   switch (err) {
3490
3491   case WTAP_ERR_UNSUPPORTED_ENCAP:
3492       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3493                "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
3494                err_info);
3495       break;
3496
3497   case WTAP_ERR_BAD_RECORD:
3498     g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3499              "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
3500              wtap_strerror(err), err_info);
3501     break;
3502
3503   default:
3504     g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3505              "An error occurred while reading from the file \"%%s\": %s.",
3506              wtap_strerror(err));
3507     break;
3508   }
3509   return errmsg_errno;
3510 }
3511
3512 static void
3513 cf_write_failure_alert_box(const char *filename, int err)
3514 {
3515   if (err < 0) {
3516     /* Wiretap error. */
3517     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3518                   "An error occurred while writing to the file \"%s\": %s.",
3519                   filename, wtap_strerror(err));
3520   } else {
3521     /* OS error. */
3522     write_failure_alert_box(filename, err);
3523   }
3524 }
3525
3526 /* Check for write errors - if the file is being written to an NFS server,
3527    a write error may not show up until the file is closed, as NFS clients
3528    might not send writes to the server until the "write()" call finishes,
3529    so that the write may fail on the server but the "write()" may succeed. */
3530 static void
3531 cf_close_failure_alert_box(const char *filename, int err)
3532 {
3533   if (err < 0) {
3534     /* Wiretap error. */
3535     switch (err) {
3536
3537     case WTAP_ERR_CANT_CLOSE:
3538       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3539                     "The file \"%s\" couldn't be closed for some unknown reason.",
3540                     filename);
3541       break;
3542
3543     case WTAP_ERR_SHORT_WRITE:
3544       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3545                     "Not all the packets could be written to the file \"%s\".",
3546                     filename);
3547       break;
3548
3549     default:
3550       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3551                     "An error occurred while closing the file \"%s\": %s.",
3552                     filename, wtap_strerror(err));
3553       break;
3554     }
3555   } else {
3556     /* OS error.
3557        We assume that a close error from the OS is really a write error. */
3558     write_failure_alert_box(filename, err);
3559   }
3560 }
3561
3562 /* Reload the current capture file. */
3563 void
3564 cf_reload(capture_file *cf) {
3565   gchar *filename;
3566   gboolean is_tempfile;
3567   int err;
3568
3569   /* If the file could be opened, "cf_open()" calls "cf_close()"
3570      to get rid of state for the old capture file before filling in state
3571      for the new capture file.  "cf_close()" will remove the file if
3572      it's a temporary file; we don't want that to happen (for one thing,
3573      it'd prevent subsequent reopens from working).  Remember whether it's
3574      a temporary file, mark it as not being a temporary file, and then
3575      reopen it as the type of file it was.
3576
3577      Also, "cf_close()" will free "cf->filename", so we must make
3578      a copy of it first. */
3579   filename = g_strdup(cf->filename);
3580   is_tempfile = cf->is_tempfile;
3581   cf->is_tempfile = FALSE;
3582   if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
3583     switch (cf_read(cf)) {
3584
3585     case CF_READ_OK:
3586     case CF_READ_ERROR:
3587       /* Just because we got an error, that doesn't mean we were unable
3588          to read any of the file; we handle what we could get from the
3589          file. */
3590       break;
3591
3592     case CF_READ_ABORTED:
3593       /* The user bailed out of re-reading the capture file; the
3594          capture file has been closed - just free the capture file name
3595          string and return (without changing the last containing
3596          directory). */
3597       g_free(filename);
3598       return;
3599     }
3600   } else {
3601     /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
3602        Instead, the file was left open, so we should restore "cf->is_tempfile"
3603        ourselves.
3604
3605        XXX - change the menu?  Presumably "cf_open()" will do that;
3606        make sure it does! */
3607     cf->is_tempfile = is_tempfile;
3608   }
3609   /* "cf_open()" made a copy of the file name we handed it, so
3610      we should free up our copy. */
3611   g_free(filename);
3612 }
3613
3614 /* Copies a file in binary mode, for those operating systems that care about
3615  * such things.
3616  * Returns TRUE on success, FALSE on failure. If a failure, it also
3617  * displays a simple dialog window with the error message.
3618  */
3619 static gboolean
3620 copy_binary_file(const char *from_filename, const char *to_filename)
3621 {
3622   int           from_fd, to_fd, nread, nwritten, err;
3623   guint8        pd[65536];
3624
3625   /* Copy the raw bytes of the file. */
3626   from_fd = eth_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
3627   if (from_fd < 0) {
3628     open_failure_alert_box(from_filename, errno, FALSE);
3629     goto done;
3630   }
3631
3632   /* Use open() instead of creat() so that we can pass the O_BINARY
3633      flag, which is relevant on Win32; it appears that "creat()"
3634      may open the file in text mode, not binary mode, but we want
3635      to copy the raw bytes of the file, so we need the output file
3636      to be open in binary mode. */
3637   to_fd = eth_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
3638   if (to_fd < 0) {
3639     open_failure_alert_box(to_filename, errno, TRUE);
3640     eth_close(from_fd);
3641     goto done;
3642   }
3643
3644   while ((nread = eth_read(from_fd, pd, sizeof pd)) > 0) {
3645     nwritten = eth_write(to_fd, pd, nread);
3646     if (nwritten < nread) {
3647       if (nwritten < 0)
3648         err = errno;
3649       else
3650         err = WTAP_ERR_SHORT_WRITE;
3651       write_failure_alert_box(to_filename, err);
3652       eth_close(from_fd);
3653       eth_close(to_fd);
3654       goto done;
3655     }
3656   }
3657   if (nread < 0) {
3658     err = errno;
3659     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3660                   "An error occurred while reading from the file \"%s\": %s.",
3661                   from_filename, strerror(err));
3662     eth_close(from_fd);
3663     eth_close(to_fd);
3664     goto done;
3665   }
3666   eth_close(from_fd);
3667   if (eth_close(to_fd) < 0) {
3668     write_failure_alert_box(to_filename, errno);
3669     goto done;
3670   }
3671
3672   return TRUE;
3673
3674 done:
3675   return FALSE;
3676 }