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