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