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