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