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