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