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