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