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