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