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