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