2d9406f3e385b620f44be5044eed3748fd87973c
[obnox/wireshark/wip.git] / file.c
1 /* file.c
2  * File I/O routines
3  *
4  * $Id: file.c,v 1.233 2001/03/23 14:43:59 jfoster 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 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35
36 #include <time.h>
37
38 #ifdef HAVE_IO_H
39 #include <io.h>
40 #endif
41
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <errno.h>
46 #include <signal.h>
47
48 #ifdef HAVE_SYS_STAT_H
49 #include <sys/stat.h>
50 #endif
51
52 #ifdef HAVE_FCNTL_H
53 #include <fcntl.h>
54 #endif
55
56 #ifdef NEED_SNPRINTF_H
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 <epan.h>
73
74 #include "gtk/main.h"
75 #include "color.h"
76 #include "gtk/color_utils.h"
77 #include "column.h"
78 #include "packet.h"
79 #include "print.h"
80 #include "file.h"
81 #include "menu.h"
82 #include "util.h"
83 #include "simple_dialog.h"
84 #include "ui_util.h"
85 #include "prefs.h"
86 #include "gtk/proto_draw.h"
87 #include "dfilter/dfilter.h"
88 #include "conversation.h"
89 #include "globals.h"
90 #include "gtk/colors.h"
91
92 extern GtkWidget *packet_list, *info_bar, *byte_nb_ptr, *tree_view;
93 extern guint      file_ctx;
94
95 gboolean auto_scroll_live = FALSE;
96
97 static guint32 firstsec, firstusec;
98 static guint32 prevsec, prevusec;
99
100 static void read_packet(capture_file *cf, int offset);
101
102 static void rescan_packets(capture_file *cf, const char *action,
103         gboolean refilter, gboolean redissect);
104
105 static void set_selected_row(int row);
106
107 static void freeze_clist(capture_file *cf);
108 static void thaw_clist(capture_file *cf);
109
110 static char *file_rename_error_message(int err);
111 static char *file_close_error_message(int err);
112 static gboolean copy_binary_file(char *from_filename, char *to_filename);
113
114 /* Update the progress bar this many times when reading a file. */
115 #define N_PROGBAR_UPDATES       100
116
117 /* Number of "frame_data" structures per memory chunk.
118    XXX - is this the right number? */
119 #define FRAME_DATA_CHUNK_SIZE   1024
120
121 int
122 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
123 {
124   wtap       *wth;
125   int         err;
126   FILE_T      fh;
127   int         fd;
128   struct stat cf_stat;
129
130   wth = wtap_open_offline(fname, &err, TRUE);
131   if (wth == NULL)
132     goto fail;
133
134   /* Find the size of the file. */
135   fh = wtap_file(wth);
136   fd = wtap_fd(wth);
137   if (fstat(fd, &cf_stat) < 0) {
138     err = errno;
139     wtap_close(wth);
140     goto fail;
141   }
142
143   /* The open succeeded.  Close whatever capture file we had open,
144      and fill in the information for this file. */
145   close_cap_file(cf, info_bar);
146
147   /* Initialize the table of conversations. */
148   epan_conversation_init();
149
150   /* Initialize protocol-specific variables */
151   init_all_protocols();
152
153   /* We're about to start reading the file. */
154   cf->state = FILE_READ_IN_PROGRESS;
155
156   cf->wth = wth;
157   cf->filed = fd;
158   cf->f_len = cf_stat.st_size;
159
160   /* Set the file name because we need it to set the follow stream filter.
161      XXX - is that still true?  We need it for other reasons, though,
162      in any case. */
163   cf->filename = g_strdup(fname);
164
165   /* Indicate whether it's a permanent or temporary file. */
166   cf->is_tempfile = is_tempfile;
167
168   /* If it's a temporary capture buffer file, mark it as not saved. */
169   cf->user_saved = !is_tempfile;
170
171   cf->cd_t      = wtap_file_type(cf->wth);
172   cf->count     = 0;
173   cf->drops_known = FALSE;
174   cf->drops     = 0;
175   cf->esec      = 0;
176   cf->eusec     = 0;
177   cf->snap      = wtap_snapshot_length(cf->wth);
178   cf->progbar_quantum = 0;
179   cf->progbar_nextstep = 0;
180   firstsec = 0, firstusec = 0;
181   prevsec = 0, prevusec = 0;
182  
183   cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
184         sizeof(frame_data),
185         FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
186         G_ALLOC_AND_FREE);
187   g_assert(cf->plist_chunk);
188
189   return (0);
190
191 fail:
192   simple_dialog(ESD_TYPE_CRIT, NULL,
193                         file_open_error_message(err, FALSE), fname);
194   return (err);
195 }
196
197 /* Reset everything to a pristine state */
198 void
199 close_cap_file(capture_file *cf, void *w)
200 {
201   /* Die if we're in the middle of reading a file. */
202   g_assert(cf->state != FILE_READ_IN_PROGRESS);
203
204   /* Destroy all popup packet windows, as they refer to packets in the
205      capture file we're closing. */
206   destroy_packet_wins();
207
208   if (cf->wth) {
209     wtap_close(cf->wth);
210     cf->wth = NULL;
211   }
212   /* We have no file open... */
213   if (cf->filename != NULL) {
214     /* If it's a temporary file, remove it. */
215     if (cf->is_tempfile)
216       unlink(cf->filename);
217     g_free(cf->filename);
218     cf->filename = NULL;
219   }
220   /* ...which means we have nothing to save. */
221   cf->user_saved = FALSE;
222
223   if (cf->plist_chunk != NULL) {
224     g_mem_chunk_destroy(cf->plist_chunk);
225     cf->plist_chunk = NULL;
226   }
227   if (cf->rfcode != NULL) {
228     dfilter_free(cf->rfcode);
229     cf->rfcode = NULL;
230   }
231   cf->plist = NULL;
232   cf->plist_end = NULL;
233   unselect_packet(cf);  /* nothing to select */
234   cf->first_displayed = NULL;
235   cf->last_displayed = NULL;
236
237   /* Clear the packet list. */
238   gtk_clist_freeze(GTK_CLIST(packet_list));
239   gtk_clist_clear(GTK_CLIST(packet_list));
240   gtk_clist_thaw(GTK_CLIST(packet_list));
241
242   /* Clear any file-related status bar messages.
243      XXX - should be "clear *ALL* file-related status bar messages;
244      will there ever be more than one on the stack? */
245   gtk_statusbar_pop(GTK_STATUSBAR(w), file_ctx);
246
247   /* Restore the standard title bar message. */
248   set_main_window_name("The Ethereal Network Analyzer");
249
250   /* Disable all menu items that make sense only if you have a capture. */
251   set_menus_for_capture_file(FALSE);
252   set_menus_for_unsaved_capture_file(FALSE);
253   set_menus_for_captured_packets(FALSE);
254   set_menus_for_selected_packet(FALSE);
255   set_menus_for_capture_in_progress(FALSE);
256   set_menus_for_selected_tree_row(FALSE);
257
258   /* We have no file open. */
259   cf->state = FILE_CLOSED;
260 }
261
262 /* Set the file name in the status line, in the name for the main window,
263    and in the name for the main window's icon. */
264 static void
265 set_display_filename(capture_file *cf)
266 {
267   gchar  *name_ptr;
268   size_t  msg_len;
269   static const gchar done_fmt_nodrops[] = " File: %s";
270   static const gchar done_fmt_drops[] = " File: %s  Drops: %u";
271   gchar  *done_msg;
272   gchar  *win_name_fmt = "%s - Ethereal";
273   gchar  *win_name;
274
275   if (!cf->is_tempfile) {
276     /* Get the last component of the file name, and put that in the
277        status bar. */
278     name_ptr = get_basename(cf->filename);
279   } else {
280     /* The file we read is a temporary file from a live capture;
281        we don't mention its name in the status bar. */
282     name_ptr = "<capture>";
283   }
284
285   if (cf->drops_known) {
286     msg_len = strlen(name_ptr) + strlen(done_fmt_drops) + 64;
287     done_msg = g_malloc(msg_len);
288     snprintf(done_msg, msg_len, done_fmt_drops, name_ptr, cf->drops);
289   } else {
290     msg_len = strlen(name_ptr) + strlen(done_fmt_nodrops);
291     done_msg = g_malloc(msg_len);
292     snprintf(done_msg, msg_len, done_fmt_nodrops, name_ptr);
293   }
294   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
295   g_free(done_msg);
296
297   msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
298   win_name = g_malloc(msg_len);
299   snprintf(win_name, msg_len, win_name_fmt, name_ptr);
300   set_main_window_name(win_name);
301   g_free(win_name);
302 }
303
304 read_status_t
305 read_cap_file(capture_file *cf, int *err)
306 {
307   gchar    *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
308   size_t    msg_len;
309   char     *errmsg;
310   char      errmsg_errno[1024+1];
311   gchar     err_str[2048+1];
312   int       data_offset;
313   progdlg_t *progbar;
314   gboolean  stop_flag;
315   int       file_pos;
316   float     prog_val;
317
318   name_ptr = get_basename(cf->filename);
319
320   msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
321   load_msg = g_malloc(msg_len);
322   snprintf(load_msg, msg_len, load_fmt, name_ptr);
323   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
324
325   /* Update the progress bar when it gets to this value. */
326   cf->progbar_nextstep = 0;
327   /* When we reach the value that triggers a progress bar update,
328      bump that value by this amount. */
329   cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
330
331 #ifndef O_BINARY
332 #define O_BINARY        0
333 #endif
334
335   freeze_clist(cf);
336
337   stop_flag = FALSE;
338   progbar = create_progress_dlg(load_msg, "Stop", &stop_flag);
339   g_free(load_msg);
340
341   while ((wtap_read(cf->wth, err, &data_offset))) {
342     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
343        when we update it, we have to run the GTK+ main loop to get it
344        to repaint what's pending, and doing so may involve an "ioctl()"
345        to see if there's any pending input from an X server, and doing
346        that for every packet can be costly, especially on a big file. */
347     if (data_offset >= cf->progbar_nextstep) {
348         file_pos = lseek(cf->filed, 0, SEEK_CUR);
349         prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
350         update_progress_dlg(progbar, prog_val);
351         cf->progbar_nextstep += cf->progbar_quantum;
352     }
353
354     if (stop_flag) {
355       /* Well, the user decided to abort the read.  Destroy the progress
356          bar, close the capture file, and return READ_ABORTED so our caller
357          can do whatever is appropriate when that happens. */
358       destroy_progress_dlg(progbar);
359       cf->state = FILE_READ_ABORTED;    /* so that we're allowed to close it */
360       gtk_clist_thaw(GTK_CLIST(packet_list));   /* undo our freeze */
361       close_cap_file(cf, info_bar);
362       return (READ_ABORTED);
363     }
364     read_packet(cf, data_offset);
365   }
366
367   /* We're done reading the file; destroy the progress bar. */
368   destroy_progress_dlg(progbar);
369
370   /* We're done reading sequentially through the file. */
371   cf->state = FILE_READ_DONE;
372
373   /* Close the sequential I/O side, to free up memory it requires. */
374   wtap_sequential_close(cf->wth);
375
376   /* Set the file encapsulation type now; we don't know what it is until
377      we've looked at all the packets, as we don't know until then whether
378      there's more than one type (and thus whether it's
379      WTAP_ENCAP_PER_PACKET). */
380   cf->lnk_t = wtap_file_encap(cf->wth);
381
382   cf->current_frame = cf->first_displayed;
383   thaw_clist(cf);
384
385   gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
386   set_display_filename(cf);
387
388   /* Enable menu items that make sense if you have a capture file you've
389      finished reading. */
390   set_menus_for_capture_file(TRUE);
391   set_menus_for_unsaved_capture_file(!cf->user_saved);
392
393   /* Enable menu items that make sense if you have some captured packets. */
394   set_menus_for_captured_packets(TRUE);
395
396   /* If we have any displayed packets to select, select the first of those
397      packets by making the first row the selected row. */
398   if (cf->first_displayed != NULL)
399     gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
400
401   if (*err != 0) {
402     /* Put up a message box noting that the read failed somewhere along
403        the line.  Don't throw out the stuff we managed to read, though,
404        if any. */
405     switch (*err) {
406
407     case WTAP_ERR_UNSUPPORTED_ENCAP:
408       errmsg = "The capture file is for a network type that Ethereal doesn't support.";
409       break;
410
411     case WTAP_ERR_CANT_READ:
412       errmsg = "An attempt to read from the file failed for"
413                " some unknown reason.";
414       break;
415
416     case WTAP_ERR_SHORT_READ:
417       errmsg = "The capture file appears to have been cut short"
418                " in the middle of a packet.";
419       break;
420
421     case WTAP_ERR_BAD_RECORD:
422       errmsg = "The capture file appears to be damaged or corrupt.";
423       break;
424
425     default:
426       snprintf(errmsg_errno, sizeof(errmsg_errno),
427                "An error occurred while reading the"
428                " capture file: %s.", wtap_strerror(*err));
429       errmsg = errmsg_errno;
430       break;
431     }
432     snprintf(err_str, sizeof err_str, errmsg);
433     simple_dialog(ESD_TYPE_CRIT, NULL, err_str);
434     return (READ_ERROR);
435   } else
436     return (READ_SUCCESS);
437 }
438
439 #ifdef HAVE_LIBPCAP
440 int
441 start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
442 {
443   int     err;
444   int     i;
445
446   err = open_cap_file(fname, is_tempfile, cf);
447   if (err == 0) {
448     /* Disable menu items that make no sense if you're currently running
449        a capture. */
450     set_menus_for_capture_in_progress(TRUE);
451
452     /* Enable menu items that make sense if you have some captured
453        packets (yes, I know, we don't have any *yet*). */
454     set_menus_for_captured_packets(TRUE);
455
456     for (i = 0; i < cf->cinfo.num_cols; i++) {
457       if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
458         gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
459       else {
460         gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
461         gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
462                                 cf->cinfo.col_width[i]);
463         gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
464       }
465     }
466
467     gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, 
468                        " <live capture in progress>");
469   }
470   return err;
471 }
472
473 read_status_t
474 continue_tail_cap_file(capture_file *cf, int to_read, int *err)
475 {
476   int data_offset = 0;
477
478   gtk_clist_freeze(GTK_CLIST(packet_list));
479
480   while (to_read != 0 && (wtap_read(cf->wth, err, &data_offset))) {
481     if (cf->state == FILE_READ_ABORTED) {
482       /* Well, the user decided to exit Ethereal.  Break out of the
483          loop, and let the code below (which is called even if there
484          aren't any packets left to read) exit. */
485       break;
486     }
487     read_packet(cf, data_offset);
488     to_read--;
489   }
490
491   gtk_clist_thaw(GTK_CLIST(packet_list));
492
493   /* XXX - this cheats and looks inside the packet list to find the final
494      row number. */
495   if (auto_scroll_live && cf->plist_end != NULL)
496     gtk_clist_moveto(GTK_CLIST(packet_list), 
497                        GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
498
499   if (cf->state == FILE_READ_ABORTED) {
500     /* Well, the user decided to exit Ethereal.  Return READ_ABORTED
501        so that our caller can kill off the capture child process;
502        this will cause an EOF on the pipe from the child, so
503        "finish_tail_cap_file()" will be called, and it will clean up
504        and exit. */
505     return READ_ABORTED;
506   } else if (*err != 0) {
507     /* We got an error reading the capture file.
508        XXX - pop up a dialog box? */
509     return (READ_ERROR);
510   } else
511     return (READ_SUCCESS);
512 }
513
514 read_status_t
515 finish_tail_cap_file(capture_file *cf, int *err)
516 {
517   int data_offset;
518
519   gtk_clist_freeze(GTK_CLIST(packet_list));
520
521   while ((wtap_read(cf->wth, err, &data_offset))) {
522     if (cf->state == FILE_READ_ABORTED) {
523       /* Well, the user decided to abort the read.  Break out of the
524          loop, and let the code below (which is called even if there
525          aren't any packets left to read) exit. */
526       break;
527     }
528     read_packet(cf, data_offset);
529   }
530
531   if (cf->state == FILE_READ_ABORTED) {
532     /* Well, the user decided to abort the read.  We're only called
533        when the child capture process closes the pipe to us (meaning
534        it's probably exited), so we can just close the capture
535        file; we return READ_ABORTED so our caller can do whatever
536        is appropriate when that happens. */
537     close_cap_file(cf, info_bar);
538     return READ_ABORTED;
539   }
540
541   thaw_clist(cf);
542   if (auto_scroll_live && cf->plist_end != NULL)
543     /* XXX - this cheats and looks inside the packet list to find the final
544        row number. */
545     gtk_clist_moveto(GTK_CLIST(packet_list), 
546                        GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
547
548   /* We're done reading sequentially through the file. */
549   cf->state = FILE_READ_DONE;
550
551   /* We're done reading sequentially through the file; close the
552      sequential I/O side, to free up memory it requires. */
553   wtap_sequential_close(cf->wth);
554
555   /* Set the file encapsulation type now; we don't know what it is until
556      we've looked at all the packets, as we don't know until then whether
557      there's more than one type (and thus whether it's
558      WTAP_ENCAP_PER_PACKET). */
559   cf->lnk_t = wtap_file_encap(cf->wth);
560
561   /* Pop the "<live capture in progress>" message off the status bar. */
562   gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
563
564   set_display_filename(cf);
565
566   /* Enable menu items that make sense if you're not currently running
567      a capture. */
568   set_menus_for_capture_in_progress(FALSE);
569
570   /* Enable menu items that make sense if you have a capture file
571      you've finished reading. */
572   set_menus_for_capture_file(TRUE);
573   set_menus_for_unsaved_capture_file(!cf->user_saved);
574
575   if (*err != 0) {
576     /* We got an error reading the capture file.
577        XXX - pop up a dialog box? */
578     return (READ_ERROR);
579   } else
580     return (READ_SUCCESS);
581 }
582 #endif /* HAVE_LIBPCAP */
583
584 typedef struct {
585   color_filter_t *colorf;
586   epan_dissect_t *edt;
587 } apply_color_filter_args;
588
589 /*
590  * If no color filter has been applied, apply this one.
591  * (The "if no color filter has been applied" is to handle the case where
592  * more than one color filter matches the packet.)
593  */
594 static void
595 apply_color_filter(gpointer filter_arg, gpointer argp)
596 {
597   color_filter_t *colorf = filter_arg;
598   apply_color_filter_args *args = argp;
599
600   if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
601     if (dfilter_apply_edt(colorf->c_colorfilter, args->edt))
602       args->colorf = colorf;
603   }
604 }
605
606 static int
607 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
608         union wtap_pseudo_header *pseudo_header, const u_char *buf,
609         gboolean refilter)
610 {
611   apply_color_filter_args args;
612   gint          i, row;
613   proto_tree   *protocol_tree = NULL;
614   epan_dissect_t *edt;
615   GdkColor      fg, bg;
616
617   /* We don't yet have a color filter to apply. */
618   args.colorf = NULL;
619
620   /* If we don't have the time stamp of the first packet in the
621      capture, it's because this is the first packet.  Save the time
622      stamp of this packet as the time stamp of the first packet. */
623   if (!firstsec && !firstusec) {
624     firstsec  = fdata->abs_secs;
625     firstusec = fdata->abs_usecs;
626   }
627
628   fdata->cinfo = &cf->cinfo;
629   for (i = 0; i < fdata->cinfo->num_cols; i++) {
630     fdata->cinfo->col_buf[i][0] = '\0';
631     fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
632   }
633
634   /* If either
635
636         we have a display filter and are re-applying it;
637
638         we have a list of color filters;
639
640      allocate a protocol tree root node, so that we'll construct
641      a protocol tree against which a filter expression can be
642      evaluated. */
643   if ((cf->dfcode != NULL && refilter) || filter_list != NULL)
644     protocol_tree = proto_tree_create_root();
645
646   /* Dissect the frame. */
647   edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree);
648
649   /* If we have a display filter, apply it if we're refiltering, otherwise
650      leave the "passed_dfilter" flag alone.
651
652      If we don't have a display filter, set "passed_dfilter" to 1. */
653   if (cf->dfcode != NULL) {
654     if (refilter) {
655       if (cf->dfcode != NULL)
656         fdata->flags.passed_dfilter = dfilter_apply_edt(cf->dfcode, edt) ? 1 : 0;
657       else
658         fdata->flags.passed_dfilter = 1;
659     }
660   } else
661     fdata->flags.passed_dfilter = 1;
662
663   /* If we have color filters, and the frame is to be displayed, apply
664      the color filters. */
665   if (fdata->flags.passed_dfilter) {
666     if (filter_list != NULL) {
667       args.edt = edt;
668       g_slist_foreach(filter_list, apply_color_filter, &args);
669     }
670   }
671
672   /* There are no more filters to apply, so we don't need any protocol
673      tree; free it if we created it. */
674   if (protocol_tree != NULL)
675     proto_tree_free(protocol_tree);
676
677   epan_dissect_free(edt);
678
679   if (fdata->flags.passed_dfilter) {
680     /* This frame passed the display filter, so add it to the clist. */
681
682     /* If we don't have the time stamp of the previous displayed packet,
683        it's because this is the first displayed packet.  Save the time
684        stamp of this packet as the time stamp of the previous displayed
685        packet. */
686     if (!prevsec && !prevusec) {
687       prevsec  = fdata->abs_secs;
688       prevusec = fdata->abs_usecs;
689     }
690
691     /* Get the time elapsed between the first packet and this packet. */
692     compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
693                 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
694
695     /* If it's greater than the current elapsed time, set the elapsed time
696        to it (we check for "greater than" so as not to be confused by
697        time moving backwards). */
698     if (cf->esec < fdata->rel_secs
699         || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
700       cf->esec = fdata->rel_secs;
701       cf->eusec = fdata->rel_usecs;
702     }
703   
704     /* Get the time elapsed between the previous displayed packet and
705        this packet. */
706     compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
707                 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
708     prevsec = fdata->abs_secs;
709     prevusec = fdata->abs_usecs;
710
711     fill_in_columns(fdata);
712
713     /* If we haven't yet seen the first frame, this is it.
714
715        XXX - we must do this before we add the row to the display,
716        as, if the display's GtkCList's selection mode is
717        GTK_SELECTION_BROWSE, when the first entry is added to it,
718        "select_packet()" will be called, and it will fetch the row
719        data for the 0th row, and will get a null pointer rather than
720        "fdata", as "gtk_clist_append()" won't yet have returned and
721        thus "gtk_clist_set_row_data()" won't yet have been called.
722
723        We thus need to leave behind bread crumbs so that
724        "select_packet()" can find this frame.  See the comment
725        in "select_packet()". */
726     if (cf->first_displayed == NULL)
727       cf->first_displayed = fdata;
728
729     /* This is the last frame we've seen so far. */
730     cf->last_displayed = fdata;
731
732     row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
733     gtk_clist_set_row_data(GTK_CLIST(packet_list), row, fdata);
734
735     if (fdata->flags.marked) {
736         color_t_to_gdkcolor(&bg, &prefs.gui_marked_bg);
737         color_t_to_gdkcolor(&fg, &prefs.gui_marked_fg);
738     } else if (filter_list != NULL && (args.colorf != NULL)) {
739         bg = args.colorf->bg_color;
740         fg = args.colorf->fg_color;
741     } else {
742         bg = WHITE;
743         fg = BLACK;
744     }
745     gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
746     gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
747   } else {
748     /* This frame didn't pass the display filter, so it's not being added
749        to the clist, and thus has no row. */
750     row = -1;
751   }
752   fdata->cinfo = NULL;
753   return row;
754 }
755
756 static void
757 read_packet(capture_file *cf, int offset)
758 {
759   const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
760   union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
761   const u_char *buf = wtap_buf_ptr(cf->wth);
762   frame_data   *fdata;
763   int           passed;
764   proto_tree   *protocol_tree;
765   frame_data   *plist_end;
766   epan_dissect_t *edt;
767
768   /* Allocate the next list entry, and add it to the list. */
769   fdata = g_mem_chunk_alloc(cf->plist_chunk);
770
771   fdata->next = NULL;
772   fdata->prev = NULL;
773   fdata->pfd  = NULL;
774   fdata->data_src  = NULL;
775   fdata->pkt_len  = phdr->len;
776   fdata->cap_len  = phdr->caplen;
777   fdata->file_off = offset;
778   fdata->lnk_t = phdr->pkt_encap;
779   fdata->abs_secs  = phdr->ts.tv_sec;
780   fdata->abs_usecs = phdr->ts.tv_usec;
781   fdata->flags.encoding = CHAR_ASCII;
782   fdata->flags.visited = 0;
783   fdata->flags.marked = 0;
784   fdata->cinfo = NULL;
785
786   passed = TRUE;
787   if (cf->rfcode) {
788     protocol_tree = proto_tree_create_root();
789     edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree);
790     passed = dfilter_apply_edt(cf->rfcode, edt);
791     proto_tree_free(protocol_tree);
792     epan_dissect_free(edt);
793   }   
794   if (passed) {
795     plist_end = cf->plist_end;
796     fdata->prev = plist_end;
797     if (plist_end != NULL)
798       plist_end->next = fdata;
799     else
800       cf->plist = fdata;
801     cf->plist_end = fdata;
802
803     cf->count++;
804     fdata->num = cf->count;
805     add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE);
806   } else {
807     /* XXX - if we didn't have read filters, or if we could avoid
808        allocating the "frame_data" structure until we knew whether
809        the frame passed the read filter, we could use a G_ALLOC_ONLY
810        memory chunk...
811
812        ...but, at least in one test I did, where I just made the chunk
813        a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
814        seem to save a noticeable amount of time or space. */
815     g_mem_chunk_free(cf->plist_chunk, fdata);
816   }
817 }
818
819 int
820 filter_packets(capture_file *cf, gchar *dftext)
821 {
822   dfilter_t *dfcode;
823
824   if (dftext == NULL) {
825     /* The new filter is an empty filter (i.e., display all packets). */
826     dfcode = NULL;
827   } else {
828     /*
829      * We have a filter; try to compile it.
830      */
831     if (!dfilter_compile(dftext, &dfcode)) {
832       /* The attempt failed; report an error. */
833       simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
834       return 0;
835     }
836
837     /* Was it empty? */
838     if (dfcode == NULL) {
839       /* Yes - free the filter text, and set it to null. */
840       g_free(dftext);
841       dftext = NULL;
842     }
843   }
844
845   /* We have a valid filter.  Replace the current filter. */
846   if (cf->dfilter != NULL)
847     g_free(cf->dfilter);
848   cf->dfilter = dftext;
849   if (cf->dfcode != NULL)
850     dfilter_free(cf->dfcode);
851   cf->dfcode = dfcode;
852
853   /* Now rescan the packet list, applying the new filter, but not
854      throwing away information constructed on a previous pass. */
855   rescan_packets(cf, "Filtering", TRUE, FALSE);
856   return 1;
857 }
858
859 void
860 colorize_packets(capture_file *cf)
861 {
862   rescan_packets(cf, "Colorizing", FALSE, FALSE);
863 }
864
865 void
866 redissect_packets(capture_file *cf)
867 {
868   rescan_packets(cf, "Reprocessing", TRUE, TRUE);
869 }
870
871 /* Rescan the list of packets, reconstructing the CList.
872
873    "action" describes why we're doing this; it's used in the progress
874    dialog box.
875
876    "refilter" is TRUE if we need to re-evaluate the filter expression.
877
878    "redissect" is TRUE if we need to make the dissectors reconstruct
879    any state information they have (because a preference that affects
880    some dissector has changed, meaning some dissector might construct
881    its state differently from the way it was constructed the last time). */
882 static void
883 rescan_packets(capture_file *cf, const char *action, gboolean refilter,
884                 gboolean redissect)
885 {
886   frame_data *fdata;
887   progdlg_t *progbar;
888   gboolean stop_flag;
889   guint32 progbar_quantum;
890   guint32 progbar_nextstep;
891   int count;
892   frame_data *selected_frame;
893   int selected_row;
894   int row;
895
896   /* Which frame, if any, is the currently selected frame?
897      XXX - should the selected frame or the focus frame be the "current"
898      frame, that frame being the one from which "Find Frame" searches
899      start? */
900   selected_frame = cf->current_frame;
901
902   /* We don't yet know what row that frame will be on, if any, after we
903      rebuild the clist, however. */
904   selected_row = -1;
905
906   if (redissect) {
907     /* We need to re-initialize all the state information that protocols
908        keep, because some preference that controls a dissector has changed,
909        which might cause the state information to be constructed differently
910        by that dissector. */
911
912     /* Initialize the table of conversations. */
913     epan_conversation_init();
914
915     /* Initialize protocol-specific variables */
916     init_all_protocols();
917   }
918
919   /* Freeze the packet list while we redo it, so we don't get any
920      screen updates while it happens. */
921   gtk_clist_freeze(GTK_CLIST(packet_list));
922
923   /* Clear it out. */
924   gtk_clist_clear(GTK_CLIST(packet_list));
925
926   /* We don't yet know which will be the first and last frames displayed. */
927   cf->first_displayed = NULL;
928   cf->last_displayed = NULL;
929
930   /* Iterate through the list of frames.  Call a routine for each frame
931      to check whether it should be displayed and, if so, add it to
932      the display list. */
933   firstsec = 0;
934   firstusec = 0;
935   prevsec = 0;
936   prevusec = 0;
937
938   /* Update the progress bar when it gets to this value. */
939   progbar_nextstep = 0;
940   /* When we reach the value that triggers a progress bar update,
941      bump that value by this amount. */
942   progbar_quantum = cf->count/N_PROGBAR_UPDATES;
943   /* Count of packets at which we've looked. */
944   count = 0;
945
946   stop_flag = FALSE;
947   progbar = create_progress_dlg(action, "Stop", &stop_flag);
948
949   for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
950     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
951        when we update it, we have to run the GTK+ main loop to get it
952        to repaint what's pending, and doing so may involve an "ioctl()"
953        to see if there's any pending input from an X server, and doing
954        that for every packet can be costly, especially on a big file. */
955     if (count >= progbar_nextstep) {
956       /* let's not divide by zero. I should never be started
957        * with count == 0, so let's assert that
958        */
959       g_assert(cf->count > 0);
960
961       update_progress_dlg(progbar, (gfloat) count / cf->count);
962
963       progbar_nextstep += progbar_quantum;
964     }
965
966     if (stop_flag) {
967       /* Well, the user decided to abort the filtering.  Just stop.
968
969          XXX - go back to the previous filter?  Users probably just
970          want not to wait for a filtering operation to finish;
971          unless we cancel by having no filter, reverting to the
972          previous filter will probably be even more expensive than
973          continuing the filtering, as it involves going back to the
974          beginning and filtering, and even with no filter we currently
975          have to re-generate the entire clist, which is also expensive.
976
977          I'm not sure what Network Monitor does, but it doesn't appear
978          to give you an unfiltered display if you cancel. */
979       break;
980     }
981
982     count++;
983
984     if (redissect) {
985       /* Since all state for the frame was destroyed, mark the frame
986        * as not visited, free the GSList referring to the state
987        * data (the per-frame data itself was freed by
988        * "init_all_protocols()"), and null out the GSList pointer. */
989       fdata->flags.visited = 0;
990       if (fdata->pfd) {
991         g_slist_free(fdata->pfd);
992       }
993       fdata->pfd = NULL;
994       if (fdata->data_src) {    /* release data source list */
995         g_slist_free(fdata->data_src);
996       }
997       fdata->data_src = NULL;
998     }
999
1000     wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1001         cf->pd, fdata->cap_len);
1002
1003     row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
1004                                         refilter);
1005     if (fdata == selected_frame)
1006       selected_row = row;
1007   }
1008  
1009   if (redissect) {
1010     /* Clear out what remains of the visited flags and per-frame data
1011        pointers.
1012
1013        XXX - that may cause various forms of bogosity when dissecting
1014        these frames, as they won't have been seen by this sequential
1015        pass, but the only alternative I see is to keep scanning them
1016        even though the user requested that the scan stop, and that
1017        would leave the user stuck with an Ethereal grinding on
1018        until it finishes.  Should we just stick them with that? */
1019     for (; fdata != NULL; fdata = fdata->next) {
1020       fdata->flags.visited = 0;
1021       if (fdata->pfd) {
1022         g_slist_free(fdata->pfd);
1023       }
1024       fdata->pfd = NULL;
1025       if (fdata->data_src) {
1026         g_slist_free(fdata->data_src);
1027       }
1028       fdata->data_src = NULL;
1029     }
1030   }
1031
1032   /* We're done filtering the packets; destroy the progress bar. */
1033   destroy_progress_dlg(progbar);
1034
1035   /* Unfreeze the packet list. */
1036   gtk_clist_thaw(GTK_CLIST(packet_list));
1037
1038   if (selected_row != -1) {
1039     /* The frame that was selected passed the filter; select it, make it
1040        the focus row, and make it visible. */
1041     set_selected_row(selected_row);
1042     finfo_selected = NULL;
1043   } else {
1044     /* The selected frame didn't pass the filter; make the first frame
1045        the current frame, and leave it unselected. */
1046     unselect_packet(cf);
1047     cf->current_frame = cf->first_displayed;
1048   }
1049 }
1050
1051 int
1052 print_packets(capture_file *cf, print_args_t *print_args)
1053 {
1054   int         i;
1055   frame_data *fdata;
1056   progdlg_t  *progbar;
1057   gboolean    stop_flag;
1058   guint32     progbar_quantum;
1059   guint32     progbar_nextstep;
1060   guint32     count;
1061   proto_tree *protocol_tree;
1062   gint       *col_widths = NULL;
1063   gint        data_width;
1064   gboolean    print_separator;
1065   char       *line_buf = NULL;
1066   int         line_buf_len = 256;
1067   char        *cp;
1068   int         column_len;
1069   int         line_len;
1070   epan_dissect_t *edt = NULL;
1071
1072   cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
1073   if (cf->print_fh == NULL)
1074     return FALSE;       /* attempt to open destination failed */
1075
1076   print_preamble(cf->print_fh, print_args->format);
1077
1078   if (print_args->print_summary) {
1079     /* We're printing packet summaries.  Allocate the line buffer at
1080        its initial length. */
1081     line_buf = g_malloc(line_buf_len + 1);
1082
1083     /* Find the widths for each of the columns - maximum of the
1084        width of the title and the width of the data - and print
1085        the column titles. */
1086     col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1087     cp = &line_buf[0];
1088     line_len = 0;
1089     for (i = 0; i < cf->cinfo.num_cols; i++) {
1090       /* Don't pad the last column. */
1091       if (i == cf->cinfo.num_cols - 1)
1092         col_widths[i] = 0;
1093       else {
1094         col_widths[i] = strlen(cf->cinfo.col_title[i]);
1095         data_width = get_column_char_width(get_column_format(i));
1096         if (data_width > col_widths[i])
1097           col_widths[i] = data_width;
1098       }
1099
1100       /* Find the length of the string for this column. */
1101       column_len = strlen(cf->cinfo.col_title[i]);
1102       if (col_widths[i] > column_len)
1103         column_len = col_widths[i];
1104
1105       /* Make sure there's room in the line buffer for the column; if not,
1106          double its length. */
1107       line_len += column_len + 1;       /* "+1" for space or \n */
1108       if (line_len > line_buf_len) {
1109         line_buf_len *= 2;
1110         line_buf = g_realloc(line_buf, line_buf_len + 1);
1111       }
1112
1113       /* Right-justify the packet number column. */
1114       if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1115         sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_title[i]);
1116       else
1117         sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
1118       cp += column_len;
1119       if (i == cf->cinfo.num_cols - 1)
1120         *cp++ = '\n';
1121       else
1122         *cp++ = ' ';
1123     }
1124     *cp = '\0';
1125     print_line(cf->print_fh, print_args->format, line_buf);
1126   }
1127
1128   print_separator = FALSE;
1129
1130   /* The protocol tree will be "visible", i.e., printed, only if we're
1131      not printing a summary. */
1132   proto_tree_is_visible = !print_args->print_summary;
1133
1134   /* Update the progress bar when it gets to this value. */
1135   progbar_nextstep = 0;
1136   /* When we reach the value that triggers a progress bar update,
1137      bump that value by this amount. */
1138   progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1139   /* Count of packets at which we've looked. */
1140   count = 0;
1141
1142   stop_flag = FALSE;
1143   progbar = create_progress_dlg("Printing", "Stop", &stop_flag);
1144
1145   /* Iterate through the list of packets, printing the packets that
1146      were selected by the current display filter.  */
1147   for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1148     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1149        when we update it, we have to run the GTK+ main loop to get it
1150        to repaint what's pending, and doing so may involve an "ioctl()"
1151        to see if there's any pending input from an X server, and doing
1152        that for every packet can be costly, especially on a big file. */
1153     if (count >= progbar_nextstep) {
1154       /* let's not divide by zero. I should never be started
1155        * with count == 0, so let's assert that
1156        */
1157       g_assert(cf->count > 0);
1158
1159       update_progress_dlg(progbar, (gfloat) count / cf->count);
1160
1161       progbar_nextstep += progbar_quantum;
1162     }
1163
1164     if (stop_flag) {
1165       /* Well, the user decided to abort the printing.  Just stop.
1166
1167          XXX - note that what got generated before they did that
1168          will get printed, as we're piping to a print program; we'd
1169          have to write to a file and then hand that to the print
1170          program to make it actually not print anything. */
1171       break;
1172     }
1173
1174     count++;
1175
1176     if (fdata->flags.passed_dfilter) {
1177       wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1178                         cf->pd, fdata->cap_len);
1179       if (print_args->print_summary) {
1180         /* Fill in the column information, but don't bother creating
1181            the logical protocol tree. */
1182         fdata->cinfo = &cf->cinfo;
1183         for (i = 0; i < fdata->cinfo->num_cols; i++) {
1184           fdata->cinfo->col_buf[i][0] = '\0';
1185           fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
1186         }
1187         edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, NULL);
1188         fill_in_columns(fdata);
1189         cp = &line_buf[0];
1190         line_len = 0;
1191         for (i = 0; i < cf->cinfo.num_cols; i++) {
1192           /* Find the length of the string for this column. */
1193           column_len = strlen(cf->cinfo.col_data[i]);
1194           if (col_widths[i] > column_len)
1195             column_len = col_widths[i];
1196
1197           /* Make sure there's room in the line buffer for the column; if not,
1198              double its length. */
1199           line_len += column_len + 1;   /* "+1" for space or \n */
1200           if (line_len > line_buf_len) {
1201             line_buf_len *= 2;
1202             line_buf = g_realloc(line_buf, line_buf_len + 1);
1203           }
1204
1205           /* Right-justify the packet number column. */
1206           if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1207             sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_data[i]);
1208           else
1209             sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
1210           cp += column_len;
1211           if (i == cf->cinfo.num_cols - 1)
1212             *cp++ = '\n';
1213           else
1214             *cp++ = ' ';
1215         }
1216         *cp = '\0';
1217         print_line(cf->print_fh, print_args->format, line_buf);
1218       } else {
1219         if (print_separator)
1220           print_line(cf->print_fh, print_args->format, "\n");
1221
1222         /* Create the logical protocol tree. */
1223         protocol_tree = proto_tree_create_root();
1224         edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
1225
1226         /* Print the information in that tree. */
1227         proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
1228                         cf->pd, fdata, cf->print_fh);
1229
1230         proto_tree_free(protocol_tree);
1231
1232         if (print_args->print_hex) {
1233           /* Print the full packet data as hex. */
1234           print_hex_data(cf->print_fh, print_args->format, fdata);
1235         }
1236
1237         /* Print a blank line if we print anything after this. */
1238         print_separator = TRUE;
1239       }
1240       epan_dissect_free(edt);
1241     }
1242   }
1243
1244   /* We're done printing the packets; destroy the progress bar. */
1245   destroy_progress_dlg(progbar);
1246
1247   if (col_widths != NULL)
1248     g_free(col_widths);
1249   if (line_buf != NULL)
1250     g_free(line_buf);
1251
1252   print_finale(cf->print_fh, print_args->format);
1253
1254   close_print_dest(print_args->to_file, cf->print_fh);
1255  
1256   cf->print_fh = NULL;
1257
1258   proto_tree_is_visible = FALSE;
1259
1260   return TRUE;
1261 }
1262
1263 /* Scan through the packet list and change all columns that use the
1264    "command-line-specified" time stamp format to use the current
1265    value of that format. */
1266 void
1267 change_time_formats(capture_file *cf)
1268 {
1269   frame_data *fdata;
1270   progdlg_t *progbar;
1271   gboolean stop_flag;
1272   guint32 progbar_quantum;
1273   guint32 progbar_nextstep;
1274   int count;
1275   int row;
1276   int i;
1277   GtkStyle  *pl_style;
1278
1279   /* Freeze the packet list while we redo it, so we don't get any
1280      screen updates while it happens. */
1281   freeze_clist(cf);
1282
1283   /* Update the progress bar when it gets to this value. */
1284   progbar_nextstep = 0;
1285   /* When we reach the value that triggers a progress bar update,
1286      bump that value by this amount. */
1287   progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1288   /* Count of packets at which we've looked. */
1289   count = 0;
1290
1291   stop_flag = FALSE;
1292   progbar = create_progress_dlg("Changing time display", "Stop", &stop_flag);
1293
1294   /* Iterate through the list of packets, checking whether the packet
1295      is in a row of the summary list and, if so, whether there are
1296      any columns that show the time in the "command-line-specified"
1297      format and, if so, update that row. */
1298   for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1299     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1300        when we update it, we have to run the GTK+ main loop to get it
1301        to repaint what's pending, and doing so may involve an "ioctl()"
1302        to see if there's any pending input from an X server, and doing
1303        that for every packet can be costly, especially on a big file. */
1304     if (count >= progbar_nextstep) {
1305       /* let's not divide by zero. I should never be started
1306        * with count == 0, so let's assert that
1307        */
1308       g_assert(cf->count > 0);
1309
1310       update_progress_dlg(progbar, (gfloat) count / cf->count);
1311
1312       progbar_nextstep += progbar_quantum;
1313     }
1314
1315     if (stop_flag) {
1316       /* Well, the user decided to abort the redisplay.  Just stop.
1317
1318          XXX - this leaves the time field in the old format in
1319          frames we haven't yet processed.  So it goes; should we
1320          simply not offer them the option of stopping? */
1321       break;
1322     }
1323
1324     count++;
1325
1326     /* Find what row this packet is in. */
1327     row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1328
1329     if (row != -1) {
1330       /* This packet is in the summary list, on row "row". */
1331
1332       /* XXX - there really should be a way of checking "cf->cinfo" for this;
1333          the answer isn't going to change from packet to packet, so we should
1334          simply skip all the "change_time_formats()" work if we're not
1335          changing anything. */
1336       fdata->cinfo = &cf->cinfo;
1337       if (check_col(fdata, COL_CLS_TIME)) {
1338         /* There are columns that show the time in the "command-line-specified"
1339            format; update them. */
1340         for (i = 0; i < cf->cinfo.num_cols; i++) {
1341           if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1342             /* This is one of the columns that shows the time in
1343                "command-line-specified" format; update it. */
1344             cf->cinfo.col_buf[i][0] = '\0';
1345             col_set_cls_time(fdata, i);
1346             gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
1347                           cf->cinfo.col_data[i]);
1348           }
1349         }
1350       }
1351     }
1352   }
1353
1354   /* We're done redisplaying the packets; destroy the progress bar. */
1355   destroy_progress_dlg(progbar);
1356
1357   /* Set the column widths of those columns that show the time in
1358      "command-line-specified" format. */
1359   pl_style = gtk_widget_get_style(packet_list);
1360   for (i = 0; i < cf->cinfo.num_cols; i++) {
1361     if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1362       gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1363         gdk_string_width(pl_style->font, get_column_longest_string(COL_CLS_TIME)));
1364     }
1365   }
1366
1367   /* Unfreeze the packet list. */
1368   thaw_clist(cf);
1369 }
1370
1371 static void
1372 clear_tree_and_hex_views(void)
1373 {
1374   /* Clear the hex dump. */
1375
1376   GtkWidget *byte_view;
1377   int i;
1378
1379 /* Get the current tab scroll window, then get the text widget  */
1380 /* from the E_BYTE_VIEW_TEXT_INFO_KEY data field                */
1381
1382   i = gtk_notebook_get_current_page( GTK_NOTEBOOK(byte_nb_ptr));
1383
1384   if ( i >= 0){
1385     byte_view = gtk_notebook_get_nth_page( GTK_NOTEBOOK(byte_nb_ptr), i);
1386     byte_view = gtk_object_get_data(GTK_OBJECT(byte_view), E_BYTE_VIEW_TEXT_INFO_KEY);
1387
1388     gtk_text_freeze(GTK_TEXT(byte_view));
1389     gtk_text_set_point(GTK_TEXT(byte_view), 0);
1390     gtk_text_forward_delete(GTK_TEXT(byte_view),
1391       gtk_text_get_length(GTK_TEXT(byte_view)));
1392     gtk_text_thaw(GTK_TEXT(byte_view));
1393   }
1394   /* Remove all nodes in ctree. This is how it's done in testgtk.c in GTK+ */
1395   gtk_clist_clear ( GTK_CLIST(tree_view) );
1396
1397 }
1398
1399 gboolean
1400 find_packet(capture_file *cf, dfilter_t *sfcode)
1401 {
1402   frame_data *start_fd;
1403   frame_data *fdata;
1404   frame_data *new_fd = NULL;
1405   progdlg_t *progbar;
1406   gboolean stop_flag;
1407   guint32 progbar_quantum;
1408   guint32 progbar_nextstep;
1409   int count;
1410   proto_tree *protocol_tree;
1411   gboolean frame_matched;
1412   int row;
1413   epan_dissect_t        *edt;
1414
1415   start_fd = cf->current_frame;
1416   if (start_fd != NULL)  {
1417     /* Iterate through the list of packets, starting at the packet we've
1418        picked, calling a routine to run the filter on the packet, see if
1419        it matches, and stop if so.  */
1420     count = 0;
1421     fdata = start_fd;
1422
1423     /* Update the progress bar when it gets to this value. */
1424     progbar_nextstep = 0;
1425     /* When we reach the value that triggers a progress bar update,
1426        bump that value by this amount. */
1427     progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1428
1429     stop_flag = FALSE;
1430     progbar = create_progress_dlg("Searching", "Cancel", &stop_flag);
1431
1432     fdata = start_fd;
1433     for (;;) {
1434       /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1435          when we update it, we have to run the GTK+ main loop to get it
1436          to repaint what's pending, and doing so may involve an "ioctl()"
1437          to see if there's any pending input from an X server, and doing
1438          that for every packet can be costly, especially on a big file. */
1439       if (count >= progbar_nextstep) {
1440         /* let's not divide by zero. I should never be started
1441          * with count == 0, so let's assert that
1442          */
1443         g_assert(cf->count > 0);
1444
1445         update_progress_dlg(progbar, (gfloat) count / cf->count);
1446
1447         progbar_nextstep += progbar_quantum;
1448       }
1449
1450       if (stop_flag) {
1451         /* Well, the user decided to abort the search.  Go back to the
1452            frame where we started. */
1453         new_fd = start_fd;
1454         break;
1455       }
1456
1457       /* Go past the current frame. */
1458       if (cf->sbackward) {
1459         /* Go on to the previous frame. */
1460         fdata = fdata->prev;
1461         if (fdata == NULL)
1462           fdata = cf->plist_end;        /* wrap around */
1463       } else {
1464         /* Go on to the next frame. */
1465         fdata = fdata->next;
1466         if (fdata == NULL)
1467           fdata = cf->plist;    /* wrap around */
1468       }
1469
1470       count++;
1471
1472       /* Is this packet in the display? */
1473       if (fdata->flags.passed_dfilter) {
1474         /* Yes.  Does it match the search filter? */
1475         protocol_tree = proto_tree_create_root();
1476         wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
1477                         cf->pd, fdata->cap_len);
1478         edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
1479         frame_matched = dfilter_apply_edt(sfcode, edt);
1480         proto_tree_free(protocol_tree);
1481         epan_dissect_free(edt);
1482         if (frame_matched) {
1483           new_fd = fdata;
1484           break;        /* found it! */
1485         }
1486       }
1487
1488       if (fdata == start_fd) {
1489         /* We're back to the frame we were on originally, and that frame
1490            doesn't match the search filter.  The search failed. */
1491         break;
1492       }
1493     }
1494
1495     /* We're done scanning the packets; destroy the progress bar. */
1496     destroy_progress_dlg(progbar);
1497   }
1498
1499   if (new_fd != NULL) {
1500     /* We found a frame.  Find what row it's in. */
1501     row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), new_fd);
1502     g_assert(row != -1);
1503
1504     /* Select that row, make it the focus row, and make it visible. */
1505     set_selected_row(row);
1506     return TRUE;        /* success */
1507   } else
1508     return FALSE;       /* failure */
1509 }
1510
1511 goto_result_t
1512 goto_frame(capture_file *cf, guint fnumber)
1513 {
1514   frame_data *fdata;
1515   int row;
1516
1517   for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
1518     ;
1519
1520   if (fdata == NULL)
1521     return NO_SUCH_FRAME;       /* we didn't find that frame */
1522   if (!fdata->flags.passed_dfilter)
1523     return FRAME_NOT_DISPLAYED; /* the frame with that number isn't displayed */
1524
1525   /* We found that frame, and it's currently being displayed.
1526      Find what row it's in. */
1527   row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1528   g_assert(row != -1);
1529
1530   /* Select that row, make it the focus row, and make it visible. */
1531   set_selected_row(row);
1532   return FOUND_FRAME;
1533 }
1534
1535 /* Select the packet on a given row. */
1536 void
1537 select_packet(capture_file *cf, int row)
1538 {
1539   frame_data *fdata;
1540   tvbuff_t *bv_tvb;
1541   int i;
1542
1543   /* Get the frame data struct pointer for this frame */
1544   fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
1545
1546   if (fdata == NULL) {
1547     /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
1548        the first entry is added to it by "real_insert_row()", that row
1549        is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
1550        our version and the vanilla GTK+ version).
1551
1552        This means that a "select-row" signal is emitted; this causes
1553        "packet_list_select_cb()" to be called, which causes "select_packet()"
1554        to be called.
1555
1556        "select_packet()" fetches, above, the data associated with the
1557        row that was selected; however, as "gtk_clist_append()", which
1558        called "real_insert_row()", hasn't yet returned, we haven't yet
1559        associated any data with that row, so we get back a null pointer.
1560
1561        We can't assume that there's only one frame in the frame list,
1562        either, as we may be filtering the display.
1563
1564        We therefore assume that, if "row" is 0, i.e. the first row
1565        is being selected, and "cf->first_displayed" equals
1566        "cf->last_displayed", i.e. there's only one frame being
1567        displayed, that frame is the frame we want.
1568
1569        This means we have to set "cf->first_displayed" and
1570        "cf->last_displayed" before adding the row to the
1571        GtkCList; see the comment in "add_packet_to_packet_list()". */
1572
1573        if (row == 0 && cf->first_displayed == cf->last_displayed)
1574          fdata = cf->first_displayed;
1575   }
1576
1577   /* Record that this frame is the current frame. */
1578   cf->current_frame = fdata;
1579
1580   /* Get the data in that frame. */
1581   wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1582                         cf->pd, fdata->cap_len);
1583
1584   /* Create the logical protocol tree. */
1585   if (cf->protocol_tree)
1586       proto_tree_free(cf->protocol_tree);
1587   cf->protocol_tree = proto_tree_create_root();
1588   proto_tree_is_visible = TRUE;
1589   cf->edt = epan_dissect_new(&cf->pseudo_header, cf->pd, cf->current_frame,
1590                 cf->protocol_tree);
1591   proto_tree_is_visible = FALSE;
1592
1593   /* Display the GUI protocol tree and hex dump. */
1594   clear_tree_and_hex_views();
1595
1596   i = 0; 
1597   while((bv_tvb = g_slist_nth_data ( cf->current_frame->data_src, i++))){
1598         add_byte_view( tvb_get_name( bv_tvb), tvb_get_ptr(bv_tvb, 0, -1), tvb_length(bv_tvb));
1599   }
1600
1601   proto_tree_draw(cf->protocol_tree, tree_view);
1602
1603   set_notebook_page( byte_nb_ptr, 0);
1604
1605   /* A packet is selected. */
1606   set_menus_for_selected_packet(TRUE);
1607 }
1608
1609 /* Unselect the selected packet, if any. */
1610 void
1611 unselect_packet(capture_file *cf)
1612 {
1613   /* Destroy the protocol tree for that packet. */
1614   if (cf->protocol_tree != NULL) {
1615     proto_tree_free(cf->protocol_tree);
1616     cf->protocol_tree = NULL;
1617     epan_dissect_free(cf->edt);
1618   }
1619
1620   finfo_selected = NULL;
1621
1622   /* Clear out the display of that packet. */
1623   clear_tree_and_hex_views();
1624
1625   /* No packet is selected. */
1626   set_menus_for_selected_packet(FALSE);
1627 }
1628
1629 /* Set the selected row and the focus row of the packet list to the specified
1630    row, and make it visible if it's not currently visible. */
1631 static void
1632 set_selected_row(int row)
1633 {
1634   if (gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) != GTK_VISIBILITY_FULL)
1635     gtk_clist_moveto(GTK_CLIST(packet_list), row, -1, 0.0, 0.0);
1636
1637   /* XXX - why is there no "gtk_clist_set_focus_row()", so that we
1638      can make the row for the frame we found the focus row?
1639
1640      See
1641
1642  http://www.gnome.org/mailing-lists/archives/gtk-list/2000-January/0038.shtml
1643
1644      */
1645   GTK_CLIST(packet_list)->focus_row = row;
1646
1647   gtk_clist_select_row(GTK_CLIST(packet_list), row, -1);
1648 }
1649
1650 static void
1651 freeze_clist(capture_file *cf)
1652 {
1653   int i;
1654
1655   /* Make the column sizes static, so they don't adjust while
1656      we're reading the capture file (freezing the clist doesn't
1657      seem to suffice). */
1658   for (i = 0; i < cf->cinfo.num_cols; i++)
1659     gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1660   gtk_clist_freeze(GTK_CLIST(packet_list));
1661 }
1662
1663 static void
1664 thaw_clist(capture_file *cf)
1665 {
1666   int i;
1667
1668   for (i = 0; i < cf->cinfo.num_cols; i++) {
1669     if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1670       /* Set this column's width to the appropriate value. */
1671       gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1672                                 cf->cinfo.col_width[i]);
1673     } else {
1674       /* Make this column's size dynamic, so that it adjusts to the
1675          appropriate size. */
1676       gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1677     }
1678   }
1679   gtk_clist_thaw(GTK_CLIST(packet_list));
1680
1681   /* Hopefully, the columns have now gotten their appropriate sizes;
1682      make them resizeable - a column that auto-resizes cannot be
1683      resized by the user, and *vice versa*. */
1684   for (i = 0; i < cf->cinfo.num_cols; i++)
1685     gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1686 }
1687
1688 int
1689 save_cap_file(char *fname, capture_file *cf, gboolean save_filtered, gboolean save_marked,
1690                 guint save_format)
1691 {
1692   gchar        *from_filename;
1693   gchar        *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
1694   size_t        msg_len;
1695   int           err;
1696   gboolean      do_copy;
1697   wtap_dumper  *pdh;
1698   frame_data   *fdata;
1699   struct wtap_pkthdr hdr;
1700   union wtap_pseudo_header pseudo_header;
1701   guint8        pd[65536];
1702
1703   name_ptr = get_basename(fname);
1704   msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
1705   save_msg = g_malloc(msg_len);
1706   snprintf(save_msg, msg_len, save_fmt, name_ptr);
1707   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
1708   g_free(save_msg);
1709
1710   if (!save_filtered && !save_marked && save_format == cf->cd_t) {
1711     /* We're not filtering packets, and we're saving it in the format
1712        it's already in, so we can just move or copy the raw data. */
1713
1714     /* In this branch, we set "err" only if we get an error, so we
1715        must first clear it. */
1716     err = 0;
1717     if (cf->is_tempfile) {
1718       /* The file being saved is a temporary file from a live
1719          capture, so it doesn't need to stay around under that name;
1720          first, try renaming the capture buffer file to the new name. */
1721 #ifndef WIN32
1722       if (rename(cf->filename, fname) == 0) {
1723         /* That succeeded - there's no need to copy the source file. */
1724         from_filename = NULL;
1725         do_copy = FALSE;
1726       } else {
1727         if (errno == EXDEV) {
1728           /* They're on different file systems, so we have to copy the
1729              file. */
1730           do_copy = TRUE;
1731           from_filename = cf->filename;
1732         } else {
1733           /* The rename failed, but not because they're on different
1734              file systems - put up an error message.  (Or should we
1735              just punt and try to copy?  The only reason why I'd
1736              expect the rename to fail and the copy to succeed would
1737              be if we didn't have permission to remove the file from
1738              the temporary directory, and that might be fixable - but
1739              is it worth requiring the user to go off and fix it?) */
1740           err = errno;
1741           simple_dialog(ESD_TYPE_CRIT, NULL,
1742                                 file_rename_error_message(err), fname);
1743           goto done;
1744         }
1745       }
1746 #else
1747       do_copy = TRUE;
1748       from_filename = cf->filename;
1749 #endif
1750     } else {
1751       /* It's a permanent file, so we should copy it, and not remove the
1752          original. */
1753       do_copy = TRUE;
1754       from_filename = cf->filename;
1755     }
1756     /* Copy the file, if we haven't moved it. */
1757     if (do_copy) {
1758             if (!copy_binary_file(from_filename, fname)) {
1759                 goto done;
1760             }
1761     }
1762   } else {
1763     /* Either we're filtering packets, or we're saving in a different
1764        format; we can't do that by copying or moving the capture file,
1765        we have to do it by writing the packets out in Wiretap. */
1766     pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
1767     if (pdh == NULL) {
1768       simple_dialog(ESD_TYPE_CRIT, NULL,
1769                         file_open_error_message(err, TRUE), fname);
1770       goto done;
1771     }
1772
1773     /* XXX - have a way to save only the packets currently selected by
1774        the display filter or the marked ones.
1775
1776        If we do that, should we make that file the current file?  If so,
1777        it means we can no longer get at the other packets.  What does
1778        NetMon do? */
1779     for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1780       /* XXX - do a progress bar */
1781       if ((!save_filtered && !save_marked) ||
1782           (save_filtered && fdata->flags.passed_dfilter && !save_marked) ||
1783           (save_marked && fdata->flags.marked && !save_filtered) ||
1784           (save_filtered && save_marked && fdata->flags.passed_dfilter &&
1785            fdata->flags.marked)) {
1786         /* Either :
1787            - we're saving all frames, or
1788            - we're saving filtered frames and this one passed the display filter or
1789            - we're saving marked frames (and it has been marked) or
1790            - we're saving filtered _and_ marked frames,
1791            save it. */
1792         hdr.ts.tv_sec = fdata->abs_secs;
1793         hdr.ts.tv_usec = fdata->abs_usecs;
1794         hdr.caplen = fdata->cap_len;
1795         hdr.len = fdata->pkt_len;
1796         hdr.pkt_encap = fdata->lnk_t;
1797         wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1798                 pd, fdata->cap_len);
1799
1800         if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
1801             simple_dialog(ESD_TYPE_CRIT, NULL,
1802                                 file_write_error_message(err), fname);
1803             wtap_dump_close(pdh, &err);
1804             goto done;
1805         }
1806       }
1807     }
1808
1809     if (!wtap_dump_close(pdh, &err)) {
1810       simple_dialog(ESD_TYPE_WARN, NULL,
1811                 file_close_error_message(err), fname);
1812       goto done;
1813     }
1814   }
1815
1816 done:
1817
1818   /* Pop the "Saving:" message off the status bar. */
1819   gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
1820   if (err == 0) {
1821     if (!save_filtered && !save_marked) {
1822       /* We saved the entire capture, not just some packets from it.
1823          Open and read the file we saved it to.
1824
1825          XXX - this is somewhat of a waste; we already have the
1826          packets, all this gets us is updated file type information
1827          (which we could just stuff into "cf"), and having the new
1828          file be the one we have opened and from which we're reading
1829          the data, and it means we have to spend time opening and
1830          reading the file, which could be a significant amount of
1831          time if the file is large. */
1832       cf->user_saved = TRUE;
1833
1834       if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
1835         /* XXX - report errors if this fails? */
1836         switch (read_cap_file(cf, &err)) {
1837
1838         case READ_SUCCESS:
1839         case READ_ERROR:
1840           /* Just because we got an error, that doesn't mean we were unable
1841              to read any of the file; we handle what we could get from the
1842              file. */
1843           break;
1844
1845         case READ_ABORTED:
1846           /* The user bailed out of re-reading the capture file; the
1847              capture file has been closed - just return (without
1848              changing any menu settings; "close_cap_file()" set them
1849              correctly for the "no capture file open" state). */
1850           return 0;
1851         }
1852         set_menus_for_unsaved_capture_file(FALSE);
1853       }
1854     }
1855   }
1856   return err;
1857 }
1858
1859 char *
1860 file_open_error_message(int err, gboolean for_writing)
1861 {
1862   char *errmsg;
1863   static char errmsg_errno[1024+1];
1864
1865   switch (err) {
1866
1867   case WTAP_ERR_NOT_REGULAR_FILE:
1868     errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1869     break;
1870
1871   case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1872   case WTAP_ERR_UNSUPPORTED:
1873     /* Seen only when opening a capture file for reading. */
1874     errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1875     break;
1876
1877   case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1878     /* Seen only when opening a capture file for writing. */
1879     errmsg = "Ethereal does not support writing capture files in that format.";
1880     break;
1881
1882   case WTAP_ERR_UNSUPPORTED_ENCAP:
1883   case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1884     if (for_writing)
1885       errmsg = "Ethereal cannot save this capture in that format.";
1886     else
1887       errmsg = "The file \"%s\" is a capture for a network type that Ethereal doesn't support.";
1888     break;
1889
1890   case WTAP_ERR_BAD_RECORD:
1891     errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1892     break;
1893
1894   case WTAP_ERR_CANT_OPEN:
1895     if (for_writing)
1896       errmsg = "The file \"%s\" could not be created for some unknown reason.";
1897     else
1898       errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1899     break;
1900
1901   case WTAP_ERR_SHORT_READ:
1902     errmsg = "The file \"%s\" appears to have been cut short"
1903              " in the middle of a packet.";
1904     break;
1905
1906   case WTAP_ERR_SHORT_WRITE:
1907     errmsg = "A full header couldn't be written to the file \"%s\".";
1908     break;
1909
1910   case ENOENT:
1911     if (for_writing)
1912       errmsg = "The path to the file \"%s\" does not exist.";
1913     else
1914       errmsg = "The file \"%s\" does not exist.";
1915     break;
1916
1917   case EACCES:
1918     if (for_writing)
1919       errmsg = "You do not have permission to create or write to the file \"%s\".";
1920     else
1921       errmsg = "You do not have permission to read the file \"%s\".";
1922     break;
1923
1924   case EISDIR:
1925     errmsg = "\"%s\" is a directory (folder), not a file.";
1926     break;
1927
1928   default:
1929     snprintf(errmsg_errno, sizeof(errmsg_errno),
1930                     "The file \"%%s\" could not be opened: %s.",
1931                                 wtap_strerror(err));
1932     errmsg = errmsg_errno;
1933     break;
1934   }
1935   return errmsg;
1936 }
1937
1938 static char *
1939 file_rename_error_message(int err)
1940 {
1941   char *errmsg;
1942   static char errmsg_errno[1024+1];
1943
1944   switch (err) {
1945
1946   case ENOENT:
1947     errmsg = "The path to the file \"%s\" does not exist.";
1948     break;
1949
1950   case EACCES:
1951     errmsg = "You do not have permission to move the capture file to \"%s\".";
1952     break;
1953
1954   default:
1955     snprintf(errmsg_errno, sizeof(errmsg_errno),
1956                     "The file \"%%s\" could not be moved: %s.",
1957                                 wtap_strerror(err));
1958     errmsg = errmsg_errno;
1959     break;
1960   }
1961   return errmsg;
1962 }
1963
1964 char *
1965 file_read_error_message(int err)
1966 {
1967   static char errmsg_errno[1024+1];
1968
1969   snprintf(errmsg_errno, sizeof(errmsg_errno),
1970                   "An error occurred while reading from the file \"%%s\": %s.",
1971                                 wtap_strerror(err));
1972   return errmsg_errno;
1973 }
1974
1975 char *
1976 file_write_error_message(int err)
1977 {
1978   char *errmsg;
1979   static char errmsg_errno[1024+1];
1980
1981   switch (err) {
1982
1983   case ENOSPC:
1984     errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1985     break;
1986
1987 #ifdef EDQUOT
1988   case EDQUOT:
1989     errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1990     break;
1991 #endif
1992
1993   default:
1994     snprintf(errmsg_errno, sizeof(errmsg_errno),
1995                     "An error occurred while writing to the file \"%%s\": %s.",
1996                                 wtap_strerror(err));
1997     errmsg = errmsg_errno;
1998     break;
1999   }
2000   return errmsg;
2001 }
2002
2003 /* Check for write errors - if the file is being written to an NFS server,
2004    a write error may not show up until the file is closed, as NFS clients
2005    might not send writes to the server until the "write()" call finishes,
2006    so that the write may fail on the server but the "write()" may succeed. */
2007 static char *
2008 file_close_error_message(int err)
2009 {
2010   char *errmsg;
2011   static char errmsg_errno[1024+1];
2012
2013   switch (err) {
2014
2015   case WTAP_ERR_CANT_CLOSE:
2016     errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
2017     break;
2018
2019   case WTAP_ERR_SHORT_WRITE:
2020     errmsg = "Not all the packets could be written to the file \"%s\".";
2021     break;
2022
2023   case ENOSPC:
2024     errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
2025     break;
2026
2027 #ifdef EDQUOT
2028   case EDQUOT:
2029     errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
2030     break;
2031 #endif
2032
2033   default:
2034     snprintf(errmsg_errno, sizeof(errmsg_errno),
2035                     "An error occurred while closing the file \"%%s\": %s.",
2036                                 wtap_strerror(err));
2037     errmsg = errmsg_errno;
2038     break;
2039   }
2040   return errmsg;
2041 }
2042
2043
2044 /* Copies a file in binary mode, for those operating systems that care about
2045  * such things.
2046  * Returns TRUE on success, FALSE on failure. If a failure, it also
2047  * displays a simple dialog window with the error message.
2048  */
2049 static gboolean
2050 copy_binary_file(char *from_filename, char *to_filename)
2051 {
2052         int           from_fd, to_fd, nread, nwritten, err;
2053         guint8        pd[65536]; /* XXX - Hmm, 64K here, 64K in save_cap_file(),
2054                                     perhaps we should make just one 64K buffer. */
2055
2056       /* Copy the raw bytes of the file. */
2057       from_fd = open(from_filename, O_RDONLY | O_BINARY);
2058       if (from_fd < 0) {
2059         err = errno;
2060         simple_dialog(ESD_TYPE_CRIT, NULL,
2061                         file_open_error_message(err, TRUE), from_filename);
2062         goto done;
2063       }
2064
2065       /* Use open() instead of creat() so that we can pass the O_BINARY
2066          flag, which is relevant on Win32; it appears that "creat()"
2067          may open the file in text mode, not binary mode, but we want
2068          to copy the raw bytes of the file, so we need the output file
2069          to be open in binary mode. */
2070       to_fd = open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
2071       if (to_fd < 0) {
2072         err = errno;
2073         simple_dialog(ESD_TYPE_CRIT, NULL,
2074                         file_open_error_message(err, TRUE), to_filename);
2075         close(from_fd);
2076         goto done;
2077       }
2078
2079       while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
2080         nwritten = write(to_fd, pd, nread);
2081         if (nwritten < nread) {
2082           if (nwritten < 0)
2083             err = errno;
2084           else
2085             err = WTAP_ERR_SHORT_WRITE;
2086           simple_dialog(ESD_TYPE_CRIT, NULL,
2087                                 file_write_error_message(err), to_filename);
2088           close(from_fd);
2089           close(to_fd);
2090           goto done;
2091         }
2092       }
2093       if (nread < 0) {
2094         err = errno;
2095         simple_dialog(ESD_TYPE_CRIT, NULL,
2096                         file_read_error_message(err), from_filename);
2097         close(from_fd);
2098         close(to_fd);
2099         goto done;
2100       }
2101       close(from_fd);
2102       if (close(to_fd) < 0) {
2103         err = errno;
2104         simple_dialog(ESD_TYPE_CRIT, NULL,
2105                 file_close_error_message(err), to_filename);
2106         goto done;
2107       }
2108
2109       return TRUE;
2110
2111    done:
2112       return FALSE;
2113 }