4 * $Id: file.c,v 1.135 1999/12/09 07:19:03 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
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.
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.
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.
51 #ifdef NEED_SNPRINTF_H
57 # include "snprintf.h"
60 #ifdef NEED_STRERROR_H
64 #ifdef HAVE_SYS_TYPES_H
65 # include <sys/types.h>
68 #ifdef HAVE_NETINET_IN_H
69 # include <netinet/in.h>
80 #include "gtk/proto_draw.h"
82 #include "timestamp.h"
83 #include "conversation.h"
90 #include "packet-atalk.h"
92 #include "packet-ipv6.h"
94 #include "packet-sna.h"
96 #include "packet-vines.h"
98 extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view;
99 extern guint file_ctx;
101 gboolean auto_scroll_live = FALSE;
103 static guint32 firstsec, firstusec;
104 static guint32 prevsec, prevusec;
106 static void wtap_dispatch_cb(u_char *, const struct wtap_pkthdr *, int,
109 static void freeze_clist(capture_file *cf);
110 static void thaw_clist(capture_file *cf);
112 static char *file_rename_error_message(int err);
113 static char *file_close_error_message(int err);
115 /* Update the progress bar this many times when reading a file. */
116 #define N_PROGBAR_UPDATES 100
119 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
127 wth = wtap_open_offline(fname, &err);
131 /* Find the size of the file. */
134 if (fstat(fd, &cf_stat) < 0) {
140 /* The open succeeded. Close whatever capture file we had open,
141 and fill in the information for this file. */
142 close_cap_file(cf, info_bar);
144 /* Initialize the table of conversations. */
147 /* Initialize protocol-specific variables */
148 init_all_protocols();
153 cf->f_len = cf_stat.st_size;
155 /* Set the file name because we need it to set the follow stream filter.
156 XXX - is that still true? We need it for other reasons, though,
158 cf->filename = g_strdup(fname);
160 /* Indicate whether it's a permanent or temporary file. */
161 cf->is_tempfile = is_tempfile;
163 /* If it's a temporary capture buffer file, mark it as not saved. */
164 cf->user_saved = !is_tempfile;
166 cf->cd_t = wtap_file_type(cf->wth);
171 cf->snap = wtap_snapshot_length(cf->wth);
172 cf->update_progbar = FALSE;
173 cf->progbar_quantum = 0;
174 cf->progbar_nextstep = 0;
175 firstsec = 0, firstusec = 0;
176 prevsec = 0, prevusec = 0;
181 simple_dialog(ESD_TYPE_WARN, NULL,
182 file_open_error_message(err, FALSE), fname);
186 /* Reset everything to a pristine state */
188 close_cap_file(capture_file *cf, void *w)
190 frame_data *fd, *fd_next;
200 /* We have no file open... */
201 if (cf->filename != NULL) {
202 /* If it's a temporary file, remove it. */
204 unlink(cf->filename);
205 g_free(cf->filename);
208 /* ...which means we have nothing to save. */
209 cf->user_saved = FALSE;
211 for (fd = cf->plist; fd != NULL; fd = fd_next) {
215 if (cf->rfcode != NULL) {
216 dfilter_destroy(cf->rfcode);
220 cf->plist_end = NULL;
221 unselect_packet(cf); /* nothing to select */
223 /* Clear the packet list. */
224 gtk_clist_freeze(GTK_CLIST(packet_list));
225 gtk_clist_clear(GTK_CLIST(packet_list));
226 gtk_clist_thaw(GTK_CLIST(packet_list));
228 /* Clear any file-related status bar messages.
229 XXX - should be "clear *ALL* file-related status bar messages;
230 will there ever be more than one on the stack? */
231 gtk_statusbar_pop(GTK_STATUSBAR(w), file_ctx);
233 /* Restore the standard title bar message. */
234 set_main_window_name("The Ethereal Network Analyzer");
236 /* Disable all menu items that make sense only if you have a capture. */
237 set_menu_sensitivity("/File/Save", FALSE);
238 set_menu_sensitivity("/File/Save As...", FALSE);
239 set_menu_sensitivity("/File/Close", FALSE);
240 set_menu_sensitivity("/File/Reload", FALSE);
241 set_menu_sensitivity("/File/Print...", FALSE);
242 set_menu_sensitivity("/Display/Options...", FALSE);
243 set_menu_sensitivity("/Display/Match Selected", FALSE);
244 set_menu_sensitivity("/Display/Colorize Display...", FALSE);
245 set_menu_sensitivity("/Display/Find Frame...", FALSE);
246 set_menu_sensitivity("/Display/Go To Frame...", FALSE);
247 set_menu_sensitivity("/Display/Collapse All", FALSE);
248 set_menu_sensitivity("/Display/Expand All", FALSE);
249 set_menu_sensitivity("/Tools/Follow TCP Stream", FALSE);
250 set_menu_sensitivity("/Tools/Graph", FALSE);
251 set_menu_sensitivity("/Tools/Summary", FALSE);
254 /* Set the file name in the status line, in the name for the main window,
255 and in the name for the main window's icon. */
257 set_display_filename(capture_file *cf)
261 gchar *done_fmt = " File: %s Drops: %u";
263 gchar *win_name_fmt = "%s - Ethereal";
266 if (!cf->is_tempfile) {
267 /* Get the last component of the file name, and put that in the
269 if ((name_ptr = (gchar *) strrchr(cf->filename, '/')) == NULL)
270 name_ptr = cf->filename;
274 /* The file we read is a temporary file from a live capture;
275 we don't mention its name in the status bar. */
276 name_ptr = "<capture>";
279 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
280 done_msg = g_malloc(msg_len);
281 snprintf(done_msg, msg_len, done_fmt, name_ptr, cf->drops);
282 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
285 msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
286 win_name = g_malloc(msg_len);
287 snprintf(win_name, msg_len, win_name_fmt, name_ptr);
288 set_main_window_name(win_name);
293 read_cap_file(capture_file *cf)
295 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
300 char errmsg_errno[1024+1];
301 gchar err_str[2048+1];
303 if ((name_ptr = (gchar *) strrchr(cf->filename, '/')) == NULL)
304 name_ptr = cf->filename;
308 msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
309 load_msg = g_malloc(msg_len);
310 snprintf(load_msg, msg_len, load_fmt, name_ptr);
311 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
314 cf->update_progbar = TRUE;
315 /* Update the progress bar when it gets to this value. */
316 cf->progbar_nextstep = 0;
317 /* When we reach the value that triggers a progress bar update,
318 bump that value by this amount. */
319 cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
322 proto_tree_is_visible = FALSE;
323 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
324 /* Set the file encapsulation type now; we don't know what it is until
325 we've looked at all the packets, as we don't know until then whether
326 there's more than one type (and thus whether it's
327 WTAP_ENCAP_PER_PACKET). */
328 cf->lnk_t = wtap_file_encap(cf->wth);
331 cf->filed = open(cf->filename, O_RDONLY);
332 cf->fh = filed_open(cf->filed, "r");
333 cf->unfiltered_count = cf->count;
334 cf->current_frame = cf->first_displayed;
335 /* Make the first row the selected row. */
336 gtk_clist_select_row(GTK_CLIST(packet_list), 0, -1);
339 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
340 gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
342 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
343 set_display_filename(cf);
345 /* Enable menu items that make sense if you have a capture file you've
347 set_menu_sensitivity("/File/Save", !cf->user_saved);
348 set_menu_sensitivity("/File/Save As...", TRUE);
349 set_menu_sensitivity("/File/Close", TRUE);
350 set_menu_sensitivity("/File/Reload", TRUE);
351 set_menu_sensitivity("/File/Print...", TRUE);
353 /* Enable menu items that make sense if you have some captured packets. */
354 set_menu_sensitivity("/Display/Options...", TRUE);
355 set_menu_sensitivity("/Display/Match Selected", TRUE);
356 set_menu_sensitivity("/Display/Colorize Display...", TRUE);
357 set_menu_sensitivity("/Display/Find Frame...", TRUE);
358 set_menu_sensitivity("/Display/Go To Frame...", TRUE);
359 set_menu_sensitivity("/Tools/Graph", TRUE);
360 set_menu_sensitivity("/Tools/Summary", TRUE);
363 /* Put up a message box noting that the read failed somewhere along
364 the line. Don't throw out the stuff we managed to read, though,
368 case WTAP_ERR_CANT_READ:
369 errmsg = "An attempt to read from the file failed for"
370 " some unknown reason.";
373 case WTAP_ERR_SHORT_READ:
374 errmsg = "The capture file appears to have been cut short"
375 " in the middle of a packet.";
378 case WTAP_ERR_BAD_RECORD:
379 errmsg = "The capture file appears to be damaged or corrupt.";
383 sprintf(errmsg_errno, "An error occurred while reading the"
384 " capture file: %s.", wtap_strerror(err));
385 errmsg = errmsg_errno;
388 snprintf(err_str, sizeof err_str, errmsg);
389 simple_dialog(ESD_TYPE_WARN, NULL, err_str);
397 start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
402 err = open_cap_file(fname, is_tempfile, cf);
404 /* Disable menu items that make sense only if you have a capture
405 file you've finished reading. */
406 set_menu_sensitivity("/File/Open...", FALSE);
408 /* Disable menu items that make sense only if you're not currently
409 running a capture. */
410 set_menu_sensitivity("/Capture/Start...", FALSE);
412 /* Enable menu items that make sense if you have some captured
413 packets (yes, I know, we don't have any *yet*). */
414 set_menu_sensitivity("/Display/Options...", TRUE);
415 set_menu_sensitivity("/Display/Match Selected", TRUE);
416 set_menu_sensitivity("/Display/Colorize Display...", TRUE);
417 set_menu_sensitivity("/Display/Find Frame...", TRUE);
418 set_menu_sensitivity("/Display/Go To Frame...", TRUE);
419 set_menu_sensitivity("/Tools/Graph", TRUE);
420 set_menu_sensitivity("/Tools/Summary", TRUE);
422 for (i = 0; i < cf->cinfo.num_cols; i++) {
423 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
424 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
426 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
427 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
428 cf->cinfo.col_width[i]);
429 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
433 /* Yes, "open_cap_file()" set this - but it set it to a file handle
434 from Wiretap, which will be closed when we close the file; we
435 want it to remain open even after that, so that we can read
436 packet data from it. */
437 cf->fh = file_open(fname, "r");
439 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
440 " <live capture in progress>");
446 continue_tail_cap_file(capture_file *cf, int to_read)
450 gtk_clist_freeze(GTK_CLIST(packet_list));
452 wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf, &err);
454 gtk_clist_thaw(GTK_CLIST(packet_list));
455 if (auto_scroll_live && cf->plist_end != NULL)
456 gtk_clist_moveto(GTK_CLIST(packet_list),
457 cf->plist_end->row, -1, 1.0, 1.0);
462 finish_tail_cap_file(capture_file *cf)
466 gtk_clist_freeze(GTK_CLIST(packet_list));
468 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
471 if (auto_scroll_live && cf->plist_end != NULL)
472 gtk_clist_moveto(GTK_CLIST(packet_list),
473 cf->plist_end->row, -1, 1.0, 1.0);
475 /* Set the file encapsulation type now; we don't know what it is until
476 we've looked at all the packets, as we don't know until then whether
477 there's more than one type (and thus whether it's
478 WTAP_ENCAP_PER_PACKET). */
479 cf->lnk_t = wtap_file_encap(cf->wth);
481 /* There's nothing more to read from the capture file - close it. */
485 /* Pop the "<live capture in progress>" message off the status bar. */
486 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
488 set_display_filename(cf);
490 /* Restore the "File/Open" menu item. */
491 set_menu_sensitivity("/File/Open...", TRUE);
493 /* Enable menu items that make sense if you have a capture file
494 you've finished reading. */
495 set_menu_sensitivity("/File/Save", !cf->user_saved);
496 set_menu_sensitivity("/File/Save As...", TRUE);
497 set_menu_sensitivity("/File/Close", TRUE);
498 set_menu_sensitivity("/File/Reload", TRUE);
499 set_menu_sensitivity("/File/Print...", TRUE);
501 /* Enable menu items that make sense if you're not currently running
503 set_menu_sensitivity("/Capture/Start...", TRUE);
507 #endif /* HAVE_LIBPCAP */
509 /* To do: Add check_col checks to the col_add* routines */
512 col_set_abs_time(frame_data *fd, int col)
518 tmp = localtime(&then);
519 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld",
523 (long)fd->abs_usecs/100);
527 col_set_rel_time(frame_data *fd, int col)
529 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->rel_secs,
534 col_set_delta_time(frame_data *fd, int col)
536 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->del_secs,
540 /* Add "command-line-specified" time. */
542 col_set_cls_time(frame_data *fd, int col)
544 switch (timestamp_type) {
546 col_set_abs_time(fd, col);
550 col_set_rel_time(fd, col);
554 col_set_delta_time(fd, col);
560 col_set_addr(frame_data *fd, int col, address *addr, gboolean is_res)
563 struct e_in6_addr ipv6_addr;
564 struct atalk_ddp_addr ddp_addr;
565 struct sna_fid_type_4_addr sna_fid_type_4_addr;
567 switch (addr->type) {
571 strncpy(fd->cinfo->col_data[col], get_ether_name(addr->data), COL_MAX_LEN);
573 strncpy(fd->cinfo->col_data[col], ether_to_str(addr->data), COL_MAX_LEN);
577 memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
579 strncpy(fd->cinfo->col_data[col], get_hostname(ipv4_addr), COL_MAX_LEN);
581 strncpy(fd->cinfo->col_data[col], ip_to_str(addr->data), COL_MAX_LEN);
585 memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
587 strncpy(fd->cinfo->col_data[col], get_hostname6(&ipv6_addr), COL_MAX_LEN);
589 strncpy(fd->cinfo->col_data[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
593 strncpy(fd->cinfo->col_data[col],
594 ipx_addr_to_str(pntohl(&addr->data[0]), &addr->data[4]), COL_MAX_LEN);
601 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X", addr->data[0]);
605 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X",
606 pntohs(&addr->data[0]));
609 case SNA_FID_TYPE_4_ADDR_LEN:
610 memcpy(&sna_fid_type_4_addr, addr->data, SNA_FID_TYPE_4_ADDR_LEN);
611 strncpy(fd->cinfo->col_data[col],
612 sna_fid_type_4_addr_to_str(&sna_fid_type_4_addr), COL_MAX_LEN);
618 memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
619 strncpy(fd->cinfo->col_data[col], atalk_addr_to_str(&ddp_addr),
624 strncpy(fd->cinfo->col_data[col], vines_addr_to_str(&addr->data[0]),
631 fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
635 col_set_port(frame_data *fd, int col, port_type ptype, guint32 port,
642 strncpy(fd->cinfo->col_data[col], get_tcp_port(port), COL_MAX_LEN);
644 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
649 strncpy(fd->cinfo->col_data[col], get_udp_port(port), COL_MAX_LEN);
651 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
657 fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
661 fill_in_columns(frame_data *fd)
665 for (i = 0; i < fd->cinfo->num_cols; i++) {
666 switch (fd->cinfo->col_fmt[i]) {
669 snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%u", fd->num);
673 col_set_cls_time(fd, i);
677 col_set_abs_time(fd, i);
681 col_set_rel_time(fd, i);
685 col_set_delta_time(fd, i);
689 case COL_RES_SRC: /* COL_DEF_SRC is currently just like COL_RES_SRC */
690 col_set_addr(fd, i, &pi.src, TRUE);
694 col_set_addr(fd, i, &pi.src, FALSE);
699 col_set_addr(fd, i, &pi.dl_src, TRUE);
702 case COL_UNRES_DL_SRC:
703 col_set_addr(fd, i, &pi.dl_src, FALSE);
706 case COL_DEF_NET_SRC:
707 case COL_RES_NET_SRC:
708 col_set_addr(fd, i, &pi.net_src, TRUE);
711 case COL_UNRES_NET_SRC:
712 col_set_addr(fd, i, &pi.net_src, FALSE);
716 case COL_RES_DST: /* COL_DEF_DST is currently just like COL_RES_DST */
717 col_set_addr(fd, i, &pi.dst, TRUE);
721 col_set_addr(fd, i, &pi.dst, FALSE);
726 col_set_addr(fd, i, &pi.dl_dst, TRUE);
729 case COL_UNRES_DL_DST:
730 col_set_addr(fd, i, &pi.dl_dst, FALSE);
733 case COL_DEF_NET_DST:
734 case COL_RES_NET_DST:
735 col_set_addr(fd, i, &pi.net_dst, TRUE);
738 case COL_UNRES_NET_DST:
739 col_set_addr(fd, i, &pi.net_dst, FALSE);
742 case COL_DEF_SRC_PORT:
743 case COL_RES_SRC_PORT: /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
744 col_set_port(fd, i, pi.ptype, pi.srcport, TRUE);
747 case COL_UNRES_SRC_PORT:
748 col_set_port(fd, i, pi.ptype, pi.srcport, FALSE);
751 case COL_DEF_DST_PORT:
752 case COL_RES_DST_PORT: /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
753 col_set_port(fd, i, pi.ptype, pi.destport, TRUE);
756 case COL_UNRES_DST_PORT:
757 col_set_port(fd, i, pi.ptype, pi.destport, FALSE);
760 case COL_PROTOCOL: /* currently done by dissectors */
761 case COL_INFO: /* currently done by dissectors */
764 case COL_PACKET_LENGTH:
765 snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%d", fd->pkt_len);
768 case NUM_COL_FMTS: /* keep compiler happy - shouldn't get here */
775 add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf)
780 proto_tree *protocol_tree;
782 fdata->num = cf->count;
784 /* If we don't have the time stamp of the first packet in the
785 capture, it's because this is the first packet. Save the time
786 stamp of this packet as the time stamp of the first packet. */
787 if (!firstsec && !firstusec) {
788 firstsec = fdata->abs_secs;
789 firstusec = fdata->abs_usecs;
792 /* Get the time elapsed between the first packet and this packet. */
793 cf->esec = fdata->abs_secs - firstsec;
794 if (firstusec <= fdata->abs_usecs) {
795 cf->eusec = fdata->abs_usecs - firstusec;
797 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
801 fdata->cinfo = &cf->cinfo;
802 for (i = 0; i < fdata->cinfo->num_cols; i++) {
803 fdata->cinfo->col_data[i][0] = '\0';
806 /* Apply the filters */
807 if (cf->dfcode != NULL || CFILTERS_CONTAINS_FILTER(cf->colors)) {
808 protocol_tree = proto_tree_create_root();
809 dissect_packet(buf, fdata, protocol_tree);
810 if (cf->dfcode != NULL)
811 fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
813 fdata->passed_dfilter = TRUE;
814 /* Apply color filters. */
816 for(crow = 0; cf->colors->num_of_filters &&
817 crow < cf->colors->num_of_filters; crow++) {
819 if(color_filter(cf->colors,crow)->c_colorfilter == NULL) {
822 if(dfilter_apply(color_filter(cf->colors,crow)->c_colorfilter, protocol_tree,
829 proto_tree_free(protocol_tree);
832 dissect_packet(buf, fdata, NULL);
833 fdata->passed_dfilter = TRUE;
836 if (fdata->passed_dfilter) {
837 /* If we don't have the time stamp of the previous displayed packet,
838 it's because this is the first displayed packet. Save the time
839 stamp of this packet as the time stamp of the previous displayed
841 if (!prevsec && !prevusec) {
842 prevsec = fdata->abs_secs;
843 prevusec = fdata->abs_usecs;
846 /* Get the time elapsed between the first packet and this packet. */
847 fdata->rel_secs = cf->esec;
848 fdata->rel_usecs = cf->eusec;
850 /* Get the time elapsed between the previous displayed packet and
852 fdata->del_secs = fdata->abs_secs - prevsec;
853 if (prevusec <= fdata->abs_usecs) {
854 fdata->del_usecs = fdata->abs_usecs - prevusec;
856 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
859 prevsec = fdata->abs_secs;
860 prevusec = fdata->abs_usecs;
862 fill_in_columns(fdata);
864 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
867 if (cf->colors->color_filters && (color != -1)){
868 gtk_clist_set_background(GTK_CLIST(packet_list), row,
869 &(color_filter(cf->colors,color)->bg_color));
870 gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
871 &(color_filter(cf->colors,color)->fg_color));
873 gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
874 gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
877 /* If we haven't yet seen the first frame, this is it. */
878 if (cf->first_displayed == NULL)
879 cf->first_displayed = fdata;
881 /* This is the last frame we've seen so far. */
882 cf->last_displayed = fdata;
884 /* If this was the current frame, remember the row it's in, so
885 we can arrange that it's on the screen when we're done. */
886 if (cf->current_frame == fdata)
887 cf->current_row = row;
889 fdata->row = -1; /* not in the display */
894 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
897 capture_file *cf = (capture_file *) user;
899 proto_tree *protocol_tree;
900 frame_data *plist_end;
904 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
905 when we update it, we have to run the GTK+ main loop to get it
906 to repaint what's pending, and doing so may involve an "ioctl()"
907 to see if there's any pending input from an X server, and doing
908 that for every packet can be costly, especially on a big file.
910 Do so only if we were told to do so; when reading a capture file
911 being updated by a live capture, we don't do so (as we're not
912 "done" until the capture stops, so we don't know how close to
915 if (cf->update_progbar && offset >= cf->progbar_nextstep) {
916 file_pos = lseek(cf->filed, 0, SEEK_CUR);
917 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
918 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), prog_val);
919 cf->progbar_nextstep += cf->progbar_quantum;
920 while (gtk_events_pending())
921 gtk_main_iteration();
924 /* Allocate the next list entry, and add it to the list. */
925 fdata = (frame_data *) g_malloc(sizeof(frame_data));
929 fdata->pkt_len = phdr->len;
930 fdata->cap_len = phdr->caplen;
931 fdata->file_off = offset;
932 fdata->lnk_t = phdr->pkt_encap;
933 fdata->abs_secs = phdr->ts.tv_sec;
934 fdata->abs_usecs = phdr->ts.tv_usec;
935 fdata->encoding = CHAR_ASCII;
936 fdata->pseudo_header = phdr->pseudo_header;
941 protocol_tree = proto_tree_create_root();
942 dissect_packet(buf, fdata, protocol_tree);
943 passed = dfilter_apply(cf->rfcode, protocol_tree, cf->pd);
944 proto_tree_free(protocol_tree);
947 plist_end = cf->plist_end;
948 fdata->prev = plist_end;
949 if (plist_end != NULL)
950 plist_end->next = fdata;
953 cf->plist_end = fdata;
956 add_packet_to_packet_list(fdata, cf, buf);
962 filter_packets(capture_file *cf, gchar *dftext)
966 if (dftext == NULL) {
967 /* The new filter is an empty filter (i.e., display all packets). */
971 * We have a filter; try to compile it.
973 if (dfilter_compile(dftext, &dfcode) != 0) {
974 /* The attempt failed; report an error. */
975 simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
980 if (dfcode == NULL) {
981 /* Yes - free the filter text, and set it to null. */
987 /* We have a valid filter. Replace the current filter. */
988 if (cf->dfilter != NULL)
990 cf->dfilter = dftext;
991 if (cf->dfcode != NULL)
992 dfilter_destroy(cf->dfcode);
995 /* Now go through the list of packets we've read from the capture file,
996 applying the current display filter, and, if the packet passes the
997 display filter, add it to the summary display, appropriately
998 colored. (That's how we colorize the display - it's like filtering
999 the display, only we don't install a new filter.) */
1000 colorize_packets(cf);
1005 colorize_packets(capture_file *cf)
1008 guint32 progbar_quantum;
1009 guint32 progbar_nextstep;
1011 /* We need to re-initialize all the state information that protocols
1012 keep, because we're making a fresh pass through all the packets. */
1014 /* Initialize the table of conversations. */
1015 conversation_init();
1017 /* Initialize protocol-specific variables */
1018 init_all_protocols();
1020 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
1022 /* Freeze the packet list while we redo it, so we don't get any
1023 screen updates while it happens. */
1024 gtk_clist_freeze(GTK_CLIST(packet_list));
1027 gtk_clist_clear(GTK_CLIST(packet_list));
1029 /* We don't yet know which will be the first and last frames displayed. */
1030 cf->first_displayed = NULL;
1031 cf->last_displayed = NULL;
1033 /* If a packet was selected, we don't know yet what row, if any, it'll
1035 cf->current_row = -1;
1037 /* Iterate through the list of packets, calling a routine
1038 to run the filter on the packet, see if it matches, and
1039 put it in the display list if so. */
1044 cf->unfiltered_count = cf->count;
1047 proto_tree_is_visible = FALSE;
1049 /* Update the progress bar when it gets to this value. */
1050 progbar_nextstep = 0;
1051 /* When we reach the value that triggers a progress bar update,
1052 bump that value by this amount. */
1053 progbar_quantum = cf->unfiltered_count/N_PROGBAR_UPDATES;
1054 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
1056 for (fd = cf->plist; fd != NULL; fd = fd->next) {
1057 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1058 when we update it, we have to run the GTK+ main loop to get it
1059 to repaint what's pending, and doing so may involve an "ioctl()"
1060 to see if there's any pending input from an X server, and doing
1061 that for every packet can be costly, especially on a big file. */
1062 if (cf->count >= progbar_nextstep) {
1063 /* let's not divide by zero. I should never be started
1064 * with unfiltered_count == 0, so let's assert that
1066 g_assert(cf->unfiltered_count > 0);
1068 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1069 (gfloat) cf->count / cf->unfiltered_count);
1071 progbar_nextstep += progbar_quantum;
1072 while (gtk_events_pending())
1073 gtk_main_iteration();
1078 wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1080 add_packet_to_packet_list(fd, cf, cf->pd);
1083 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1085 if (cf->current_row != -1) {
1086 /* The current frame passed the filter; make sure it's visible. */
1087 if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), cf->current_row))
1088 gtk_clist_moveto(GTK_CLIST(packet_list), cf->current_row, -1, 0.0, 0.0);
1089 if (cf->current_frame_is_selected) {
1090 /* It was selected, so re-select it. */
1091 gtk_clist_select_row(GTK_CLIST(packet_list), cf->current_row, -1);
1093 finfo_selected = NULL;
1095 /* The current frame didn't pass the filter; make the first frame
1096 the current frame, and leave it unselected. */
1097 unselect_packet(cf);
1098 cf->current_frame = cf->first_displayed;
1101 /* Unfreeze the packet list. */
1102 gtk_clist_thaw(GTK_CLIST(packet_list));
1106 print_packets(capture_file *cf, print_args_t *print_args)
1110 guint32 progbar_quantum;
1111 guint32 progbar_nextstep;
1113 proto_tree *protocol_tree;
1114 gint *col_widths = NULL;
1116 gboolean print_separator;
1118 cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
1119 if (cf->print_fh == NULL)
1120 return FALSE; /* attempt to open destination failed */
1122 /* XXX - printing multiple frames in PostScript looks as if it's
1123 tricky - you have to deal with page boundaries, I think -
1124 and I'll have to spend some time learning enough about
1125 PostScript to figure it out, so, for now, we only print
1126 multiple frames as text. */
1128 print_preamble(cf->print_fh);
1131 if (print_args->print_summary) {
1132 /* We're printing packet summaries.
1134 Find the widths for each of the columns - maximum of the
1135 width of the title and the width of the data - and print
1136 the column titles. */
1137 col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1138 for (i = 0; i < cf->cinfo.num_cols; i++) {
1139 /* Don't pad the last column. */
1140 if (i == cf->cinfo.num_cols - 1)
1143 col_widths[i] = strlen(cf->cinfo.col_title[i]);
1144 data_width = get_column_char_width(get_column_format(i));
1145 if (data_width > col_widths[i])
1146 col_widths[i] = data_width;
1149 /* Right-justify the packet number column. */
1150 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1151 fprintf(cf->print_fh, "%*s", col_widths[i], cf->cinfo.col_title[i]);
1153 fprintf(cf->print_fh, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
1154 if (i == cf->cinfo.num_cols - 1)
1155 fputc('\n', cf->print_fh);
1157 fputc(' ', cf->print_fh);
1161 print_separator = FALSE;
1162 proto_tree_is_visible = TRUE;
1164 /* Update the progress bar when it gets to this value. */
1165 progbar_nextstep = 0;
1166 /* When we reach the value that triggers a progress bar update,
1167 bump that value by this amount. */
1168 progbar_quantum = cf->unfiltered_count/N_PROGBAR_UPDATES;
1169 /* Count of packets we've looked at. */
1172 /* Iterate through the list of packets, printing the packets that
1173 were selected by the current display filter. */
1174 for (fd = cf->plist; fd != NULL; fd = fd->next) {
1175 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1176 when we update it, we have to run the GTK+ main loop to get it
1177 to repaint what's pending, and doing so may involve an "ioctl()"
1178 to see if there's any pending input from an X server, and doing
1179 that for every packet can be costly, especially on a big file. */
1180 if (count >= progbar_nextstep) {
1181 /* let's not divide by zero. I should never be started
1182 * with unfiltered_count == 0, so let's assert that
1184 g_assert(cf->unfiltered_count > 0);
1186 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1187 (gfloat) count / cf->unfiltered_count);
1188 progbar_nextstep += progbar_quantum;
1189 while (gtk_events_pending())
1190 gtk_main_iteration();
1194 if (fd->passed_dfilter) {
1195 wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1196 if (print_args->print_summary) {
1197 /* Fill in the column information, but don't bother creating
1198 the logical protocol tree. */
1199 fd->cinfo = &cf->cinfo;
1200 for (i = 0; i < fd->cinfo->num_cols; i++) {
1201 fd->cinfo->col_data[i][0] = '\0';
1203 dissect_packet(cf->pd, fd, NULL);
1204 fill_in_columns(fd);
1205 for (i = 0; i < cf->cinfo.num_cols; i++) {
1206 /* Right-justify the packet number column. */
1207 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1208 fprintf(cf->print_fh, "%*s", col_widths[i], cf->cinfo.col_data[i]);
1210 fprintf(cf->print_fh, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
1211 if (i == cf->cinfo.num_cols - 1)
1212 fputc('\n', cf->print_fh);
1214 fputc(' ', cf->print_fh);
1217 if (print_separator)
1218 fputc('\n', cf->print_fh);
1220 /* Create the logical protocol tree. */
1221 protocol_tree = proto_tree_create_root();
1222 dissect_packet(cf->pd, fd, protocol_tree);
1224 /* Print the information in that tree. */
1225 proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
1226 cf->pd, fd, cf->print_fh);
1228 proto_tree_free(protocol_tree);
1230 if (print_args->print_hex) {
1231 /* Print the full packet data as hex. */
1232 print_hex_data(cf->print_fh, cf->pd, fd->cap_len, fd->encoding);
1235 /* Print a blank line if we print anything after this. */
1236 print_separator = TRUE;
1241 if (col_widths != NULL)
1245 print_finale(cf->print_fh);
1248 close_print_dest(print_args->to_file, cf->print_fh);
1250 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1252 cf->print_fh = NULL;
1256 /* Scan through the packet list and change all columns that use the
1257 "command-line-specified" time stamp format to use the current
1258 value of that format. */
1260 change_time_formats(capture_file *cf)
1266 /* Freeze the packet list while we redo it, so we don't get any
1267 screen updates while it happens. */
1270 /* Iterate through the list of packets, checking whether the packet
1271 is in a row of the summary list and, if so, whether there are
1272 any columns that show the time in the "command-line-specified"
1273 format and, if so, update that row. */
1274 for (fd = cf->plist; fd != NULL; fd = fd->next) {
1275 if (fd->row != -1) {
1276 /* This packet is in the summary list, on row "fd->row". */
1278 /* XXX - there really should be a way of checking "cf->cinfo" for this;
1279 the answer isn't going to change from packet to packet, so we should
1280 simply skip all the "change_time_formats()" work if we're not
1281 changing anything. */
1282 fd->cinfo = &cf->cinfo;
1283 if (check_col(fd, COL_CLS_TIME)) {
1284 /* There are columns that show the time in the "command-line-specified"
1285 format; update them. */
1286 for (i = 0; i < cf->cinfo.num_cols; i++) {
1287 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1288 /* This is one of the columns that shows the time in
1289 "command-line-specified" format; update it. */
1290 cf->cinfo.col_data[i][0] = '\0';
1291 col_set_cls_time(fd, i);
1292 gtk_clist_set_text(GTK_CLIST(packet_list), fd->row, i,
1293 cf->cinfo.col_data[i]);
1300 /* Set the column widths of those columns that show the time in
1301 "command-line-specified" format. */
1302 pl_style = gtk_widget_get_style(packet_list);
1303 for (i = 0; i < cf->cinfo.num_cols; i++) {
1304 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1305 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1306 get_column_width(COL_CLS_TIME, pl_style->font));
1310 /* Unfreeze the packet list. */
1315 clear_tree_and_hex_views(void)
1318 GtkWidget *tmp_item;
1320 /* Clear the hex dump. */
1321 gtk_text_freeze(GTK_TEXT(byte_view));
1322 gtk_text_set_point(GTK_TEXT(byte_view), 0);
1323 gtk_text_forward_delete(GTK_TEXT(byte_view),
1324 gtk_text_get_length(GTK_TEXT(byte_view)));
1325 gtk_text_thaw(GTK_TEXT(byte_view));
1327 /* Deselect any selected tree item. gtktree.c should
1328 * do this when we clear_items, but it doesn't. I copied
1329 * this while() loop from gtktree.c, gtk_real_tree_select_child()
1331 if (GTK_TREE(tree_view)->root_tree) {
1332 selection = GTK_TREE(tree_view)->root_tree->selection;
1334 tmp_item = selection->data;
1335 gtk_tree_item_deselect(GTK_TREE_ITEM(tmp_item));
1336 gtk_widget_unref(tmp_item);
1337 selection = selection->next;
1339 g_list_free(GTK_TREE(tree_view)->root_tree->selection);
1340 GTK_TREE(tree_view)->root_tree->selection = NULL;
1343 /* Clear the protocol tree view. The length arg of -1
1344 * means to clear all items up to the end. */
1345 gtk_tree_clear_items(GTK_TREE(tree_view), 0, -1);
1349 find_packet(capture_file *cf, dfilter *sfcode)
1351 frame_data *start_fd;
1353 frame_data *new_fd = NULL;
1354 guint32 progbar_quantum;
1355 guint32 progbar_nextstep;
1357 proto_tree *protocol_tree;
1359 start_fd = cf->current_frame;
1360 if (start_fd != NULL) {
1361 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
1363 /* Iterate through the list of packets, starting at the packet we've
1364 picked, calling a routine to run the filter on the packet, see if
1365 it matches, and stop if so. */
1369 proto_tree_is_visible = FALSE;
1371 /* Update the progress bar when it gets to this value. */
1372 progbar_nextstep = 0;
1373 /* When we reach the value that triggers a progress bar update,
1374 bump that value by this amount.
1376 We base the progress bar on the extent to which we've gone through
1377 the displayed packets, as those are the only ones for which we
1378 have to do a significant amount of work. */
1379 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1380 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
1384 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1385 when we update it, we have to run the GTK+ main loop to get it
1386 to repaint what's pending, and doing so may involve an "ioctl()"
1387 to see if there's any pending input from an X server, and doing
1388 that for every packet can be costly, especially on a big file. */
1389 if (count >= progbar_nextstep) {
1390 /* let's not divide by zero. I should never be started
1391 * with count == 0, so let's assert that
1393 g_assert(cf->count > 0);
1395 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1396 (gfloat) count / cf->count);
1398 progbar_nextstep += progbar_quantum;
1399 while (gtk_events_pending())
1400 gtk_main_iteration();
1403 /* Go past the current frame. */
1404 if (cf->sbackward) {
1405 /* Go on to the previous frame. */
1408 fd = cf->plist_end; /* wrap around */
1410 /* Go on to the next frame. */
1413 fd = cf->plist; /* wrap around */
1416 if (fd == start_fd) {
1417 /* We're back to the frame we were on originally. The search
1422 /* Is this packet in the display? */
1423 if (fd->passed_dfilter) {
1426 /* Yes. Does it match the search filter? */
1427 protocol_tree = proto_tree_create_root();
1428 wtap_seek_read(cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1429 dissect_packet(cf->pd, fd, protocol_tree);
1430 if (dfilter_apply(sfcode, protocol_tree, cf->pd)) {
1432 break; /* found it! */
1437 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1440 if (new_fd != NULL) {
1441 /* We found a frame. Make it visible, and select it. */
1442 if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), new_fd->row))
1443 gtk_clist_moveto(GTK_CLIST(packet_list), new_fd->row, -1, 0.0, 0.0);
1444 gtk_clist_select_row(GTK_CLIST(packet_list), new_fd->row, -1);
1445 return TRUE; /* success */
1447 return FALSE; /* failure */
1451 goto_frame(capture_file *cf, guint fnumber)
1455 for (fd = cf->plist; fd != NULL && fd->num < fnumber; fd = fd->next)
1459 return NO_SUCH_FRAME; /* we didn't find that frame */
1460 if (!fd->passed_dfilter)
1461 return FRAME_NOT_DISPLAYED; /* the frame with that number isn't displayed */
1463 /* We found that frame, and it's currently being displayed.
1464 Make it visible, and select it. */
1465 if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), fd->row))
1466 gtk_clist_moveto(GTK_CLIST(packet_list), fd->row, -1, 0.0, 0.0);
1467 gtk_clist_select_row(GTK_CLIST(packet_list), fd->row, -1);
1471 /* Select the packet on a given row. */
1473 select_packet(capture_file *cf, int row)
1478 /* Clear out whatever's currently in the hex dump. */
1479 gtk_text_freeze(GTK_TEXT(byte_view));
1480 gtk_text_set_point(GTK_TEXT(byte_view), 0);
1481 gtk_text_forward_delete(GTK_TEXT(byte_view),
1482 gtk_text_get_length(GTK_TEXT(byte_view)));
1484 /* Search through the list of frames to see which one is in
1486 for (fd = cf->plist, i = 0; fd != NULL; fd = fd->next, i++) {
1491 g_assert(fd != NULL);
1493 /* Record that this frame is the current frame, and that it's selected. */
1494 cf->current_frame = fd;
1495 cf->current_frame_is_selected = TRUE;
1497 /* Get the data in that frame. */
1498 wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1500 /* Create the logical protocol tree. */
1501 if (cf->protocol_tree)
1502 proto_tree_free(cf->protocol_tree);
1503 cf->protocol_tree = proto_tree_create_root();
1504 proto_tree_is_visible = TRUE;
1505 dissect_packet(cf->pd, cf->current_frame, cf->protocol_tree);
1507 /* Display the GUI protocol tree and hex dump. */
1508 clear_tree_and_hex_views();
1509 proto_tree_draw(cf->protocol_tree, tree_view);
1510 packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->current_frame->cap_len,
1511 -1, -1, cf->current_frame->encoding);
1512 gtk_text_thaw(GTK_TEXT(byte_view));
1514 /* A packet is selected, so "File/Print Packet" has something to print. */
1515 set_menu_sensitivity("/File/Print Packet", TRUE);
1516 set_menu_sensitivity("/Display/Collapse All", TRUE);
1517 set_menu_sensitivity("/Display/Expand All", TRUE);
1519 if (pi.ipproto == 6) {
1520 set_menu_sensitivity("/Tools/Follow TCP Stream", TRUE);
1522 set_menu_sensitivity("/Tools/Follow TCP Stream", FALSE);
1526 /* Unselect the selected packet, if any. */
1528 unselect_packet(capture_file *cf)
1530 cf->current_frame_is_selected = FALSE;
1532 /* Destroy the protocol tree for that packet. */
1533 if (cf->protocol_tree != NULL) {
1534 proto_tree_free(cf->protocol_tree);
1535 cf->protocol_tree = NULL;
1538 finfo_selected = NULL;
1540 /* Clear out the display of that packet. */
1541 clear_tree_and_hex_views();
1543 /* No packet is selected, so "File/Print Packet" has nothing to print. */
1544 set_menu_sensitivity("/File/Print Packet", FALSE);
1545 set_menu_sensitivity("/Display/Collapse All", FALSE);
1546 set_menu_sensitivity("/Display/Expand All", FALSE);
1547 set_menu_sensitivity("/Tools/Follow TCP Stream", FALSE);
1551 freeze_clist(capture_file *cf)
1555 /* Make the column sizes static, so they don't adjust while
1556 we're reading the capture file (freezing the clist doesn't
1557 seem to suffice). */
1558 for (i = 0; i < cf->cinfo.num_cols; i++)
1559 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1560 gtk_clist_freeze(GTK_CLIST(packet_list));
1564 thaw_clist(capture_file *cf)
1568 for (i = 0; i < cf->cinfo.num_cols; i++) {
1569 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1570 /* Set this column's width to the appropriate value. */
1571 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1572 cf->cinfo.col_width[i]);
1574 /* Make this column's size dynamic, so that it adjusts to the
1575 appropriate size. */
1576 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1579 gtk_clist_thaw(GTK_CLIST(packet_list));
1581 /* Hopefully, the columns have now gotten their appropriate sizes;
1582 make them resizeable - a column that auto-resizes cannot be
1583 resized by the user, and *vice versa*. */
1584 for (i = 0; i < cf->cinfo.num_cols; i++)
1585 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1589 save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
1592 gchar *from_filename;
1593 gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
1597 int from_fd, to_fd, nread, nwritten;
1600 struct wtap_pkthdr hdr;
1603 if ((name_ptr = (gchar *) strrchr(fname, '/')) == NULL)
1607 msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
1608 save_msg = g_malloc(msg_len);
1609 snprintf(save_msg, msg_len, save_fmt, name_ptr);
1610 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
1613 if (!save_filtered && save_format == cf->cd_t) {
1614 /* We're not filtering packets, and we're saving it in the format
1615 it's already in, so we can just move or copy the raw data. */
1617 /* In this branch, we set "err" only if we get an error, so we
1618 must first clear it. */
1620 if (cf->is_tempfile) {
1621 /* The file being saved is a temporary file from a live
1622 capture, so it doesn't need to stay around under that name;
1623 first, try renaming the capture buffer file to the new name. */
1624 if (rename(cf->filename, fname) == 0) {
1625 /* That succeeded - there's no need to copy the source file. */
1626 from_filename = NULL;
1629 if (errno == EXDEV) {
1630 /* They're on different file systems, so we have to copy the
1633 from_filename = cf->filename;
1635 /* The rename failed, but not because they're on different
1636 file systems - put up an error message. (Or should we
1637 just punt and try to copy? The only reason why I'd
1638 expect the rename to fail and the copy to succeed would
1639 be if we didn't have permission to remove the file from
1640 the temporary directory, and that might be fixable - but
1641 is it worth requiring the user to go off and fix it?) */
1643 simple_dialog(ESD_TYPE_WARN, NULL,
1644 file_rename_error_message(err), fname);
1649 /* It's a permanent file, so we should copy it, and not remove the
1652 from_filename = cf->filename;
1655 /* Copy the file, if we haven't moved it. */
1657 /* Copy the raw bytes of the file. */
1658 from_fd = open(from_filename, O_RDONLY);
1661 simple_dialog(ESD_TYPE_WARN, NULL,
1662 file_open_error_message(err, TRUE), from_filename);
1666 to_fd = creat(fname, 0644);
1669 simple_dialog(ESD_TYPE_WARN, NULL,
1670 file_open_error_message(err, TRUE), fname);
1675 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
1676 nwritten = write(to_fd, pd, nread);
1677 if (nwritten < nread) {
1681 err = WTAP_ERR_SHORT_WRITE;
1682 simple_dialog(ESD_TYPE_WARN, NULL,
1683 file_write_error_message(err), fname);
1691 simple_dialog(ESD_TYPE_WARN, NULL,
1692 file_read_error_message(err), from_filename);
1698 if (close(to_fd) < 0) {
1700 simple_dialog(ESD_TYPE_WARN, NULL,
1701 file_close_error_message(err), fname);
1706 /* Either we're filtering packets, or we're saving in a different
1707 format; we can't do that by copying or moving the capture file,
1708 we have to do it by writing the packets out in Wiretap. */
1709 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
1711 simple_dialog(ESD_TYPE_WARN, NULL,
1712 file_open_error_message(err, TRUE), fname);
1716 /* XXX - have a way to save only the packets currently selected by
1719 If we do that, should we make that file the current file? If so,
1720 it means we can no longer get at the other packets. What does
1722 for (fd = cf->plist; fd != NULL; fd = fd->next) {
1723 /* XXX - do a progress bar */
1724 if (!save_filtered || fd->passed_dfilter) {
1725 /* Either we're saving all frames, or we're saving filtered frames
1726 and this one passed the display filter - save it. */
1727 hdr.ts.tv_sec = fd->abs_secs;
1728 hdr.ts.tv_usec = fd->abs_usecs;
1729 hdr.caplen = fd->cap_len;
1730 hdr.len = fd->pkt_len;
1731 hdr.pkt_encap = fd->lnk_t;
1732 wtap_seek_read(cf->cd_t, cf->fh, fd->file_off, pd, fd->cap_len);
1734 if (!wtap_dump(pdh, &hdr, pd, &err)) {
1735 simple_dialog(ESD_TYPE_WARN, NULL,
1736 file_write_error_message(err), fname);
1737 wtap_dump_close(pdh, &err);
1743 if (!wtap_dump_close(pdh, &err)) {
1744 simple_dialog(ESD_TYPE_WARN, NULL,
1745 file_close_error_message(err), fname);
1752 /* Pop the "Saving:" message off the status bar. */
1753 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
1755 if (!save_filtered) {
1756 /* We saved the entire capture, not just some packets from it.
1757 Open and read the file we saved it to.
1759 XXX - this is somewhat of a waste; we already have the
1760 packets, all this gets us is updated file type information
1761 (which we could just stuff into "cf"), and having the new
1762 file be the one we have opened and from which we're reading
1763 the data, and it means we have to spend time opening and
1764 reading the file, which could be a significant amount of
1765 time if the file is large. */
1766 cf->user_saved = TRUE;
1768 if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
1769 /* XXX - report errors if this fails? */
1770 err = read_cap_file(cf);
1771 set_menu_sensitivity("/File/Save", FALSE);
1779 file_open_error_message(int err, int for_writing)
1782 static char errmsg_errno[1024+1];
1786 case WTAP_ERR_NOT_REGULAR_FILE:
1787 errmsg = "The file \"%s\" is invalid.";
1790 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1791 case WTAP_ERR_UNSUPPORTED:
1792 /* Seen only when opening a capture file for reading. */
1793 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1796 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1797 /* Seen only when opening a capture file for writing. */
1798 errmsg = "Ethereal does not support writing capture files in that format.";
1801 case WTAP_ERR_UNSUPPORTED_ENCAP:
1802 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1803 /* Seen only when opening a capture file for writing. */
1804 errmsg = "Ethereal cannot save this capture in that format.";
1807 case WTAP_ERR_BAD_RECORD:
1808 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1811 case WTAP_ERR_CANT_OPEN:
1813 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1815 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1818 case WTAP_ERR_SHORT_READ:
1819 errmsg = "The file \"%s\" appears to have been cut short"
1820 " in the middle of a packet.";
1823 case WTAP_ERR_SHORT_WRITE:
1824 errmsg = "A full header couldn't be written to the file \"%s\".";
1829 errmsg = "The path to the file \"%s\" does not exist.";
1831 errmsg = "The file \"%s\" does not exist.";
1836 errmsg = "You do not have permission to create or write to the file \"%s\".";
1838 errmsg = "You do not have permission to read the file \"%s\".";
1842 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
1843 wtap_strerror(err));
1844 errmsg = errmsg_errno;
1851 file_rename_error_message(int err)
1854 static char errmsg_errno[1024+1];
1859 errmsg = "The path to the file \"%s\" does not exist.";
1863 errmsg = "You do not have permission to move the capture file to \"%s\".";
1867 sprintf(errmsg_errno, "The file \"%%s\" could not be moved: %s.",
1868 wtap_strerror(err));
1869 errmsg = errmsg_errno;
1876 file_read_error_message(int err)
1878 static char errmsg_errno[1024+1];
1880 sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.",
1881 wtap_strerror(err));
1882 return errmsg_errno;
1886 file_write_error_message(int err)
1889 static char errmsg_errno[1024+1];
1894 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1899 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1904 sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.",
1905 wtap_strerror(err));
1906 errmsg = errmsg_errno;
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. */
1917 file_close_error_message(int err)
1920 static char errmsg_errno[1024+1];
1924 case WTAP_ERR_CANT_CLOSE:
1925 errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
1928 case WTAP_ERR_SHORT_WRITE:
1929 errmsg = "Not all the data could be written to the file \"%s\".";
1933 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1938 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1943 sprintf(errmsg_errno, "An error occurred while closing the file \"%%s\": %s.",
1944 wtap_strerror(err));
1945 errmsg = errmsg_errno;