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