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