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