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