Patch from Ben Fowler to rename the global variable "cf" to "cfile", to
[obnox/wireshark/wip.git] / file.c
1 /* file.c
2  * File I/O routines
3  *
4  * $Id: file.c,v 1.190 2000/06/27 04:35:44 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <gtk/gtk.h>
31
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35
36 #include <time.h>
37
38 #ifdef HAVE_IO_H
39 #include <io.h>
40 #endif
41
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <sys/stat.h>
46 #include <errno.h>
47 #include <fcntl.h>
48 #include <signal.h>
49
50 #ifdef NEED_SNPRINTF_H
51 # ifdef HAVE_STDARG_H
52 #  include <stdarg.h>
53 # else
54 #  include <varargs.h>
55 # endif
56 # include "snprintf.h"
57 #endif
58
59 #ifdef NEED_STRERROR_H
60 #include "strerror.h"
61 #endif
62
63 #ifdef HAVE_SYS_TYPES_H
64 # include <sys/types.h>
65 #endif
66
67 #ifdef HAVE_NETINET_IN_H
68 # include <netinet/in.h>
69 #endif
70
71 #include "gtk/main.h"
72 #include "column.h"
73 #include "packet.h"
74 #include "print.h"
75 #include "file.h"
76 #include "menu.h"
77 #include "util.h"
78 #include "simple_dialog.h"
79 #include "ui_util.h"
80 #include "prefs.h"
81 #include "gtk/proto_draw.h"
82 #include "dfilter.h"
83 #include "conversation.h"
84 #include "globals.h"
85
86 #include "plugins.h"
87
88 extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view;
89 extern guint      file_ctx;
90
91 gboolean auto_scroll_live = FALSE;
92
93 static guint32 firstsec, firstusec;
94 static guint32 prevsec, prevusec;
95
96 static void wtap_dispatch_cb(u_char *, const struct wtap_pkthdr *, int,
97     union wtap_pseudo_header *, const u_char *);
98
99 static void set_selected_row(int row);
100
101 static void freeze_clist(capture_file *cf);
102 static void thaw_clist(capture_file *cf);
103
104 static char *file_rename_error_message(int err);
105 static char *file_close_error_message(int err);
106
107 /* Update the progress bar this many times when reading a file. */
108 #define N_PROGBAR_UPDATES       100
109
110 /* Number of "frame_data" structures per memory chunk.
111    XXX - is this the right number? */
112 #define FRAME_DATA_CHUNK_SIZE   1024
113
114 int
115 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
116 {
117   wtap       *wth;
118   int         err;
119   FILE_T      fh;
120   int         fd;
121   struct stat cf_stat;
122
123   wth = wtap_open_offline(fname, &err, TRUE);
124   if (wth == NULL)
125     goto fail;
126
127   /* Find the size of the file. */
128   fh = wtap_file(wth);
129   fd = wtap_fd(wth);
130   if (fstat(fd, &cf_stat) < 0) {
131     err = errno;
132     wtap_close(wth);
133     goto fail;
134   }
135
136   /* The open succeeded.  Close whatever capture file we had open,
137      and fill in the information for this file. */
138   close_cap_file(cf, info_bar);
139
140   /* Initialize the table of conversations. */
141   conversation_init();
142
143   /* Initialize protocol-specific variables */
144   init_all_protocols();
145
146   cf->wth = wth;
147   cf->filed = fd;
148   cf->f_len = cf_stat.st_size;
149
150   /* Set the file name because we need it to set the follow stream filter.
151      XXX - is that still true?  We need it for other reasons, though,
152      in any case. */
153   cf->filename = g_strdup(fname);
154
155   /* Indicate whether it's a permanent or temporary file. */
156   cf->is_tempfile = is_tempfile;
157
158   /* If it's a temporary capture buffer file, mark it as not saved. */
159   cf->user_saved = !is_tempfile;
160
161   cf->cd_t      = wtap_file_type(cf->wth);
162   cf->count     = 0;
163   cf->drops     = 0;
164   cf->esec      = 0;
165   cf->eusec     = 0;
166   cf->snap      = wtap_snapshot_length(cf->wth);
167   cf->update_progbar = FALSE;
168   cf->progbar_quantum = 0;
169   cf->progbar_nextstep = 0;
170   firstsec = 0, firstusec = 0;
171   prevsec = 0, prevusec = 0;
172  
173   cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
174         sizeof(frame_data),
175         FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
176         G_ALLOC_AND_FREE);
177   g_assert(cf->plist_chunk);
178
179   return (0);
180
181 fail:
182   simple_dialog(ESD_TYPE_WARN, NULL,
183                         file_open_error_message(err, FALSE), fname);
184   return (err);
185 }
186
187 /* Reset everything to a pristine state */
188 void
189 close_cap_file(capture_file *cf, void *w)
190 {
191   /* Destroy all popup packet windows, as they refer to packets in the
192      capture file we're closing. */
193   destroy_packet_wins();
194
195   if (cf->wth) {
196     wtap_close(cf->wth);
197     cf->wth = NULL;
198   }
199   /* We have no file open... */
200   if (cf->filename != NULL) {
201     /* If it's a temporary file, remove it. */
202     if (cf->is_tempfile)
203       unlink(cf->filename);
204     g_free(cf->filename);
205     cf->filename = NULL;
206   }
207   /* ...which means we have nothing to save. */
208   cf->user_saved = FALSE;
209
210   if (cf->plist_chunk != NULL) {
211     g_mem_chunk_destroy(cf->plist_chunk);
212     cf->plist_chunk = NULL;
213   }
214   if (cf->rfcode != NULL) {
215     dfilter_destroy(cf->rfcode);
216     cf->rfcode = NULL;
217   }
218   cf->plist = NULL;
219   cf->plist_end = NULL;
220   unselect_packet(cf);  /* nothing to select */
221   cf->first_displayed = NULL;
222   cf->last_displayed = NULL;
223
224   /* Clear the packet list. */
225   gtk_clist_freeze(GTK_CLIST(packet_list));
226   gtk_clist_clear(GTK_CLIST(packet_list));
227   gtk_clist_thaw(GTK_CLIST(packet_list));
228
229   /* Clear any file-related status bar messages.
230      XXX - should be "clear *ALL* file-related status bar messages;
231      will there ever be more than one on the stack? */
232   gtk_statusbar_pop(GTK_STATUSBAR(w), file_ctx);
233
234   /* Restore the standard title bar message. */
235   set_main_window_name("The Ethereal Network Analyzer");
236
237   /* Disable all menu items that make sense only if you have a capture. */
238   set_menus_for_capture_file(FALSE);
239   set_menus_for_unsaved_capture_file(FALSE);
240   set_menus_for_captured_packets(FALSE);
241   set_menus_for_selected_packet(FALSE);
242   set_menus_for_capture_in_progress(FALSE);
243 }
244
245 /* Set the file name in the status line, in the name for the main window,
246    and in the name for the main window's icon. */
247 static void
248 set_display_filename(capture_file *cf)
249 {
250   gchar  *name_ptr;
251   size_t  msg_len;
252   gchar  *done_fmt = " File: %s  Drops: %u";
253   gchar  *done_msg;
254   gchar  *win_name_fmt = "%s - Ethereal";
255   gchar  *win_name;
256
257   if (!cf->is_tempfile) {
258     /* Get the last component of the file name, and put that in the
259        status bar. */
260     name_ptr = get_basename(cf->filename);
261   } else {
262     /* The file we read is a temporary file from a live capture;
263        we don't mention its name in the status bar. */
264     name_ptr = "<capture>";
265   }
266
267   msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
268   done_msg = g_malloc(msg_len);
269   snprintf(done_msg, msg_len, done_fmt, name_ptr, cf->drops);
270   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
271   g_free(done_msg);
272
273   msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
274   win_name = g_malloc(msg_len);
275   snprintf(win_name, msg_len, win_name_fmt, name_ptr);
276   set_main_window_name(win_name);
277   g_free(win_name);
278 }
279
280 int
281 read_cap_file(capture_file *cf)
282 {
283   gchar  *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
284   int     success;
285   int     err;
286   size_t  msg_len;
287   char   *errmsg;
288   char    errmsg_errno[1024+1];
289   gchar   err_str[2048+1];
290
291   name_ptr = get_basename(cf->filename);
292
293   msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
294   load_msg = g_malloc(msg_len);
295   snprintf(load_msg, msg_len, load_fmt, name_ptr);
296   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
297   g_free(load_msg);
298
299   cf->update_progbar = TRUE;
300   /* Update the progress bar when it gets to this value. */
301   cf->progbar_nextstep = 0;
302   /* When we reach the value that triggers a progress bar update,
303      bump that value by this amount. */
304   cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
305
306 #ifndef O_BINARY
307 #define O_BINARY        0
308 #endif
309
310   freeze_clist(cf);
311   success = wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
312   /* Set the file encapsulation type now; we don't know what it is until
313      we've looked at all the packets, as we don't know until then whether
314      there's more than one type (and thus whether it's
315      WTAP_ENCAP_PER_PACKET). */
316
317   /* We're done reading sequentially through the file; close the
318      sequential I/O side, to free up memory it requires. */
319   wtap_sequential_close(cf->wth);
320
321   cf->lnk_t = wtap_file_encap(cf->wth);
322   cf->current_frame = cf->first_displayed;
323   thaw_clist(cf);
324
325   gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
326   gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
327
328   gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
329   set_display_filename(cf);
330
331   /* Enable menu items that make sense if you have a capture file you've
332      finished reading. */
333   set_menus_for_capture_file(TRUE);
334   set_menus_for_unsaved_capture_file(!cf->user_saved);
335
336   /* Enable menu items that make sense if you have some captured packets. */
337   set_menus_for_captured_packets(TRUE);
338
339   /* If we have any displayed packets to select, select the first of those
340      packets by making the first row the selected row. */
341   if (cf->first_displayed != NULL)
342     gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
343
344   if (!success) {
345     /* Put up a message box noting that the read failed somewhere along
346        the line.  Don't throw out the stuff we managed to read, though,
347        if any. */
348     switch (err) {
349
350     case WTAP_ERR_UNSUPPORTED_ENCAP:
351       errmsg = "The capture file is for a network type that Ethereal doesn't support.";
352       break;
353
354     case WTAP_ERR_CANT_READ:
355       errmsg = "An attempt to read from the file failed for"
356                " some unknown reason.";
357       break;
358
359     case WTAP_ERR_SHORT_READ:
360       errmsg = "The capture file appears to have been cut short"
361                " in the middle of a packet.";
362       break;
363
364     case WTAP_ERR_BAD_RECORD:
365       errmsg = "The capture file appears to be damaged or corrupt.";
366       break;
367
368     default:
369       sprintf(errmsg_errno, "An error occurred while reading the"
370                               " capture file: %s.", wtap_strerror(err));
371       errmsg = errmsg_errno;
372       break;
373     }
374     snprintf(err_str, sizeof err_str, errmsg);
375     simple_dialog(ESD_TYPE_WARN, NULL, err_str);
376     return (err);
377   } else
378     return (0);
379 }
380
381 #ifdef HAVE_LIBPCAP
382 int
383 start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
384 {
385   int     err;
386   int     i;
387
388   err = open_cap_file(fname, is_tempfile, cf);
389   if (err == 0) {
390     /* Disable menu items that make no sense if you're currently running
391        a capture. */
392     set_menus_for_capture_in_progress(TRUE);
393
394     /* Enable menu items that make sense if you have some captured
395        packets (yes, I know, we don't have any *yet*). */
396     set_menus_for_captured_packets(TRUE);
397
398     for (i = 0; i < cf->cinfo.num_cols; i++) {
399       if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
400         gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
401       else {
402         gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
403         gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
404                                 cf->cinfo.col_width[i]);
405         gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
406       }
407     }
408
409     gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, 
410                        " <live capture in progress>");
411   }
412   return err;
413 }
414
415 int
416 continue_tail_cap_file(capture_file *cf, int to_read)
417 {
418   int err;
419
420   gtk_clist_freeze(GTK_CLIST(packet_list));
421
422   wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf, &err);
423
424   gtk_clist_thaw(GTK_CLIST(packet_list));
425
426   /* XXX - this cheats and looks inside the packet list to find the final
427      row number. */
428   if (auto_scroll_live && cf->plist_end != NULL)
429     gtk_clist_moveto(GTK_CLIST(packet_list), 
430                        GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
431   return err;
432 }
433
434 int
435 finish_tail_cap_file(capture_file *cf)
436 {
437   int err;
438
439   gtk_clist_freeze(GTK_CLIST(packet_list));
440
441   wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
442
443   thaw_clist(cf);
444   if (auto_scroll_live && cf->plist_end != NULL)
445     /* XXX - this cheats and looks inside the packet list to find the final
446        row number. */
447     gtk_clist_moveto(GTK_CLIST(packet_list), 
448                        GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
449
450   /* We're done reading sequentially through the file; close the
451      sequential I/O side, to free up memory it requires. */
452   wtap_sequential_close(cf->wth);
453
454   /* Set the file encapsulation type now; we don't know what it is until
455      we've looked at all the packets, as we don't know until then whether
456      there's more than one type (and thus whether it's
457      WTAP_ENCAP_PER_PACKET). */
458   cf->lnk_t = wtap_file_encap(cf->wth);
459
460   /* Pop the "<live capture in progress>" message off the status bar. */
461   gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
462
463   set_display_filename(cf);
464
465   /* Enable menu items that make sense if you're not currently running
466      a capture. */
467   set_menus_for_capture_in_progress(FALSE);
468
469   /* Enable menu items that make sense if you have a capture file
470      you've finished reading. */
471   set_menus_for_capture_file(TRUE);
472   set_menus_for_unsaved_capture_file(!cf->user_saved);
473
474   return err;
475 }
476 #endif /* HAVE_LIBPCAP */
477
478 typedef struct {
479   color_filter_t *colorf;
480   proto_tree    *protocol_tree;
481   const guint8  *pd;
482   frame_data    *fdata;
483 } apply_color_filter_args;
484
485 /*
486  * If no color filter has been applied, apply this one.
487  * (The "if no color filter has been applied" is to handle the case where
488  * more than one color filter matches the packet.)
489  */
490 static void
491 apply_color_filter(gpointer filter_arg, gpointer argp)
492 {
493   color_filter_t *colorf = filter_arg;
494   apply_color_filter_args *args = argp;
495
496   if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
497     if (dfilter_apply(colorf->c_colorfilter, args->protocol_tree, args->pd, args->fdata->cap_len))
498       args->colorf = colorf;
499   }
500 }
501
502 static int
503 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
504         union wtap_pseudo_header *pseudo_header, const u_char *buf)
505 {
506   apply_color_filter_args args;
507   gint          i, row;
508   proto_tree   *protocol_tree = NULL;
509
510   /* We don't yet have a color filter to apply. */
511   args.colorf = NULL;
512
513   /* If we don't have the time stamp of the first packet in the
514      capture, it's because this is the first packet.  Save the time
515      stamp of this packet as the time stamp of the first packet. */
516   if (!firstsec && !firstusec) {
517     firstsec  = fdata->abs_secs;
518     firstusec = fdata->abs_usecs;
519   }
520
521   /* Get the time elapsed between the first packet and this packet. */
522   cf->esec = fdata->abs_secs - firstsec;
523   if (firstusec <= fdata->abs_usecs) {
524     cf->eusec = fdata->abs_usecs - firstusec;
525   } else {
526     cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
527     cf->esec--;
528   }
529
530   fdata->cinfo = &cf->cinfo;
531   for (i = 0; i < fdata->cinfo->num_cols; i++) {
532     fdata->cinfo->col_data[i][0] = '\0';
533   }
534
535   /* Apply the filters */
536   if (cf->dfcode != NULL || filter_list != NULL) {
537     protocol_tree = proto_tree_create_root();
538     dissect_packet(pseudo_header, buf, fdata, protocol_tree);
539     if (cf->dfcode != NULL)
540       fdata->flags.passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, buf, fdata->cap_len) ? 1 : 0;
541     else
542       fdata->flags.passed_dfilter = 1;
543
544     /* Apply color filters, if we have any. */
545     if (filter_list != NULL) {
546       args.protocol_tree = protocol_tree;
547       args.pd = buf;
548       args.fdata = fdata;
549       g_slist_foreach(filter_list, apply_color_filter, &args);
550     }
551     proto_tree_free(protocol_tree);
552   }
553   else {
554 #ifdef HAVE_PLUGINS
555         if (enabled_plugins_number > 0)
556             protocol_tree = proto_tree_create_root();
557 #endif
558         dissect_packet(pseudo_header, buf, fdata, protocol_tree);
559         fdata->flags.passed_dfilter = 1;
560 #ifdef HAVE_PLUGINS
561         if (protocol_tree)
562             proto_tree_free(protocol_tree);
563 #endif
564   }
565
566   if (fdata->flags.passed_dfilter) {
567     /* This frame passed the display filter, so add it to the clist. */
568
569     /* If we don't have the time stamp of the previous displayed packet,
570        it's because this is the first displayed packet.  Save the time
571        stamp of this packet as the time stamp of the previous displayed
572        packet. */
573     if (!prevsec && !prevusec) {
574       prevsec  = fdata->abs_secs;
575       prevusec = fdata->abs_usecs;
576     }
577
578     /* Get the time elapsed between the first packet and this packet. */
579     fdata->rel_secs = cf->esec;
580     fdata->rel_usecs = cf->eusec;
581   
582     /* Get the time elapsed between the previous displayed packet and
583        this packet. */
584     fdata->del_secs = fdata->abs_secs - prevsec;
585     if (prevusec <= fdata->abs_usecs) {
586       fdata->del_usecs = fdata->abs_usecs - prevusec;
587     } else {
588       fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
589       fdata->del_secs--;
590     }
591     prevsec = fdata->abs_secs;
592     prevusec = fdata->abs_usecs;
593
594     fill_in_columns(fdata);
595
596     /* If we haven't yet seen the first frame, this is it.
597
598        XXX - we must do this before we add the row to the display,
599        as, if the display's GtkCList's selection mode is
600        GTK_SELECTION_BROWSE, when the first entry is added to it,
601        "select_packet()" will be called, and it will fetch the row
602        data for the 0th row, and will get a null pointer rather than
603        "fdata", as "gtk_clist_append()" won't yet have returned and
604        thus "gtk_clist_set_row_data()" won't yet have been called.
605
606        We thus need to leave behind bread crumbs so that
607        "select_packet()" can find this frame.  See the comment
608        in "select_packet()". */
609     if (cf->first_displayed == NULL)
610       cf->first_displayed = fdata;
611
612     /* This is the last frame we've seen so far. */
613     cf->last_displayed = fdata;
614
615     row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
616     gtk_clist_set_row_data(GTK_CLIST(packet_list), row, fdata);
617
618     if (filter_list != NULL && (args.colorf != NULL)) {
619         gtk_clist_set_background(GTK_CLIST(packet_list), row,
620                    &args.colorf->bg_color);
621         gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
622                    &args.colorf->fg_color);
623     } else {
624         gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
625         gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
626     }
627   } else {
628     /* This frame didn't pass the display filter, so it's not being added
629        to the clist, and thus has no row. */
630     row = -1;
631   }
632   fdata->cinfo = NULL;
633   return row;
634 }
635
636 static void
637 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
638         union wtap_pseudo_header *pseudo_header, const u_char *buf)
639 {
640   frame_data   *fdata;
641   capture_file *cf = (capture_file *) user;
642   int           passed;
643   proto_tree   *protocol_tree;
644   frame_data   *plist_end;
645   int file_pos;
646   float prog_val;
647
648   /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
649      when we update it, we have to run the GTK+ main loop to get it
650      to repaint what's pending, and doing so may involve an "ioctl()"
651      to see if there's any pending input from an X server, and doing
652      that for every packet can be costly, especially on a big file.
653      
654      Do so only if we were told to do so; when reading a capture file
655      being updated by a live capture, we don't do so (as we're not
656      "done" until the capture stops, so we don't know how close to
657      "done" we are. */
658
659   if (cf->update_progbar && offset >= cf->progbar_nextstep) {
660       file_pos = lseek(cf->filed, 0, SEEK_CUR);
661       prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
662       gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), prog_val);
663       cf->progbar_nextstep += cf->progbar_quantum;
664       while (gtk_events_pending())
665       gtk_main_iteration();
666   }
667
668   /* Allocate the next list entry, and add it to the list. */
669   fdata = g_mem_chunk_alloc(cf->plist_chunk);
670
671   fdata->next = NULL;
672   fdata->prev = NULL;
673   fdata->pfd  = NULL;
674   fdata->pkt_len  = phdr->len;
675   fdata->cap_len  = phdr->caplen;
676   fdata->file_off = offset;
677   fdata->lnk_t = phdr->pkt_encap;
678   fdata->abs_secs  = phdr->ts.tv_sec;
679   fdata->abs_usecs = phdr->ts.tv_usec;
680   fdata->flags.encoding = CHAR_ASCII;
681   fdata->flags.visited = 0;
682   fdata->cinfo = NULL;
683
684   passed = TRUE;
685   if (cf->rfcode) {
686     protocol_tree = proto_tree_create_root();
687     dissect_packet(pseudo_header, buf, fdata, protocol_tree);
688     passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata->cap_len);
689     proto_tree_free(protocol_tree);
690   }   
691   if (passed) {
692     plist_end = cf->plist_end;
693     fdata->prev = plist_end;
694     if (plist_end != NULL)
695       plist_end->next = fdata;
696     else
697       cf->plist = fdata;
698     cf->plist_end = fdata;
699
700     cf->count++;
701     fdata->num = cf->count;
702     add_packet_to_packet_list(fdata, cf, pseudo_header, buf);
703   } else {
704     /* XXX - if we didn't have read filters, or if we could avoid
705        allocating the "frame_data" structure until we knew whether
706        the frame passed the read filter, we could use a G_ALLOC_ONLY
707        memory chunk...
708
709        ...but, at least in one test I did, where I just made the chunk
710        a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
711        seem to save a noticeable amount of time or space. */
712     g_mem_chunk_free(cf->plist_chunk, fdata);
713   }
714 }
715
716 int
717 filter_packets(capture_file *cf, gchar *dftext)
718 {
719   dfilter *dfcode;
720
721   if (dftext == NULL) {
722     /* The new filter is an empty filter (i.e., display all packets). */
723     dfcode = NULL;
724   } else {
725     /*
726      * We have a filter; try to compile it.
727      */
728     if (dfilter_compile(dftext, &dfcode) != 0) {
729       /* The attempt failed; report an error. */
730       simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
731       return 0;
732     }
733
734     /* Was it empty? */
735     if (dfcode == NULL) {
736       /* Yes - free the filter text, and set it to null. */
737       g_free(dftext);
738       dftext = NULL;
739     }
740   }
741
742   /* We have a valid filter.  Replace the current filter. */
743   if (cf->dfilter != NULL)
744     g_free(cf->dfilter);
745   cf->dfilter = dftext;
746   if (cf->dfcode != NULL)
747     dfilter_destroy(cf->dfcode);
748   cf->dfcode = dfcode;
749
750   /* Now go through the list of packets we've read from the capture file,
751      applying the current display filter, and, if the packet passes the
752      display filter, add it to the summary display, appropriately
753      colored.  (That's how we colorize the display - it's like filtering
754      the display, only we don't install a new filter.) */
755   colorize_packets(cf);
756   return 1;
757 }
758
759 void
760 colorize_packets(capture_file *cf)
761 {
762   frame_data *fdata;
763   guint32 progbar_quantum;
764   guint32 progbar_nextstep;
765   int count;
766   frame_data *selected_frame;
767   int selected_row;
768   int row;
769
770   /* Which frame, if any, is the currently selected frame?
771      XXX - should the selected frame or the focus frame be the "current"
772      frame, that frame being the one from which "Find Frame" searches
773      start? */
774   selected_frame = cf->current_frame;
775
776   /* We don't yet know what row that frame will be on, if any, after we
777      rebuild the clist, however. */
778   selected_row = -1;
779
780   /* We need to re-initialize all the state information that protocols
781      keep, because we're making a fresh pass through all the packets. */
782
783   /* Initialize the table of conversations. */
784   conversation_init();
785
786   /* Initialize protocol-specific variables */
787   init_all_protocols();
788
789   gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
790
791   /* Freeze the packet list while we redo it, so we don't get any
792      screen updates while it happens. */
793   gtk_clist_freeze(GTK_CLIST(packet_list));
794
795   /* Clear it out. */
796   gtk_clist_clear(GTK_CLIST(packet_list));
797
798   /* We don't yet know which will be the first and last frames displayed. */
799   cf->first_displayed = NULL;
800   cf->last_displayed = NULL;
801
802   /* Iterate through the list of packets, calling a routine
803      to run the filter on the packet, see if it matches, and
804      put it in the display list if so.  */
805   firstsec = 0;
806   firstusec = 0;
807   prevsec = 0;
808   prevusec = 0;
809
810   /* Update the progress bar when it gets to this value. */
811   progbar_nextstep = 0;
812   /* When we reach the value that triggers a progress bar update,
813      bump that value by this amount. */
814   progbar_quantum = cf->count/N_PROGBAR_UPDATES;
815   /* Count of packets at which we've looked. */
816   count = 0;
817
818   gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
819
820   for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
821     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
822        when we update it, we have to run the GTK+ main loop to get it
823        to repaint what's pending, and doing so may involve an "ioctl()"
824        to see if there's any pending input from an X server, and doing
825        that for every packet can be costly, especially on a big file. */
826     if (count >= progbar_nextstep) {
827       /* let's not divide by zero. I should never be started
828        * with count == 0, so let's assert that
829        */
830       g_assert(cf->count > 0);
831
832       gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
833                 (gfloat) count / cf->count);
834
835       progbar_nextstep += progbar_quantum;
836       while (gtk_events_pending())
837         gtk_main_iteration();
838     }
839
840     count++;
841
842     wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
843         cf->pd, fdata->cap_len);
844
845     row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd);
846     if (fdata == selected_frame)
847       selected_row = row;
848   }
849  
850   gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
851
852   /* Unfreeze the packet list. */
853   gtk_clist_thaw(GTK_CLIST(packet_list));
854
855   if (selected_row != -1) {
856     /* The frame that was selected passed the filter; select it, make it
857        the focus row, and make it visible. */
858     set_selected_row(selected_row);
859     finfo_selected = NULL;
860   } else {
861     /* The selected frame didn't pass the filter; make the first frame
862        the current frame, and leave it unselected. */
863     unselect_packet(cf);
864     cf->current_frame = cf->first_displayed;
865   }
866 }
867
868 int
869 print_packets(capture_file *cf, print_args_t *print_args)
870 {
871   int         i;
872   frame_data *fdata;
873   guint32     progbar_quantum;
874   guint32     progbar_nextstep;
875   guint32     count;
876   proto_tree *protocol_tree;
877   gint       *col_widths = NULL;
878   gint        data_width;
879   gboolean    print_separator;
880   char       *line_buf = NULL;
881   int         line_buf_len = 256;
882   char        *cp;
883   int         column_len;
884   int         line_len;
885
886   cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
887   if (cf->print_fh == NULL)
888     return FALSE;       /* attempt to open destination failed */
889
890   print_preamble(cf->print_fh, print_args->format);
891
892   if (print_args->print_summary) {
893     /* We're printing packet summaries.  Allocate the line buffer at
894        its initial length. */
895     line_buf = g_malloc(line_buf_len + 1);
896
897     /* Find the widths for each of the columns - maximum of the
898        width of the title and the width of the data - and print
899        the column titles. */
900     col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
901     cp = &line_buf[0];
902     line_len = 0;
903     for (i = 0; i < cf->cinfo.num_cols; i++) {
904       /* Don't pad the last column. */
905       if (i == cf->cinfo.num_cols - 1)
906         col_widths[i] = 0;
907       else {
908         col_widths[i] = strlen(cf->cinfo.col_title[i]);
909         data_width = get_column_char_width(get_column_format(i));
910         if (data_width > col_widths[i])
911           col_widths[i] = data_width;
912       }
913
914       /* Find the length of the string for this column. */
915       column_len = strlen(cf->cinfo.col_title[i]);
916       if (col_widths[i] > column_len)
917         column_len = col_widths[i];
918
919       /* Make sure there's room in the line buffer for the column; if not,
920          double its length. */
921       line_len += column_len + 1;       /* "+1" for space or \n */
922       if (line_len > line_buf_len) {
923         line_buf_len *= 2;
924         line_buf = g_realloc(line_buf, line_buf_len + 1);
925       }
926
927       /* Right-justify the packet number column. */
928       if (cf->cinfo.col_fmt[i] == COL_NUMBER)
929         sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_title[i]);
930       else
931         sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
932       cp += column_len;
933       if (i == cf->cinfo.num_cols - 1)
934         *cp++ = '\n';
935       else
936         *cp++ = ' ';
937     }
938     *cp = '\0';
939     print_line(cf->print_fh, print_args->format, line_buf);
940   }
941
942   print_separator = FALSE;
943
944   /* The protocol tree will be "visible", i.e., printed, only if we're
945      not printing a summary. */
946   proto_tree_is_visible = !print_args->print_summary;
947
948   /* Update the progress bar when it gets to this value. */
949   progbar_nextstep = 0;
950   /* When we reach the value that triggers a progress bar update,
951      bump that value by this amount. */
952   progbar_quantum = cf->count/N_PROGBAR_UPDATES;
953   /* Count of packets at which we've looked. */
954   count = 0;
955
956   gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
957
958   /* Iterate through the list of packets, printing the packets that
959      were selected by the current display filter.  */
960   for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
961     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
962        when we update it, we have to run the GTK+ main loop to get it
963        to repaint what's pending, and doing so may involve an "ioctl()"
964        to see if there's any pending input from an X server, and doing
965        that for every packet can be costly, especially on a big file. */
966     if (count >= progbar_nextstep) {
967       /* let's not divide by zero. I should never be started
968        * with count == 0, so let's assert that
969        */
970       g_assert(cf->count > 0);
971
972       gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
973         (gfloat) count / cf->count);
974       progbar_nextstep += progbar_quantum;
975       while (gtk_events_pending())
976         gtk_main_iteration();
977     }
978     count++;
979
980     if (fdata->flags.passed_dfilter) {
981       wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
982                         cf->pd, fdata->cap_len);
983       if (print_args->print_summary) {
984         /* Fill in the column information, but don't bother creating
985            the logical protocol tree. */
986         fdata->cinfo = &cf->cinfo;
987         for (i = 0; i < fdata->cinfo->num_cols; i++) {
988           fdata->cinfo->col_data[i][0] = '\0';
989         }
990         dissect_packet(&cf->pseudo_header, cf->pd, fdata, NULL);
991         fill_in_columns(fdata);
992         cp = &line_buf[0];
993         line_len = 0;
994         for (i = 0; i < cf->cinfo.num_cols; i++) {
995           /* Find the length of the string for this column. */
996           column_len = strlen(cf->cinfo.col_data[i]);
997           if (col_widths[i] > column_len)
998             column_len = col_widths[i];
999
1000           /* Make sure there's room in the line buffer for the column; if not,
1001              double its length. */
1002           line_len += column_len + 1;   /* "+1" for space or \n */
1003           if (line_len > line_buf_len) {
1004             line_buf_len *= 2;
1005             line_buf = g_realloc(line_buf, line_buf_len + 1);
1006           }
1007
1008           /* Right-justify the packet number column. */
1009           if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1010             sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_data[i]);
1011           else
1012             sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
1013           cp += column_len;
1014           if (i == cf->cinfo.num_cols - 1)
1015             *cp++ = '\n';
1016           else
1017             *cp++ = ' ';
1018         }
1019         *cp = '\0';
1020         print_line(cf->print_fh, print_args->format, line_buf);
1021       } else {
1022         if (print_separator)
1023           print_line(cf->print_fh, print_args->format, "\n");
1024
1025         /* Create the logical protocol tree. */
1026         protocol_tree = proto_tree_create_root();
1027         dissect_packet(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
1028
1029         /* Print the information in that tree. */
1030         proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
1031                         cf->pd, fdata, cf->print_fh);
1032
1033         proto_tree_free(protocol_tree);
1034
1035         if (print_args->print_hex) {
1036           /* Print the full packet data as hex. */
1037           print_hex_data(cf->print_fh, print_args->format, cf->pd,
1038                         fdata->cap_len, fdata->flags.encoding);
1039         }
1040
1041         /* Print a blank line if we print anything after this. */
1042         print_separator = TRUE;
1043       }
1044     }
1045   }
1046
1047   if (col_widths != NULL)
1048     g_free(col_widths);
1049   if (line_buf != NULL)
1050     g_free(line_buf);
1051
1052   print_finale(cf->print_fh, print_args->format);
1053
1054   close_print_dest(print_args->to_file, cf->print_fh);
1055  
1056   gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1057
1058   cf->print_fh = NULL;
1059
1060   proto_tree_is_visible = FALSE;
1061
1062   return TRUE;
1063 }
1064
1065 /* Scan through the packet list and change all columns that use the
1066    "command-line-specified" time stamp format to use the current
1067    value of that format. */
1068 void
1069 change_time_formats(capture_file *cf)
1070 {
1071   frame_data *fdata;
1072   int row;
1073   int i;
1074   GtkStyle  *pl_style;
1075
1076   /* Freeze the packet list while we redo it, so we don't get any
1077      screen updates while it happens. */
1078   freeze_clist(cf);
1079
1080   /* Iterate through the list of packets, checking whether the packet
1081      is in a row of the summary list and, if so, whether there are
1082      any columns that show the time in the "command-line-specified"
1083      format and, if so, update that row. */
1084   for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1085     /* Find what row this packet is in. */
1086     row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1087
1088     if (row != -1) {
1089       /* This packet is in the summary list, on row "row". */
1090
1091       /* XXX - there really should be a way of checking "cf->cinfo" for this;
1092          the answer isn't going to change from packet to packet, so we should
1093          simply skip all the "change_time_formats()" work if we're not
1094          changing anything. */
1095       fdata->cinfo = &cf->cinfo;
1096       if (check_col(fdata, COL_CLS_TIME)) {
1097         /* There are columns that show the time in the "command-line-specified"
1098            format; update them. */
1099         for (i = 0; i < cf->cinfo.num_cols; i++) {
1100           if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1101             /* This is one of the columns that shows the time in
1102                "command-line-specified" format; update it. */
1103             cf->cinfo.col_data[i][0] = '\0';
1104             col_set_cls_time(fdata, i);
1105             gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
1106                           cf->cinfo.col_data[i]);
1107           }
1108         }
1109       }
1110     }
1111   }
1112
1113   /* Set the column widths of those columns that show the time in
1114      "command-line-specified" format. */
1115   pl_style = gtk_widget_get_style(packet_list);
1116   for (i = 0; i < cf->cinfo.num_cols; i++) {
1117     if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1118       gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1119         gdk_string_width(pl_style->font, get_column_longest_string(COL_CLS_TIME)));
1120     }
1121   }
1122
1123   /* Unfreeze the packet list. */
1124   thaw_clist(cf);
1125 }
1126
1127 static void
1128 clear_tree_and_hex_views(void)
1129 {
1130   /* Clear the hex dump. */
1131   gtk_text_freeze(GTK_TEXT(byte_view));
1132   gtk_text_set_point(GTK_TEXT(byte_view), 0);
1133   gtk_text_forward_delete(GTK_TEXT(byte_view),
1134     gtk_text_get_length(GTK_TEXT(byte_view)));
1135   gtk_text_thaw(GTK_TEXT(byte_view));
1136
1137   /* Remove all nodes in ctree. This is how it's done in testgtk.c in GTK+ */
1138   gtk_clist_clear ( GTK_CLIST(tree_view) );
1139
1140 }
1141
1142 gboolean
1143 find_packet(capture_file *cf, dfilter *sfcode)
1144 {
1145   frame_data *start_fd;
1146   frame_data *fdata;
1147   frame_data *new_fd = NULL;
1148   guint32 progbar_quantum;
1149   guint32 progbar_nextstep;
1150   int count;
1151   proto_tree *protocol_tree;
1152   gboolean frame_matched;
1153   int row;
1154
1155   start_fd = cf->current_frame;
1156   if (start_fd != NULL)  {
1157     gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
1158
1159     /* Iterate through the list of packets, starting at the packet we've
1160        picked, calling a routine to run the filter on the packet, see if
1161        it matches, and stop if so.  */
1162     count = 0;
1163     fdata = start_fd;
1164
1165     /* Update the progress bar when it gets to this value. */
1166     progbar_nextstep = 0;
1167     /* When we reach the value that triggers a progress bar update,
1168        bump that value by this amount. */
1169     progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1170     gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
1171
1172     fdata = start_fd;
1173     for (;;) {
1174       /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1175          when we update it, we have to run the GTK+ main loop to get it
1176          to repaint what's pending, and doing so may involve an "ioctl()"
1177          to see if there's any pending input from an X server, and doing
1178          that for every packet can be costly, especially on a big file. */
1179       if (count >= progbar_nextstep) {
1180         /* let's not divide by zero. I should never be started
1181          * with count == 0, so let's assert that
1182          */
1183         g_assert(cf->count > 0);
1184
1185         gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1186                 (gfloat) count / cf->count);
1187
1188         progbar_nextstep += progbar_quantum;
1189         while (gtk_events_pending())
1190           gtk_main_iteration();
1191       }
1192
1193       /* Go past the current frame. */
1194       if (cf->sbackward) {
1195         /* Go on to the previous frame. */
1196         fdata = fdata->prev;
1197         if (fdata == NULL)
1198           fdata = cf->plist_end;        /* wrap around */
1199       } else {
1200         /* Go on to the next frame. */
1201         fdata = fdata->next;
1202         if (fdata == NULL)
1203           fdata = cf->plist;    /* wrap around */
1204       }
1205
1206       count++;
1207
1208       /* Is this packet in the display? */
1209       if (fdata->flags.passed_dfilter) {
1210         /* Yes.  Does it match the search filter? */
1211         protocol_tree = proto_tree_create_root();
1212         wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
1213                         cf->pd, fdata->cap_len);
1214         dissect_packet(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
1215         frame_matched = dfilter_apply(sfcode, protocol_tree, cf->pd, fdata->cap_len);
1216         proto_tree_free(protocol_tree);
1217         if (frame_matched) {
1218           new_fd = fdata;
1219           break;        /* found it! */
1220         }
1221       }
1222
1223       if (fdata == start_fd) {
1224         /* We're back to the frame we were on originally, and that frame
1225            doesn't match the search filter.  The search failed. */
1226         break;
1227       }
1228     }
1229
1230     gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1231   }
1232
1233   if (new_fd != NULL) {
1234     /* We found a frame.  Find what row it's in. */
1235     row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), new_fd);
1236     g_assert(row != -1);
1237
1238     /* Select that row, make it the focus row, and make it visible. */
1239     set_selected_row(row);
1240     return TRUE;        /* success */
1241   } else
1242     return FALSE;       /* failure */
1243 }
1244
1245 goto_result_t
1246 goto_frame(capture_file *cf, guint fnumber)
1247 {
1248   frame_data *fdata;
1249   int row;
1250
1251   for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
1252     ;
1253
1254   if (fdata == NULL)
1255     return NO_SUCH_FRAME;       /* we didn't find that frame */
1256   if (!fdata->flags.passed_dfilter)
1257     return FRAME_NOT_DISPLAYED; /* the frame with that number isn't displayed */
1258
1259   /* We found that frame, and it's currently being displayed.
1260      Find what row it's in. */
1261   row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1262   g_assert(row != -1);
1263
1264   /* Select that row, make it the focus row, and make it visible. */
1265   set_selected_row(row);
1266   return FOUND_FRAME;
1267 }
1268
1269 /* Select the packet on a given row. */
1270 void
1271 select_packet(capture_file *cf, int row)
1272 {
1273   frame_data *fdata;
1274
1275   /* Get the frame data struct pointer for this frame */
1276   fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
1277
1278   if (fdata == NULL) {
1279     /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
1280        the first entry is added to it by "real_insert_row()", that row
1281        is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
1282        our version and the vanilla GTK+ version).
1283
1284        This means that a "select-row" signal is emitted; this causes
1285        "packet_list_select_cb()" to be called, which causes "select_packet()"
1286        to be called.
1287
1288        "select_packet()" fetches, above, the data associated with the
1289        row that was selected; however, as "gtk_clist_append()", which
1290        called "real_insert_row()", hasn't yet returned, we haven't yet
1291        associated any data with that row, so we get back a null pointer.
1292
1293        We can't assume that there's only one frame in the frame list,
1294        either, as we may be filtering the display.
1295
1296        We therefore assume that, if "row" is 0, i.e. the first row
1297        is being selected, and "cf->first_displayed" equals
1298        "cf->last_displayed", i.e. there's only one frame being
1299        displayed, that frame is the frame we want.
1300
1301        This means we have to set "cf->first_displayed" and
1302        "cf->last_displayed" before adding the row to the
1303        GtkCList; see the comment in "add_packet_to_packet_list()". */
1304
1305        if (row == 0 && cf->first_displayed == cf->last_displayed)
1306          fdata = cf->first_displayed;
1307   }
1308
1309   /* Record that this frame is the current frame. */
1310   cf->current_frame = fdata;
1311
1312   /* Get the data in that frame. */
1313   wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1314                         cf->pd, fdata->cap_len);
1315
1316   /* Create the logical protocol tree. */
1317   if (cf->protocol_tree)
1318       proto_tree_free(cf->protocol_tree);
1319   cf->protocol_tree = proto_tree_create_root();
1320   proto_tree_is_visible = TRUE;
1321   dissect_packet(&cf->pseudo_header, cf->pd, cf->current_frame,
1322                 cf->protocol_tree);
1323   proto_tree_is_visible = FALSE;
1324
1325   /* Display the GUI protocol tree and hex dump. */
1326   clear_tree_and_hex_views();
1327   proto_tree_draw(cf->protocol_tree, tree_view);
1328   packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->current_frame->cap_len,
1329                         -1, -1, cf->current_frame->flags.encoding);
1330
1331   /* A packet is selected. */
1332   set_menus_for_selected_packet(TRUE);
1333 }
1334
1335 /* Unselect the selected packet, if any. */
1336 void
1337 unselect_packet(capture_file *cf)
1338 {
1339   /* Destroy the protocol tree for that packet. */
1340   if (cf->protocol_tree != NULL) {
1341     proto_tree_free(cf->protocol_tree);
1342     cf->protocol_tree = NULL;
1343   }
1344
1345   finfo_selected = NULL;
1346
1347   /* Clear out the display of that packet. */
1348   clear_tree_and_hex_views();
1349
1350   /* No packet is selected. */
1351   set_menus_for_selected_packet(FALSE);
1352 }
1353
1354 /* Set the selected row and the focus row of the packet list to the specified
1355    row, and make it visible if it's not currently visible. */
1356 static void
1357 set_selected_row(int row)
1358 {
1359   if (gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) != GTK_VISIBILITY_FULL)
1360     gtk_clist_moveto(GTK_CLIST(packet_list), row, -1, 0.0, 0.0);
1361
1362   /* XXX - why is there no "gtk_clist_set_focus_row()", so that we
1363      can make the row for the frame we found the focus row?
1364
1365      See
1366
1367  http://www.gnome.org/mailing-lists/archives/gtk-list/2000-January/0038.shtml
1368
1369      */
1370   GTK_CLIST(packet_list)->focus_row = row;
1371
1372   gtk_clist_select_row(GTK_CLIST(packet_list), row, -1);
1373 }
1374
1375 static void
1376 freeze_clist(capture_file *cf)
1377 {
1378   int i;
1379
1380   /* Make the column sizes static, so they don't adjust while
1381      we're reading the capture file (freezing the clist doesn't
1382      seem to suffice). */
1383   for (i = 0; i < cf->cinfo.num_cols; i++)
1384     gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1385   gtk_clist_freeze(GTK_CLIST(packet_list));
1386 }
1387
1388 static void
1389 thaw_clist(capture_file *cf)
1390 {
1391   int i;
1392
1393   for (i = 0; i < cf->cinfo.num_cols; i++) {
1394     if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1395       /* Set this column's width to the appropriate value. */
1396       gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1397                                 cf->cinfo.col_width[i]);
1398     } else {
1399       /* Make this column's size dynamic, so that it adjusts to the
1400          appropriate size. */
1401       gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1402     }
1403   }
1404   gtk_clist_thaw(GTK_CLIST(packet_list));
1405
1406   /* Hopefully, the columns have now gotten their appropriate sizes;
1407      make them resizeable - a column that auto-resizes cannot be
1408      resized by the user, and *vice versa*. */
1409   for (i = 0; i < cf->cinfo.num_cols; i++)
1410     gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1411 }
1412
1413 int
1414 save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
1415                 guint save_format)
1416 {
1417   gchar        *from_filename;
1418   gchar        *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
1419   size_t        msg_len;
1420   int           err;
1421   gboolean      do_copy;
1422   int           from_fd, to_fd, nread, nwritten;
1423   wtap_dumper  *pdh;
1424   frame_data   *fdata;
1425   struct wtap_pkthdr hdr;
1426   union wtap_pseudo_header pseudo_header;
1427   guint8        pd[65536];
1428
1429   name_ptr = get_basename(fname);
1430   msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
1431   save_msg = g_malloc(msg_len);
1432   snprintf(save_msg, msg_len, save_fmt, name_ptr);
1433   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
1434   g_free(save_msg);
1435
1436   if (!save_filtered && save_format == cf->cd_t) {
1437     /* We're not filtering packets, and we're saving it in the format
1438        it's already in, so we can just move or copy the raw data. */
1439
1440     /* In this branch, we set "err" only if we get an error, so we
1441        must first clear it. */
1442     err = 0;
1443     if (cf->is_tempfile) {
1444       /* The file being saved is a temporary file from a live
1445          capture, so it doesn't need to stay around under that name;
1446          first, try renaming the capture buffer file to the new name. */
1447 #ifndef WIN32
1448       if (rename(cf->filename, fname) == 0) {
1449         /* That succeeded - there's no need to copy the source file. */
1450         from_filename = NULL;
1451         do_copy = FALSE;
1452       } else {
1453         if (errno == EXDEV) {
1454           /* They're on different file systems, so we have to copy the
1455              file. */
1456           do_copy = TRUE;
1457           from_filename = cf->filename;
1458         } else {
1459           /* The rename failed, but not because they're on different
1460              file systems - put up an error message.  (Or should we
1461              just punt and try to copy?  The only reason why I'd
1462              expect the rename to fail and the copy to succeed would
1463              be if we didn't have permission to remove the file from
1464              the temporary directory, and that might be fixable - but
1465              is it worth requiring the user to go off and fix it?) */
1466           err = errno;
1467           simple_dialog(ESD_TYPE_WARN, NULL,
1468                                 file_rename_error_message(err), fname);
1469           goto done;
1470         }
1471       }
1472 #else
1473       do_copy = TRUE;
1474       from_filename = cf->filename;
1475 #endif
1476     } else {
1477       /* It's a permanent file, so we should copy it, and not remove the
1478          original. */
1479       do_copy = TRUE;
1480       from_filename = cf->filename;
1481     }
1482     /* Copy the file, if we haven't moved it. */
1483     if (do_copy) {
1484       /* Copy the raw bytes of the file. */
1485       from_fd = open(from_filename, O_RDONLY | O_BINARY);
1486       if (from_fd < 0) {
1487         err = errno;
1488         simple_dialog(ESD_TYPE_WARN, NULL,
1489                         file_open_error_message(err, TRUE), from_filename);
1490         goto done;
1491       }
1492
1493       /* Use open() instead of creat() so that we can pass the O_BINARY
1494          flag, which is relevant on Win32; it appears that "creat()"
1495          may open the file in text mode, not binary mode, but we want
1496          to copy the raw bytes of the file, so we need the output file
1497          to be open in binary mode. */
1498       to_fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1499       if (to_fd < 0) {
1500         err = errno;
1501         simple_dialog(ESD_TYPE_WARN, NULL,
1502                         file_open_error_message(err, TRUE), fname);
1503         close(from_fd);
1504         goto done;
1505       }
1506
1507       while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
1508         nwritten = write(to_fd, pd, nread);
1509         if (nwritten < nread) {
1510           if (nwritten < 0)
1511             err = errno;
1512           else
1513             err = WTAP_ERR_SHORT_WRITE;
1514           simple_dialog(ESD_TYPE_WARN, NULL,
1515                                 file_write_error_message(err), fname);
1516           close(from_fd);
1517           close(to_fd);
1518           goto done;
1519         }
1520       }
1521       if (nread < 0) {
1522         err = errno;
1523         simple_dialog(ESD_TYPE_WARN, NULL,
1524                         file_read_error_message(err), from_filename);
1525         close(from_fd);
1526         close(to_fd);
1527         goto done;
1528       }
1529       close(from_fd);
1530       if (close(to_fd) < 0) {
1531         err = errno;
1532         simple_dialog(ESD_TYPE_WARN, NULL,
1533                 file_close_error_message(err), fname);
1534         goto done;
1535       }
1536     }
1537   } else {
1538     /* Either we're filtering packets, or we're saving in a different
1539        format; we can't do that by copying or moving the capture file,
1540        we have to do it by writing the packets out in Wiretap. */
1541     pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
1542     if (pdh == NULL) {
1543       simple_dialog(ESD_TYPE_WARN, NULL,
1544                         file_open_error_message(err, TRUE), fname);
1545       goto done;
1546     }
1547
1548     /* XXX - have a way to save only the packets currently selected by
1549        the display filter.
1550
1551        If we do that, should we make that file the current file?  If so,
1552        it means we can no longer get at the other packets.  What does
1553        NetMon do? */
1554     for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1555       /* XXX - do a progress bar */
1556       if (!save_filtered || fdata->flags.passed_dfilter) {
1557         /* Either we're saving all frames, or we're saving filtered frames
1558            and this one passed the display filter - save it. */
1559         hdr.ts.tv_sec = fdata->abs_secs;
1560         hdr.ts.tv_usec = fdata->abs_usecs;
1561         hdr.caplen = fdata->cap_len;
1562         hdr.len = fdata->pkt_len;
1563         hdr.pkt_encap = fdata->lnk_t;
1564         wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1565                 pd, fdata->cap_len);
1566
1567         if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
1568             simple_dialog(ESD_TYPE_WARN, NULL,
1569                                 file_write_error_message(err), fname);
1570             wtap_dump_close(pdh, &err);
1571             goto done;
1572         }
1573       }
1574     }
1575
1576     if (!wtap_dump_close(pdh, &err)) {
1577       simple_dialog(ESD_TYPE_WARN, NULL,
1578                 file_close_error_message(err), fname);
1579       goto done;
1580     }
1581   }
1582
1583 done:
1584
1585   /* Pop the "Saving:" message off the status bar. */
1586   gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
1587   if (err == 0) {
1588     if (!save_filtered) {
1589       /* We saved the entire capture, not just some packets from it.
1590          Open and read the file we saved it to.
1591
1592          XXX - this is somewhat of a waste; we already have the
1593          packets, all this gets us is updated file type information
1594          (which we could just stuff into "cf"), and having the new
1595          file be the one we have opened and from which we're reading
1596          the data, and it means we have to spend time opening and
1597          reading the file, which could be a significant amount of
1598          time if the file is large. */
1599       cf->user_saved = TRUE;
1600
1601       if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
1602         /* XXX - report errors if this fails? */
1603         err = read_cap_file(cf);
1604         set_menus_for_unsaved_capture_file(FALSE);
1605       }
1606     }
1607   }
1608   return err;
1609 }
1610
1611 char *
1612 file_open_error_message(int err, int for_writing)
1613 {
1614   char *errmsg;
1615   static char errmsg_errno[1024+1];
1616
1617   switch (err) {
1618
1619   case WTAP_ERR_NOT_REGULAR_FILE:
1620     errmsg = "The file \"%s\" is invalid.";
1621     break;
1622
1623   case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1624   case WTAP_ERR_UNSUPPORTED:
1625     /* Seen only when opening a capture file for reading. */
1626     errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1627     break;
1628
1629   case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1630     /* Seen only when opening a capture file for writing. */
1631     errmsg = "Ethereal does not support writing capture files in that format.";
1632     break;
1633
1634   case WTAP_ERR_UNSUPPORTED_ENCAP:
1635   case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1636     if (for_writing)
1637       errmsg = "Ethereal cannot save this capture in that format.";
1638     else
1639       errmsg = "The file \"%s\" is a capture for a network type that Ethereal doesn't support.";
1640     break;
1641
1642   case WTAP_ERR_BAD_RECORD:
1643     errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1644     break;
1645
1646   case WTAP_ERR_CANT_OPEN:
1647     if (for_writing)
1648       errmsg = "The file \"%s\" could not be created for some unknown reason.";
1649     else
1650       errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1651     break;
1652
1653   case WTAP_ERR_SHORT_READ:
1654     errmsg = "The file \"%s\" appears to have been cut short"
1655              " in the middle of a packet.";
1656     break;
1657
1658   case WTAP_ERR_SHORT_WRITE:
1659     errmsg = "A full header couldn't be written to the file \"%s\".";
1660     break;
1661
1662   case ENOENT:
1663     if (for_writing)
1664       errmsg = "The path to the file \"%s\" does not exist.";
1665     else
1666       errmsg = "The file \"%s\" does not exist.";
1667     break;
1668
1669   case EACCES:
1670     if (for_writing)
1671       errmsg = "You do not have permission to create or write to the file \"%s\".";
1672     else
1673       errmsg = "You do not have permission to read the file \"%s\".";
1674     break;
1675
1676   default:
1677     sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
1678                                 wtap_strerror(err));
1679     errmsg = errmsg_errno;
1680     break;
1681   }
1682   return errmsg;
1683 }
1684
1685 static char *
1686 file_rename_error_message(int err)
1687 {
1688   char *errmsg;
1689   static char errmsg_errno[1024+1];
1690
1691   switch (err) {
1692
1693   case ENOENT:
1694     errmsg = "The path to the file \"%s\" does not exist.";
1695     break;
1696
1697   case EACCES:
1698     errmsg = "You do not have permission to move the capture file to \"%s\".";
1699     break;
1700
1701   default:
1702     sprintf(errmsg_errno, "The file \"%%s\" could not be moved: %s.",
1703                                 wtap_strerror(err));
1704     errmsg = errmsg_errno;
1705     break;
1706   }
1707   return errmsg;
1708 }
1709
1710 char *
1711 file_read_error_message(int err)
1712 {
1713   static char errmsg_errno[1024+1];
1714
1715   sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.",
1716                                 wtap_strerror(err));
1717   return errmsg_errno;
1718 }
1719
1720 char *
1721 file_write_error_message(int err)
1722 {
1723   char *errmsg;
1724   static char errmsg_errno[1024+1];
1725
1726   switch (err) {
1727
1728   case ENOSPC:
1729     errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1730     break;
1731
1732 #ifdef EDQUOT
1733   case EDQUOT:
1734     errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1735     break;
1736 #endif
1737
1738   default:
1739     sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.",
1740                                 wtap_strerror(err));
1741     errmsg = errmsg_errno;
1742     break;
1743   }
1744   return errmsg;
1745 }
1746
1747 /* Check for write errors - if the file is being written to an NFS server,
1748    a write error may not show up until the file is closed, as NFS clients
1749    might not send writes to the server until the "write()" call finishes,
1750    so that the write may fail on the server but the "write()" may succeed. */
1751 static char *
1752 file_close_error_message(int err)
1753 {
1754   char *errmsg;
1755   static char errmsg_errno[1024+1];
1756
1757   switch (err) {
1758
1759   case WTAP_ERR_CANT_CLOSE:
1760     errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
1761     break;
1762
1763   case WTAP_ERR_SHORT_WRITE:
1764     errmsg = "Not all the data could be written to the file \"%s\".";
1765     break;
1766
1767   case ENOSPC:
1768     errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1769     break;
1770
1771 #ifdef EDQUOT
1772   case EDQUOT:
1773     errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1774     break;
1775 #endif
1776
1777   default:
1778     sprintf(errmsg_errno, "An error occurred while closing the file \"%%s\": %s.",
1779                                 wtap_strerror(err));
1780     errmsg = errmsg_errno;
1781     break;
1782   }
1783   return errmsg;
1784 }