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