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