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