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