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