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