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