4 * $Id: file.c,v 1.204 2000/08/09 06:18:10 gram 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.
50 #ifdef NEED_SNPRINTF_H
56 # include "snprintf.h"
59 #ifdef NEED_STRERROR_H
63 #ifdef HAVE_SYS_TYPES_H
64 # include <sys/types.h>
67 #ifdef HAVE_NETINET_IN_H
68 # include <netinet/in.h>
78 #include "simple_dialog.h"
81 #include "gtk/proto_draw.h"
83 #include "conversation.h"
88 extern GtkWidget *packet_list, *info_bar, *byte_view, *tree_view;
89 extern guint file_ctx;
91 gboolean auto_scroll_live = FALSE;
93 static guint32 firstsec, firstusec;
94 static guint32 prevsec, prevusec;
96 static void read_packet(capture_file *cf, int offset);
98 static void rescan_packets(capture_file *cf, const char *action,
101 static void set_selected_row(int row);
103 static void freeze_clist(capture_file *cf);
104 static void thaw_clist(capture_file *cf);
106 static char *file_rename_error_message(int err);
107 static char *file_close_error_message(int err);
108 static gboolean copy_binary_file(char *from_filename, char *to_filename);
110 /* Update the progress bar this many times when reading a file. */
111 #define N_PROGBAR_UPDATES 100
113 /* Number of "frame_data" structures per memory chunk.
114 XXX - is this the right number? */
115 #define FRAME_DATA_CHUNK_SIZE 1024
118 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
126 wth = wtap_open_offline(fname, &err, TRUE);
130 /* Find the size of the file. */
133 if (fstat(fd, &cf_stat) < 0) {
139 /* The open succeeded. Close whatever capture file we had open,
140 and fill in the information for this file. */
141 close_cap_file(cf, info_bar);
143 /* Initialize the table of conversations. */
146 /* Initialize protocol-specific variables */
147 init_all_protocols();
149 /* We're about to start reading the file. */
150 cf->state = FILE_READ_IN_PROGRESS;
154 cf->f_len = cf_stat.st_size;
156 /* Set the file name because we need it to set the follow stream filter.
157 XXX - is that still true? We need it for other reasons, though,
159 cf->filename = g_strdup(fname);
161 /* Indicate whether it's a permanent or temporary file. */
162 cf->is_tempfile = is_tempfile;
164 /* If it's a temporary capture buffer file, mark it as not saved. */
165 cf->user_saved = !is_tempfile;
167 cf->cd_t = wtap_file_type(cf->wth);
172 cf->snap = wtap_snapshot_length(cf->wth);
173 cf->progbar_quantum = 0;
174 cf->progbar_nextstep = 0;
175 firstsec = 0, firstusec = 0;
176 prevsec = 0, prevusec = 0;
178 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
180 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
182 g_assert(cf->plist_chunk);
187 simple_dialog(ESD_TYPE_CRIT, NULL,
188 file_open_error_message(err, FALSE), fname);
192 /* Reset everything to a pristine state */
194 close_cap_file(capture_file *cf, void *w)
196 /* Die if we're in the middle of reading a file. */
197 g_assert(cf->state != FILE_READ_IN_PROGRESS);
199 /* Destroy all popup packet windows, as they refer to packets in the
200 capture file we're closing. */
201 destroy_packet_wins();
207 /* We have no file open... */
208 if (cf->filename != NULL) {
209 /* If it's a temporary file, remove it. */
211 unlink(cf->filename);
212 g_free(cf->filename);
215 /* ...which means we have nothing to save. */
216 cf->user_saved = FALSE;
218 if (cf->plist_chunk != NULL) {
219 g_mem_chunk_destroy(cf->plist_chunk);
220 cf->plist_chunk = NULL;
222 if (cf->rfcode != NULL) {
223 dfilter_destroy(cf->rfcode);
227 cf->plist_end = NULL;
228 unselect_packet(cf); /* nothing to select */
229 cf->first_displayed = NULL;
230 cf->last_displayed = NULL;
232 /* Clear the packet list. */
233 gtk_clist_freeze(GTK_CLIST(packet_list));
234 gtk_clist_clear(GTK_CLIST(packet_list));
235 gtk_clist_thaw(GTK_CLIST(packet_list));
237 /* Clear any file-related status bar messages.
238 XXX - should be "clear *ALL* file-related status bar messages;
239 will there ever be more than one on the stack? */
240 gtk_statusbar_pop(GTK_STATUSBAR(w), file_ctx);
242 /* Restore the standard title bar message. */
243 set_main_window_name("The Ethereal Network Analyzer");
245 /* Disable all menu items that make sense only if you have a capture. */
246 set_menus_for_capture_file(FALSE);
247 set_menus_for_unsaved_capture_file(FALSE);
248 set_menus_for_captured_packets(FALSE);
249 set_menus_for_selected_packet(FALSE);
250 set_menus_for_capture_in_progress(FALSE);
252 /* We have no file open. */
253 cf->state = FILE_CLOSED;
256 /* Set the file name in the status line, in the name for the main window,
257 and in the name for the main window's icon. */
259 set_display_filename(capture_file *cf)
263 gchar *done_fmt = " File: %s Drops: %u";
265 gchar *win_name_fmt = "%s - Ethereal";
268 if (!cf->is_tempfile) {
269 /* Get the last component of the file name, and put that in the
271 name_ptr = get_basename(cf->filename);
273 /* The file we read is a temporary file from a live capture;
274 we don't mention its name in the status bar. */
275 name_ptr = "<capture>";
278 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
279 done_msg = g_malloc(msg_len);
280 snprintf(done_msg, msg_len, done_fmt, name_ptr, cf->drops);
281 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
284 msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
285 win_name = g_malloc(msg_len);
286 snprintf(win_name, msg_len, win_name_fmt, name_ptr);
287 set_main_window_name(win_name);
292 read_cap_file(capture_file *cf, int *err)
294 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
297 char errmsg_errno[1024+1];
298 gchar err_str[2048+1];
305 name_ptr = get_basename(cf->filename);
307 msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
308 load_msg = g_malloc(msg_len);
309 snprintf(load_msg, msg_len, load_fmt, name_ptr);
310 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
312 /* Update the progress bar when it gets to this value. */
313 cf->progbar_nextstep = 0;
314 /* When we reach the value that triggers a progress bar update,
315 bump that value by this amount. */
316 cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
325 progbar = create_progress_dlg(load_msg, "Stop", &stop_flag);
328 while ((data_offset = wtap_read(cf->wth, err)) > 0) {
329 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
330 when we update it, we have to run the GTK+ main loop to get it
331 to repaint what's pending, and doing so may involve an "ioctl()"
332 to see if there's any pending input from an X server, and doing
333 that for every packet can be costly, especially on a big file. */
334 if (data_offset >= cf->progbar_nextstep) {
335 file_pos = lseek(cf->filed, 0, SEEK_CUR);
336 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
337 update_progress_dlg(progbar, prog_val);
338 cf->progbar_nextstep += cf->progbar_quantum;
342 /* Well, the user decided to abort the read. Destroy the progress
343 bar, close the capture file, and return READ_ABORTED so our caller
344 can do whatever is appropriate when that happens. */
345 destroy_progress_dlg(progbar);
346 cf->state = FILE_READ_ABORTED; /* so that we're allowed to close it */
347 gtk_clist_thaw(GTK_CLIST(packet_list)); /* undo our freeze */
348 close_cap_file(cf, info_bar);
349 return (READ_ABORTED);
351 read_packet(cf, data_offset);
354 /* We're done reading the file; destroy the progress bar. */
355 destroy_progress_dlg(progbar);
357 /* We're done reading sequentially through the file. */
358 cf->state = FILE_READ_DONE;
360 /* Close the sequential I/O side, to free up memory it requires. */
361 wtap_sequential_close(cf->wth);
363 /* Set the file encapsulation type now; we don't know what it is until
364 we've looked at all the packets, as we don't know until then whether
365 there's more than one type (and thus whether it's
366 WTAP_ENCAP_PER_PACKET). */
367 cf->lnk_t = wtap_file_encap(cf->wth);
369 cf->current_frame = cf->first_displayed;
372 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
373 set_display_filename(cf);
375 /* Enable menu items that make sense if you have a capture file you've
377 set_menus_for_capture_file(TRUE);
378 set_menus_for_unsaved_capture_file(!cf->user_saved);
380 /* Enable menu items that make sense if you have some captured packets. */
381 set_menus_for_captured_packets(TRUE);
383 /* If we have any displayed packets to select, select the first of those
384 packets by making the first row the selected row. */
385 if (cf->first_displayed != NULL)
386 gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
388 if (data_offset < 0) {
389 /* Put up a message box noting that the read failed somewhere along
390 the line. Don't throw out the stuff we managed to read, though,
394 case WTAP_ERR_UNSUPPORTED_ENCAP:
395 errmsg = "The capture file is for a network type that Ethereal doesn't support.";
398 case WTAP_ERR_CANT_READ:
399 errmsg = "An attempt to read from the file failed for"
400 " some unknown reason.";
403 case WTAP_ERR_SHORT_READ:
404 errmsg = "The capture file appears to have been cut short"
405 " in the middle of a packet.";
408 case WTAP_ERR_BAD_RECORD:
409 errmsg = "The capture file appears to be damaged or corrupt.";
413 sprintf(errmsg_errno, "An error occurred while reading the"
414 " capture file: %s.", wtap_strerror(*err));
415 errmsg = errmsg_errno;
418 snprintf(err_str, sizeof err_str, errmsg);
419 simple_dialog(ESD_TYPE_CRIT, NULL, err_str);
422 return (READ_SUCCESS);
427 start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
432 err = open_cap_file(fname, is_tempfile, cf);
434 /* Disable menu items that make no sense if you're currently running
436 set_menus_for_capture_in_progress(TRUE);
438 /* Enable menu items that make sense if you have some captured
439 packets (yes, I know, we don't have any *yet*). */
440 set_menus_for_captured_packets(TRUE);
442 for (i = 0; i < cf->cinfo.num_cols; i++) {
443 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
444 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
446 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
447 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
448 cf->cinfo.col_width[i]);
449 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
453 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
454 " <live capture in progress>");
460 continue_tail_cap_file(capture_file *cf, int to_read, int *err)
464 gtk_clist_freeze(GTK_CLIST(packet_list));
466 while (to_read != 0 && (data_offset = wtap_read(cf->wth, err)) > 0) {
467 if (cf->state == FILE_READ_ABORTED) {
468 /* Well, the user decided to exit Ethereal. Break out of the
469 loop, and let the code below (which is called even if there
470 aren't any packets left to read) exit. */
473 read_packet(cf, data_offset);
477 gtk_clist_thaw(GTK_CLIST(packet_list));
479 /* XXX - this cheats and looks inside the packet list to find the final
481 if (auto_scroll_live && cf->plist_end != NULL)
482 gtk_clist_moveto(GTK_CLIST(packet_list),
483 GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
485 if (cf->state == FILE_READ_ABORTED) {
486 /* Well, the user decided to exit Ethereal. Return READ_ABORTED
487 so that our caller can kill off the capture child process;
488 this will cause an EOF on the pipe from the child, so
489 "finish_tail_cap_file()" will be called, and it will clean up
492 } else if (data_offset < 0) {
493 /* We got an error reading the capture file.
494 XXX - pop up a dialog box? */
497 return (READ_SUCCESS);
501 finish_tail_cap_file(capture_file *cf, int *err)
505 gtk_clist_freeze(GTK_CLIST(packet_list));
507 while ((data_offset = wtap_read(cf->wth, err)) > 0) {
508 if (cf->state == FILE_READ_ABORTED) {
509 /* Well, the user decided to abort the read. Break out of the
510 loop, and let the code below (which is called even if there
511 aren't any packets left to read) exit. */
514 read_packet(cf, data_offset);
517 if (cf->state == FILE_READ_ABORTED) {
518 /* Well, the user decided to abort the read. We're only called
519 when the child capture process closes the pipe to us (meaning
520 it's probably exited), so we can just close the capture
521 file; we return READ_ABORTED so our caller can do whatever
522 is appropriate when that happens. */
523 close_cap_file(cf, info_bar);
528 if (auto_scroll_live && cf->plist_end != NULL)
529 /* XXX - this cheats and looks inside the packet list to find the final
531 gtk_clist_moveto(GTK_CLIST(packet_list),
532 GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
534 /* We're done reading sequentially through the file. */
535 cf->state = FILE_READ_DONE;
537 /* We're done reading sequentially through the file; close the
538 sequential I/O side, to free up memory it requires. */
539 wtap_sequential_close(cf->wth);
541 /* Set the file encapsulation type now; we don't know what it is until
542 we've looked at all the packets, as we don't know until then whether
543 there's more than one type (and thus whether it's
544 WTAP_ENCAP_PER_PACKET). */
545 cf->lnk_t = wtap_file_encap(cf->wth);
547 /* Pop the "<live capture in progress>" message off the status bar. */
548 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
550 set_display_filename(cf);
552 /* Enable menu items that make sense if you're not currently running
554 set_menus_for_capture_in_progress(FALSE);
556 /* Enable menu items that make sense if you have a capture file
557 you've finished reading. */
558 set_menus_for_capture_file(TRUE);
559 set_menus_for_unsaved_capture_file(!cf->user_saved);
561 if (data_offset < 0) {
562 /* We got an error reading the capture file.
563 XXX - pop up a dialog box? */
566 return (READ_SUCCESS);
568 #endif /* HAVE_LIBPCAP */
571 color_filter_t *colorf;
572 proto_tree *protocol_tree;
575 } apply_color_filter_args;
578 * If no color filter has been applied, apply this one.
579 * (The "if no color filter has been applied" is to handle the case where
580 * more than one color filter matches the packet.)
583 apply_color_filter(gpointer filter_arg, gpointer argp)
585 color_filter_t *colorf = filter_arg;
586 apply_color_filter_args *args = argp;
588 if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
589 if (dfilter_apply(colorf->c_colorfilter, args->protocol_tree, args->pd, args->fdata->cap_len))
590 args->colorf = colorf;
595 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
596 union wtap_pseudo_header *pseudo_header, const u_char *buf,
599 apply_color_filter_args args;
601 proto_tree *protocol_tree = NULL;
603 /* We don't yet have a color filter to apply. */
606 /* If we don't have the time stamp of the first packet in the
607 capture, it's because this is the first packet. Save the time
608 stamp of this packet as the time stamp of the first packet. */
609 if (!firstsec && !firstusec) {
610 firstsec = fdata->abs_secs;
611 firstusec = fdata->abs_usecs;
614 /* Get the time elapsed between the first packet and this packet. */
615 cf->esec = fdata->abs_secs - firstsec;
616 if (firstusec <= fdata->abs_usecs) {
617 cf->eusec = fdata->abs_usecs - firstusec;
619 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
623 fdata->cinfo = &cf->cinfo;
624 for (i = 0; i < fdata->cinfo->num_cols; i++) {
625 fdata->cinfo->col_data[i][0] = '\0';
630 we have a display filter and are re-applying it;
632 we have a list of color filters;
634 we have plugins to apply;
636 allocate a protocol tree root node, so that we'll construct
637 a protocol tree against which a filter expression can be
639 if ((cf->dfcode != NULL && refilter) || filter_list != NULL
641 || enabled_plugins_number > 0
644 protocol_tree = proto_tree_create_root();
646 /* Dissect the frame. */
647 dissect_packet(pseudo_header, buf, fdata, protocol_tree);
649 /* If we have a display filter, apply it if we're refiltering, otherwise
650 leave the "passed_dfilter" flag alone.
652 If we don't have a display filter, set "passed_dfilter" to 1. */
653 if (cf->dfcode != NULL) {
655 if (cf->dfcode != NULL)
656 fdata->flags.passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, buf, fdata->cap_len) ? 1 : 0;
658 fdata->flags.passed_dfilter = 1;
661 fdata->flags.passed_dfilter = 1;
663 /* If we have color filters, and the frame is to be displayed, apply
664 the color filters. */
665 if (fdata->flags.passed_dfilter) {
666 if (filter_list != NULL) {
667 args.protocol_tree = protocol_tree;
670 g_slist_foreach(filter_list, apply_color_filter, &args);
674 /* There are no more filters to apply, so we don't need any protocol
675 tree; free it if we created it. */
676 if (protocol_tree != NULL)
677 proto_tree_free(protocol_tree);
679 if (fdata->flags.passed_dfilter) {
680 /* This frame passed the display filter, so add it to the clist. */
682 /* If we don't have the time stamp of the previous displayed packet,
683 it's because this is the first displayed packet. Save the time
684 stamp of this packet as the time stamp of the previous displayed
686 if (!prevsec && !prevusec) {
687 prevsec = fdata->abs_secs;
688 prevusec = fdata->abs_usecs;
691 /* Get the time elapsed between the first packet and this packet. */
692 fdata->rel_secs = cf->esec;
693 fdata->rel_usecs = cf->eusec;
695 /* Get the time elapsed between the previous displayed packet and
697 fdata->del_secs = fdata->abs_secs - prevsec;
698 if (prevusec <= fdata->abs_usecs) {
699 fdata->del_usecs = fdata->abs_usecs - prevusec;
701 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
704 prevsec = fdata->abs_secs;
705 prevusec = fdata->abs_usecs;
707 fill_in_columns(fdata);
709 /* If we haven't yet seen the first frame, this is it.
711 XXX - we must do this before we add the row to the display,
712 as, if the display's GtkCList's selection mode is
713 GTK_SELECTION_BROWSE, when the first entry is added to it,
714 "select_packet()" will be called, and it will fetch the row
715 data for the 0th row, and will get a null pointer rather than
716 "fdata", as "gtk_clist_append()" won't yet have returned and
717 thus "gtk_clist_set_row_data()" won't yet have been called.
719 We thus need to leave behind bread crumbs so that
720 "select_packet()" can find this frame. See the comment
721 in "select_packet()". */
722 if (cf->first_displayed == NULL)
723 cf->first_displayed = fdata;
725 /* This is the last frame we've seen so far. */
726 cf->last_displayed = fdata;
728 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
729 gtk_clist_set_row_data(GTK_CLIST(packet_list), row, fdata);
731 if (filter_list != NULL && (args.colorf != NULL)) {
732 gtk_clist_set_background(GTK_CLIST(packet_list), row,
733 &args.colorf->bg_color);
734 gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
735 &args.colorf->fg_color);
737 gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
738 gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
741 /* This frame didn't pass the display filter, so it's not being added
742 to the clist, and thus has no row. */
750 read_packet(capture_file *cf, int offset)
752 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
753 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
754 const u_char *buf = wtap_buf_ptr(cf->wth);
757 proto_tree *protocol_tree;
758 frame_data *plist_end;
760 /* Allocate the next list entry, and add it to the list. */
761 fdata = g_mem_chunk_alloc(cf->plist_chunk);
766 fdata->pkt_len = phdr->len;
767 fdata->cap_len = phdr->caplen;
768 fdata->file_off = offset;
769 fdata->lnk_t = phdr->pkt_encap;
770 fdata->abs_secs = phdr->ts.tv_sec;
771 fdata->abs_usecs = phdr->ts.tv_usec;
772 fdata->flags.encoding = CHAR_ASCII;
773 fdata->flags.visited = 0;
778 protocol_tree = proto_tree_create_root();
779 dissect_packet(pseudo_header, buf, fdata, protocol_tree);
780 passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata->cap_len);
781 proto_tree_free(protocol_tree);
784 plist_end = cf->plist_end;
785 fdata->prev = plist_end;
786 if (plist_end != NULL)
787 plist_end->next = fdata;
790 cf->plist_end = fdata;
793 fdata->num = cf->count;
794 add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE);
796 /* XXX - if we didn't have read filters, or if we could avoid
797 allocating the "frame_data" structure until we knew whether
798 the frame passed the read filter, we could use a G_ALLOC_ONLY
801 ...but, at least in one test I did, where I just made the chunk
802 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
803 seem to save a noticeable amount of time or space. */
804 g_mem_chunk_free(cf->plist_chunk, fdata);
809 filter_packets(capture_file *cf, gchar *dftext)
813 if (dftext == NULL) {
814 /* The new filter is an empty filter (i.e., display all packets). */
818 * We have a filter; try to compile it.
820 if (dfilter_compile(dftext, &dfcode) != 0) {
821 /* The attempt failed; report an error. */
822 simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
827 if (dfcode == NULL) {
828 /* Yes - free the filter text, and set it to null. */
834 /* We have a valid filter. Replace the current filter. */
835 if (cf->dfilter != NULL)
837 cf->dfilter = dftext;
838 if (cf->dfcode != NULL)
839 dfilter_destroy(cf->dfcode);
842 /* Now rescan the packet list, applying the new filter. */
843 rescan_packets(cf, "Filtering", TRUE);
848 colorize_packets(capture_file *cf)
850 rescan_packets(cf, "Colorizing", FALSE);
854 redissect_packets(capture_file *cf)
856 rescan_packets(cf, "Reprocessing", TRUE);
859 /* Rescan the list of packets, reconstructing the CList.
861 "action" describes why we're doing this; it's used in the progress
864 "refilter" is TRUE if we need to re-evaluate the filter expression. */
866 rescan_packets(capture_file *cf, const char *action, gboolean refilter)
871 guint32 progbar_quantum;
872 guint32 progbar_nextstep;
874 frame_data *selected_frame;
878 /* Which frame, if any, is the currently selected frame?
879 XXX - should the selected frame or the focus frame be the "current"
880 frame, that frame being the one from which "Find Frame" searches
882 selected_frame = cf->current_frame;
884 /* We don't yet know what row that frame will be on, if any, after we
885 rebuild the clist, however. */
888 /* We need to re-initialize all the state information that protocols
889 keep, because we're making a fresh pass through all the packets. */
891 /* Initialize the table of conversations. */
894 /* Initialize protocol-specific variables */
895 init_all_protocols();
897 /* Freeze the packet list while we redo it, so we don't get any
898 screen updates while it happens. */
899 gtk_clist_freeze(GTK_CLIST(packet_list));
902 gtk_clist_clear(GTK_CLIST(packet_list));
904 /* We don't yet know which will be the first and last frames displayed. */
905 cf->first_displayed = NULL;
906 cf->last_displayed = NULL;
908 /* Iterate through the list of frames. Call a routine for each frame
909 to check whether it should be displayed and, if so, add it to
916 /* Update the progress bar when it gets to this value. */
917 progbar_nextstep = 0;
918 /* When we reach the value that triggers a progress bar update,
919 bump that value by this amount. */
920 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
921 /* Count of packets at which we've looked. */
925 progbar = create_progress_dlg(action, "Stop", &stop_flag);
927 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
928 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
929 when we update it, we have to run the GTK+ main loop to get it
930 to repaint what's pending, and doing so may involve an "ioctl()"
931 to see if there's any pending input from an X server, and doing
932 that for every packet can be costly, especially on a big file. */
933 if (count >= progbar_nextstep) {
934 /* let's not divide by zero. I should never be started
935 * with count == 0, so let's assert that
937 g_assert(cf->count > 0);
939 update_progress_dlg(progbar, (gfloat) count / cf->count);
941 progbar_nextstep += progbar_quantum;
945 /* Well, the user decided to abort the filtering. Just stop.
947 XXX - go back to the previous filter? Users probably just
948 want not to wait for a filtering operation to finish;
949 unless we cancel by having no filter, reverting to the
950 previous filter will probably be even more expensive than
951 continuing the filtering, as it involves going back to the
952 beginning and filtering, and even with no filter we currently
953 have to re-generate the entire clist, which is also expensive.
955 I'm not sure what Network Monitor does, but it doesn't appear
956 to give you an unfiltered display if you cancel. */
962 /* Since all state for the frame was destroyed, mark the frame
964 fdata->flags.visited = 0;
966 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
967 cf->pd, fdata->cap_len);
969 row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
971 if (fdata == selected_frame)
975 /* We're done filtering the packets; destroy the progress bar. */
976 destroy_progress_dlg(progbar);
978 /* Unfreeze the packet list. */
979 gtk_clist_thaw(GTK_CLIST(packet_list));
981 if (selected_row != -1) {
982 /* The frame that was selected passed the filter; select it, make it
983 the focus row, and make it visible. */
984 set_selected_row(selected_row);
985 finfo_selected = NULL;
987 /* The selected frame didn't pass the filter; make the first frame
988 the current frame, and leave it unselected. */
990 cf->current_frame = cf->first_displayed;
995 print_packets(capture_file *cf, print_args_t *print_args)
1001 guint32 progbar_quantum;
1002 guint32 progbar_nextstep;
1004 proto_tree *protocol_tree;
1005 gint *col_widths = NULL;
1007 gboolean print_separator;
1008 char *line_buf = NULL;
1009 int line_buf_len = 256;
1014 cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
1015 if (cf->print_fh == NULL)
1016 return FALSE; /* attempt to open destination failed */
1018 print_preamble(cf->print_fh, print_args->format);
1020 if (print_args->print_summary) {
1021 /* We're printing packet summaries. Allocate the line buffer at
1022 its initial length. */
1023 line_buf = g_malloc(line_buf_len + 1);
1025 /* Find the widths for each of the columns - maximum of the
1026 width of the title and the width of the data - and print
1027 the column titles. */
1028 col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1031 for (i = 0; i < cf->cinfo.num_cols; i++) {
1032 /* Don't pad the last column. */
1033 if (i == cf->cinfo.num_cols - 1)
1036 col_widths[i] = strlen(cf->cinfo.col_title[i]);
1037 data_width = get_column_char_width(get_column_format(i));
1038 if (data_width > col_widths[i])
1039 col_widths[i] = data_width;
1042 /* Find the length of the string for this column. */
1043 column_len = strlen(cf->cinfo.col_title[i]);
1044 if (col_widths[i] > column_len)
1045 column_len = col_widths[i];
1047 /* Make sure there's room in the line buffer for the column; if not,
1048 double its length. */
1049 line_len += column_len + 1; /* "+1" for space or \n */
1050 if (line_len > line_buf_len) {
1052 line_buf = g_realloc(line_buf, line_buf_len + 1);
1055 /* Right-justify the packet number column. */
1056 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1057 sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_title[i]);
1059 sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
1061 if (i == cf->cinfo.num_cols - 1)
1067 print_line(cf->print_fh, print_args->format, line_buf);
1070 print_separator = FALSE;
1072 /* The protocol tree will be "visible", i.e., printed, only if we're
1073 not printing a summary. */
1074 proto_tree_is_visible = !print_args->print_summary;
1076 /* Update the progress bar when it gets to this value. */
1077 progbar_nextstep = 0;
1078 /* When we reach the value that triggers a progress bar update,
1079 bump that value by this amount. */
1080 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1081 /* Count of packets at which we've looked. */
1085 progbar = create_progress_dlg("Printing", "Stop", &stop_flag);
1087 /* Iterate through the list of packets, printing the packets that
1088 were selected by the current display filter. */
1089 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1090 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1091 when we update it, we have to run the GTK+ main loop to get it
1092 to repaint what's pending, and doing so may involve an "ioctl()"
1093 to see if there's any pending input from an X server, and doing
1094 that for every packet can be costly, especially on a big file. */
1095 if (count >= progbar_nextstep) {
1096 /* let's not divide by zero. I should never be started
1097 * with count == 0, so let's assert that
1099 g_assert(cf->count > 0);
1101 update_progress_dlg(progbar, (gfloat) count / cf->count);
1103 progbar_nextstep += progbar_quantum;
1107 /* Well, the user decided to abort the printing. Just stop.
1109 XXX - note that what got generated before they did that
1110 will get printed, as we're piping to a print program; we'd
1111 have to write to a file and then hand that to the print
1112 program to make it actually not print anything. */
1118 if (fdata->flags.passed_dfilter) {
1119 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1120 cf->pd, fdata->cap_len);
1121 if (print_args->print_summary) {
1122 /* Fill in the column information, but don't bother creating
1123 the logical protocol tree. */
1124 fdata->cinfo = &cf->cinfo;
1125 for (i = 0; i < fdata->cinfo->num_cols; i++) {
1126 fdata->cinfo->col_data[i][0] = '\0';
1128 dissect_packet(&cf->pseudo_header, cf->pd, fdata, NULL);
1129 fill_in_columns(fdata);
1132 for (i = 0; i < cf->cinfo.num_cols; i++) {
1133 /* Find the length of the string for this column. */
1134 column_len = strlen(cf->cinfo.col_data[i]);
1135 if (col_widths[i] > column_len)
1136 column_len = col_widths[i];
1138 /* Make sure there's room in the line buffer for the column; if not,
1139 double its length. */
1140 line_len += column_len + 1; /* "+1" for space or \n */
1141 if (line_len > line_buf_len) {
1143 line_buf = g_realloc(line_buf, line_buf_len + 1);
1146 /* Right-justify the packet number column. */
1147 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1148 sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_data[i]);
1150 sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
1152 if (i == cf->cinfo.num_cols - 1)
1158 print_line(cf->print_fh, print_args->format, line_buf);
1160 if (print_separator)
1161 print_line(cf->print_fh, print_args->format, "\n");
1163 /* Create the logical protocol tree. */
1164 protocol_tree = proto_tree_create_root();
1165 dissect_packet(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
1167 /* Print the information in that tree. */
1168 proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
1169 cf->pd, fdata, cf->print_fh);
1171 proto_tree_free(protocol_tree);
1173 if (print_args->print_hex) {
1174 /* Print the full packet data as hex. */
1175 print_hex_data(cf->print_fh, print_args->format, cf->pd,
1176 fdata->cap_len, fdata->flags.encoding);
1179 /* Print a blank line if we print anything after this. */
1180 print_separator = TRUE;
1185 /* We're done printing the packets; destroy the progress bar. */
1186 destroy_progress_dlg(progbar);
1188 if (col_widths != NULL)
1190 if (line_buf != NULL)
1193 print_finale(cf->print_fh, print_args->format);
1195 close_print_dest(print_args->to_file, cf->print_fh);
1197 cf->print_fh = NULL;
1199 proto_tree_is_visible = FALSE;
1204 /* Scan through the packet list and change all columns that use the
1205 "command-line-specified" time stamp format to use the current
1206 value of that format. */
1208 change_time_formats(capture_file *cf)
1213 guint32 progbar_quantum;
1214 guint32 progbar_nextstep;
1220 /* Freeze the packet list while we redo it, so we don't get any
1221 screen updates while it happens. */
1224 /* Update the progress bar when it gets to this value. */
1225 progbar_nextstep = 0;
1226 /* When we reach the value that triggers a progress bar update,
1227 bump that value by this amount. */
1228 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1229 /* Count of packets at which we've looked. */
1233 progbar = create_progress_dlg("Changing time display", "Stop", &stop_flag);
1235 /* Iterate through the list of packets, checking whether the packet
1236 is in a row of the summary list and, if so, whether there are
1237 any columns that show the time in the "command-line-specified"
1238 format and, if so, update that row. */
1239 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1240 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1241 when we update it, we have to run the GTK+ main loop to get it
1242 to repaint what's pending, and doing so may involve an "ioctl()"
1243 to see if there's any pending input from an X server, and doing
1244 that for every packet can be costly, especially on a big file. */
1245 if (count >= progbar_nextstep) {
1246 /* let's not divide by zero. I should never be started
1247 * with count == 0, so let's assert that
1249 g_assert(cf->count > 0);
1251 update_progress_dlg(progbar, (gfloat) count / cf->count);
1253 progbar_nextstep += progbar_quantum;
1257 /* Well, the user decided to abort the redisplay. Just stop.
1259 XXX - this leaves the time field in the old format in
1260 frames we haven't yet processed. So it goes; should we
1261 simply not offer them the option of stopping? */
1267 /* Find what row this packet is in. */
1268 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1271 /* This packet is in the summary list, on row "row". */
1273 /* XXX - there really should be a way of checking "cf->cinfo" for this;
1274 the answer isn't going to change from packet to packet, so we should
1275 simply skip all the "change_time_formats()" work if we're not
1276 changing anything. */
1277 fdata->cinfo = &cf->cinfo;
1278 if (check_col(fdata, COL_CLS_TIME)) {
1279 /* There are columns that show the time in the "command-line-specified"
1280 format; update them. */
1281 for (i = 0; i < cf->cinfo.num_cols; i++) {
1282 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1283 /* This is one of the columns that shows the time in
1284 "command-line-specified" format; update it. */
1285 cf->cinfo.col_data[i][0] = '\0';
1286 col_set_cls_time(fdata, i);
1287 gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
1288 cf->cinfo.col_data[i]);
1295 /* We're done redisplaying the packets; destroy the progress bar. */
1296 destroy_progress_dlg(progbar);
1298 /* Set the column widths of those columns that show the time in
1299 "command-line-specified" format. */
1300 pl_style = gtk_widget_get_style(packet_list);
1301 for (i = 0; i < cf->cinfo.num_cols; i++) {
1302 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1303 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1304 gdk_string_width(pl_style->font, get_column_longest_string(COL_CLS_TIME)));
1308 /* Unfreeze the packet list. */
1313 clear_tree_and_hex_views(void)
1315 /* Clear the hex dump. */
1316 gtk_text_freeze(GTK_TEXT(byte_view));
1317 gtk_text_set_point(GTK_TEXT(byte_view), 0);
1318 gtk_text_forward_delete(GTK_TEXT(byte_view),
1319 gtk_text_get_length(GTK_TEXT(byte_view)));
1320 gtk_text_thaw(GTK_TEXT(byte_view));
1322 /* Remove all nodes in ctree. This is how it's done in testgtk.c in GTK+ */
1323 gtk_clist_clear ( GTK_CLIST(tree_view) );
1328 find_packet(capture_file *cf, dfilter *sfcode)
1330 frame_data *start_fd;
1332 frame_data *new_fd = NULL;
1335 guint32 progbar_quantum;
1336 guint32 progbar_nextstep;
1338 proto_tree *protocol_tree;
1339 gboolean frame_matched;
1342 start_fd = cf->current_frame;
1343 if (start_fd != NULL) {
1344 /* Iterate through the list of packets, starting at the packet we've
1345 picked, calling a routine to run the filter on the packet, see if
1346 it matches, and stop if so. */
1350 /* Update the progress bar when it gets to this value. */
1351 progbar_nextstep = 0;
1352 /* When we reach the value that triggers a progress bar update,
1353 bump that value by this amount. */
1354 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1357 progbar = create_progress_dlg("Searching", "Cancel", &stop_flag);
1361 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1362 when we update it, we have to run the GTK+ main loop to get it
1363 to repaint what's pending, and doing so may involve an "ioctl()"
1364 to see if there's any pending input from an X server, and doing
1365 that for every packet can be costly, especially on a big file. */
1366 if (count >= progbar_nextstep) {
1367 /* let's not divide by zero. I should never be started
1368 * with count == 0, so let's assert that
1370 g_assert(cf->count > 0);
1372 update_progress_dlg(progbar, (gfloat) count / cf->count);
1374 progbar_nextstep += progbar_quantum;
1378 /* Well, the user decided to abort the search. Go back to the
1379 frame where we started. */
1384 /* Go past the current frame. */
1385 if (cf->sbackward) {
1386 /* Go on to the previous frame. */
1387 fdata = fdata->prev;
1389 fdata = cf->plist_end; /* wrap around */
1391 /* Go on to the next frame. */
1392 fdata = fdata->next;
1394 fdata = cf->plist; /* wrap around */
1399 /* Is this packet in the display? */
1400 if (fdata->flags.passed_dfilter) {
1401 /* Yes. Does it match the search filter? */
1402 protocol_tree = proto_tree_create_root();
1403 wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
1404 cf->pd, fdata->cap_len);
1405 dissect_packet(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
1406 frame_matched = dfilter_apply(sfcode, protocol_tree, cf->pd, fdata->cap_len);
1407 proto_tree_free(protocol_tree);
1408 if (frame_matched) {
1410 break; /* found it! */
1414 if (fdata == start_fd) {
1415 /* We're back to the frame we were on originally, and that frame
1416 doesn't match the search filter. The search failed. */
1421 /* We're done scanning the packets; destroy the progress bar. */
1422 destroy_progress_dlg(progbar);
1425 if (new_fd != NULL) {
1426 /* We found a frame. Find what row it's in. */
1427 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), new_fd);
1428 g_assert(row != -1);
1430 /* Select that row, make it the focus row, and make it visible. */
1431 set_selected_row(row);
1432 return TRUE; /* success */
1434 return FALSE; /* failure */
1438 goto_frame(capture_file *cf, guint fnumber)
1443 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
1447 return NO_SUCH_FRAME; /* we didn't find that frame */
1448 if (!fdata->flags.passed_dfilter)
1449 return FRAME_NOT_DISPLAYED; /* the frame with that number isn't displayed */
1451 /* We found that frame, and it's currently being displayed.
1452 Find what row it's in. */
1453 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1454 g_assert(row != -1);
1456 /* Select that row, make it the focus row, and make it visible. */
1457 set_selected_row(row);
1461 /* Select the packet on a given row. */
1463 select_packet(capture_file *cf, int row)
1467 /* Get the frame data struct pointer for this frame */
1468 fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
1470 if (fdata == NULL) {
1471 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
1472 the first entry is added to it by "real_insert_row()", that row
1473 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
1474 our version and the vanilla GTK+ version).
1476 This means that a "select-row" signal is emitted; this causes
1477 "packet_list_select_cb()" to be called, which causes "select_packet()"
1480 "select_packet()" fetches, above, the data associated with the
1481 row that was selected; however, as "gtk_clist_append()", which
1482 called "real_insert_row()", hasn't yet returned, we haven't yet
1483 associated any data with that row, so we get back a null pointer.
1485 We can't assume that there's only one frame in the frame list,
1486 either, as we may be filtering the display.
1488 We therefore assume that, if "row" is 0, i.e. the first row
1489 is being selected, and "cf->first_displayed" equals
1490 "cf->last_displayed", i.e. there's only one frame being
1491 displayed, that frame is the frame we want.
1493 This means we have to set "cf->first_displayed" and
1494 "cf->last_displayed" before adding the row to the
1495 GtkCList; see the comment in "add_packet_to_packet_list()". */
1497 if (row == 0 && cf->first_displayed == cf->last_displayed)
1498 fdata = cf->first_displayed;
1501 /* Record that this frame is the current frame. */
1502 cf->current_frame = fdata;
1504 /* Get the data in that frame. */
1505 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1506 cf->pd, fdata->cap_len);
1508 /* Create the logical protocol tree. */
1509 if (cf->protocol_tree)
1510 proto_tree_free(cf->protocol_tree);
1511 cf->protocol_tree = proto_tree_create_root();
1512 proto_tree_is_visible = TRUE;
1513 dissect_packet(&cf->pseudo_header, cf->pd, cf->current_frame,
1515 proto_tree_is_visible = FALSE;
1517 /* Display the GUI protocol tree and hex dump. */
1518 clear_tree_and_hex_views();
1519 proto_tree_draw(cf->protocol_tree, tree_view);
1520 packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->current_frame->cap_len,
1521 -1, -1, cf->current_frame->flags.encoding);
1523 /* A packet is selected. */
1524 set_menus_for_selected_packet(TRUE);
1527 /* Unselect the selected packet, if any. */
1529 unselect_packet(capture_file *cf)
1531 /* Destroy the protocol tree for that packet. */
1532 if (cf->protocol_tree != NULL) {
1533 proto_tree_free(cf->protocol_tree);
1534 cf->protocol_tree = NULL;
1537 finfo_selected = NULL;
1539 /* Clear out the display of that packet. */
1540 clear_tree_and_hex_views();
1542 /* No packet is selected. */
1543 set_menus_for_selected_packet(FALSE);
1546 /* Set the selected row and the focus row of the packet list to the specified
1547 row, and make it visible if it's not currently visible. */
1549 set_selected_row(int row)
1551 if (gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) != GTK_VISIBILITY_FULL)
1552 gtk_clist_moveto(GTK_CLIST(packet_list), row, -1, 0.0, 0.0);
1554 /* XXX - why is there no "gtk_clist_set_focus_row()", so that we
1555 can make the row for the frame we found the focus row?
1559 http://www.gnome.org/mailing-lists/archives/gtk-list/2000-January/0038.shtml
1562 GTK_CLIST(packet_list)->focus_row = row;
1564 gtk_clist_select_row(GTK_CLIST(packet_list), row, -1);
1568 freeze_clist(capture_file *cf)
1572 /* Make the column sizes static, so they don't adjust while
1573 we're reading the capture file (freezing the clist doesn't
1574 seem to suffice). */
1575 for (i = 0; i < cf->cinfo.num_cols; i++)
1576 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1577 gtk_clist_freeze(GTK_CLIST(packet_list));
1581 thaw_clist(capture_file *cf)
1585 for (i = 0; i < cf->cinfo.num_cols; i++) {
1586 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1587 /* Set this column's width to the appropriate value. */
1588 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1589 cf->cinfo.col_width[i]);
1591 /* Make this column's size dynamic, so that it adjusts to the
1592 appropriate size. */
1593 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1596 gtk_clist_thaw(GTK_CLIST(packet_list));
1598 /* Hopefully, the columns have now gotten their appropriate sizes;
1599 make them resizeable - a column that auto-resizes cannot be
1600 resized by the user, and *vice versa*. */
1601 for (i = 0; i < cf->cinfo.num_cols; i++)
1602 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1606 save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
1609 gchar *from_filename;
1610 gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
1616 struct wtap_pkthdr hdr;
1617 union wtap_pseudo_header pseudo_header;
1620 name_ptr = get_basename(fname);
1621 msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
1622 save_msg = g_malloc(msg_len);
1623 snprintf(save_msg, msg_len, save_fmt, name_ptr);
1624 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
1627 if (!save_filtered && save_format == cf->cd_t) {
1628 /* We're not filtering packets, and we're saving it in the format
1629 it's already in, so we can just move or copy the raw data. */
1631 /* In this branch, we set "err" only if we get an error, so we
1632 must first clear it. */
1634 if (cf->is_tempfile) {
1635 /* The file being saved is a temporary file from a live
1636 capture, so it doesn't need to stay around under that name;
1637 first, try renaming the capture buffer file to the new name. */
1639 if (rename(cf->filename, fname) == 0) {
1640 /* That succeeded - there's no need to copy the source file. */
1641 from_filename = NULL;
1644 if (errno == EXDEV) {
1645 /* They're on different file systems, so we have to copy the
1648 from_filename = cf->filename;
1650 /* The rename failed, but not because they're on different
1651 file systems - put up an error message. (Or should we
1652 just punt and try to copy? The only reason why I'd
1653 expect the rename to fail and the copy to succeed would
1654 be if we didn't have permission to remove the file from
1655 the temporary directory, and that might be fixable - but
1656 is it worth requiring the user to go off and fix it?) */
1658 simple_dialog(ESD_TYPE_CRIT, NULL,
1659 file_rename_error_message(err), fname);
1665 from_filename = cf->filename;
1668 /* It's a permanent file, so we should copy it, and not remove the
1671 from_filename = cf->filename;
1673 /* Copy the file, if we haven't moved it. */
1675 if (!copy_binary_file(from_filename, fname)) {
1680 /* Either we're filtering packets, or we're saving in a different
1681 format; we can't do that by copying or moving the capture file,
1682 we have to do it by writing the packets out in Wiretap. */
1683 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
1685 simple_dialog(ESD_TYPE_CRIT, NULL,
1686 file_open_error_message(err, TRUE), fname);
1690 /* XXX - have a way to save only the packets currently selected by
1693 If we do that, should we make that file the current file? If so,
1694 it means we can no longer get at the other packets. What does
1696 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1697 /* XXX - do a progress bar */
1698 if (!save_filtered || fdata->flags.passed_dfilter) {
1699 /* Either we're saving all frames, or we're saving filtered frames
1700 and this one passed the display filter - save it. */
1701 hdr.ts.tv_sec = fdata->abs_secs;
1702 hdr.ts.tv_usec = fdata->abs_usecs;
1703 hdr.caplen = fdata->cap_len;
1704 hdr.len = fdata->pkt_len;
1705 hdr.pkt_encap = fdata->lnk_t;
1706 wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1707 pd, fdata->cap_len);
1709 if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
1710 simple_dialog(ESD_TYPE_CRIT, NULL,
1711 file_write_error_message(err), fname);
1712 wtap_dump_close(pdh, &err);
1718 if (!wtap_dump_close(pdh, &err)) {
1719 simple_dialog(ESD_TYPE_WARN, NULL,
1720 file_close_error_message(err), fname);
1727 /* Pop the "Saving:" message off the status bar. */
1728 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
1730 if (!save_filtered) {
1731 /* We saved the entire capture, not just some packets from it.
1732 Open and read the file we saved it to.
1734 XXX - this is somewhat of a waste; we already have the
1735 packets, all this gets us is updated file type information
1736 (which we could just stuff into "cf"), and having the new
1737 file be the one we have opened and from which we're reading
1738 the data, and it means we have to spend time opening and
1739 reading the file, which could be a significant amount of
1740 time if the file is large. */
1741 cf->user_saved = TRUE;
1743 if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
1744 /* XXX - report errors if this fails? */
1745 switch (read_cap_file(cf, &err)) {
1749 /* Just because we got an error, that doesn't mean we were unable
1750 to read any of the file; we handle what we could get from the
1755 /* The user bailed out of re-reading the capture file; the
1756 capture file has been closed - just return (without
1757 changing any menu settings; "close_cap_file()" set them
1758 correctly for the "no capture file open" state). */
1761 set_menus_for_unsaved_capture_file(FALSE);
1769 file_open_error_message(int err, gboolean for_writing)
1772 static char errmsg_errno[1024+1];
1776 case WTAP_ERR_NOT_REGULAR_FILE:
1777 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1780 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1781 case WTAP_ERR_UNSUPPORTED:
1782 /* Seen only when opening a capture file for reading. */
1783 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1786 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1787 /* Seen only when opening a capture file for writing. */
1788 errmsg = "Ethereal does not support writing capture files in that format.";
1791 case WTAP_ERR_UNSUPPORTED_ENCAP:
1792 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1794 errmsg = "Ethereal cannot save this capture in that format.";
1796 errmsg = "The file \"%s\" is a capture for a network type that Ethereal doesn't support.";
1799 case WTAP_ERR_BAD_RECORD:
1800 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1803 case WTAP_ERR_CANT_OPEN:
1805 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1807 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1810 case WTAP_ERR_SHORT_READ:
1811 errmsg = "The file \"%s\" appears to have been cut short"
1812 " in the middle of a packet.";
1815 case WTAP_ERR_SHORT_WRITE:
1816 errmsg = "A full header couldn't be written to the file \"%s\".";
1821 errmsg = "The path to the file \"%s\" does not exist.";
1823 errmsg = "The file \"%s\" does not exist.";
1828 errmsg = "You do not have permission to create or write to the file \"%s\".";
1830 errmsg = "You do not have permission to read the file \"%s\".";
1834 errmsg = "\"%s\" is a directory (folder), not a file.";
1838 snprintf(errmsg_errno, sizeof(errmsg_errno),
1839 "The file \"%%s\" could not be opened: %s.",
1840 wtap_strerror(err));
1841 errmsg = errmsg_errno;
1848 file_rename_error_message(int err)
1851 static char errmsg_errno[1024+1];
1856 errmsg = "The path to the file \"%s\" does not exist.";
1860 errmsg = "You do not have permission to move the capture file to \"%s\".";
1864 snprintf(errmsg_errno, sizeof(errmsg_errno),
1865 "The file \"%%s\" could not be moved: %s.",
1866 wtap_strerror(err));
1867 errmsg = errmsg_errno;
1874 file_read_error_message(int err)
1876 static char errmsg_errno[1024+1];
1878 snprintf(errmsg_errno, sizeof(errmsg_errno),
1879 "An error occurred while reading from the file \"%%s\": %s.",
1880 wtap_strerror(err));
1881 return errmsg_errno;
1885 file_write_error_message(int err)
1888 static char errmsg_errno[1024+1];
1893 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1898 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1903 snprintf(errmsg_errno, sizeof(errmsg_errno),
1904 "An error occurred while writing to the file \"%%s\": %s.",
1905 wtap_strerror(err));
1906 errmsg = errmsg_errno;
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 snprintf(errmsg_errno, sizeof(errmsg_errno),
1944 "An error occurred while closing the file \"%%s\": %s.",
1945 wtap_strerror(err));
1946 errmsg = errmsg_errno;
1953 /* Copies a file in binary mode, for those operating systems that care about
1955 * Returns TRUE on success, FALSE on failure. If a failure, it also
1956 * displays a simple dialog window with the error message.
1959 copy_binary_file(char *from_filename, char *to_filename)
1961 int from_fd, to_fd, nread, nwritten, err;
1962 guint8 pd[65536]; /* XXX - Hmm, 64K here, 64K in save_cap_file(),
1963 perhaps we should make just one 64K buffer. */
1965 /* Copy the raw bytes of the file. */
1966 from_fd = open(from_filename, O_RDONLY | O_BINARY);
1969 simple_dialog(ESD_TYPE_CRIT, NULL,
1970 file_open_error_message(err, TRUE), from_filename);
1974 /* Use open() instead of creat() so that we can pass the O_BINARY
1975 flag, which is relevant on Win32; it appears that "creat()"
1976 may open the file in text mode, not binary mode, but we want
1977 to copy the raw bytes of the file, so we need the output file
1978 to be open in binary mode. */
1979 to_fd = open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1982 simple_dialog(ESD_TYPE_CRIT, NULL,
1983 file_open_error_message(err, TRUE), to_filename);
1988 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
1989 nwritten = write(to_fd, pd, nread);
1990 if (nwritten < nread) {
1994 err = WTAP_ERR_SHORT_WRITE;
1995 simple_dialog(ESD_TYPE_CRIT, NULL,
1996 file_write_error_message(err), to_filename);
2004 simple_dialog(ESD_TYPE_CRIT, NULL,
2005 file_read_error_message(err), from_filename);
2011 if (close(to_fd) < 0) {
2013 simple_dialog(ESD_TYPE_CRIT, NULL,
2014 file_close_error_message(err), to_filename);