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