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