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