4 * $Id: file.c,v 1.192 2000/06/27 09:26:10 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.
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, *prog_bar, *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 set_selected_row(int row);
100 static void freeze_clist(capture_file *cf);
101 static void thaw_clist(capture_file *cf);
103 static char *file_rename_error_message(int err);
104 static char *file_close_error_message(int err);
106 /* Update the progress bar this many times when reading a file. */
107 #define N_PROGBAR_UPDATES 100
109 /* Number of "frame_data" structures per memory chunk.
110 XXX - is this the right number? */
111 #define FRAME_DATA_CHUNK_SIZE 1024
114 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
122 wth = wtap_open_offline(fname, &err, TRUE);
126 /* Find the size of the file. */
129 if (fstat(fd, &cf_stat) < 0) {
135 /* The open succeeded. Close whatever capture file we had open,
136 and fill in the information for this file. */
137 close_cap_file(cf, info_bar);
139 /* Initialize the table of conversations. */
142 /* Initialize protocol-specific variables */
143 init_all_protocols();
145 /* We're about to start reading the file. */
146 cf->state = FILE_READ_IN_PROGRESS;
150 cf->f_len = cf_stat.st_size;
152 /* Set the file name because we need it to set the follow stream filter.
153 XXX - is that still true? We need it for other reasons, though,
155 cf->filename = g_strdup(fname);
157 /* Indicate whether it's a permanent or temporary file. */
158 cf->is_tempfile = is_tempfile;
160 /* If it's a temporary capture buffer file, mark it as not saved. */
161 cf->user_saved = !is_tempfile;
163 cf->cd_t = wtap_file_type(cf->wth);
168 cf->snap = wtap_snapshot_length(cf->wth);
169 cf->update_progbar = FALSE;
170 cf->progbar_quantum = 0;
171 cf->progbar_nextstep = 0;
172 firstsec = 0, firstusec = 0;
173 prevsec = 0, prevusec = 0;
175 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
177 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
179 g_assert(cf->plist_chunk);
184 simple_dialog(ESD_TYPE_WARN, NULL,
185 file_open_error_message(err, FALSE), fname);
189 /* Reset everything to a pristine state */
191 close_cap_file(capture_file *cf, void *w)
193 /* Die if we're in the middle of reading a file. */
194 g_assert(cf->state != FILE_READ_IN_PROGRESS);
196 /* Destroy all popup packet windows, as they refer to packets in the
197 capture file we're closing. */
198 destroy_packet_wins();
204 /* We have no file open... */
205 if (cf->filename != NULL) {
206 /* If it's a temporary file, remove it. */
208 unlink(cf->filename);
209 g_free(cf->filename);
212 /* ...which means we have nothing to save. */
213 cf->user_saved = FALSE;
215 if (cf->plist_chunk != NULL) {
216 g_mem_chunk_destroy(cf->plist_chunk);
217 cf->plist_chunk = NULL;
219 if (cf->rfcode != NULL) {
220 dfilter_destroy(cf->rfcode);
224 cf->plist_end = NULL;
225 unselect_packet(cf); /* nothing to select */
226 cf->first_displayed = NULL;
227 cf->last_displayed = NULL;
229 /* Clear the packet list. */
230 gtk_clist_freeze(GTK_CLIST(packet_list));
231 gtk_clist_clear(GTK_CLIST(packet_list));
232 gtk_clist_thaw(GTK_CLIST(packet_list));
234 /* Clear any file-related status bar messages.
235 XXX - should be "clear *ALL* file-related status bar messages;
236 will there ever be more than one on the stack? */
237 gtk_statusbar_pop(GTK_STATUSBAR(w), file_ctx);
239 /* Restore the standard title bar message. */
240 set_main_window_name("The Ethereal Network Analyzer");
242 /* Disable all menu items that make sense only if you have a capture. */
243 set_menus_for_capture_file(FALSE);
244 set_menus_for_unsaved_capture_file(FALSE);
245 set_menus_for_captured_packets(FALSE);
246 set_menus_for_selected_packet(FALSE);
247 set_menus_for_capture_in_progress(FALSE);
249 /* We have no file open. */
250 cf->state = FILE_CLOSED;
253 /* Set the file name in the status line, in the name for the main window,
254 and in the name for the main window's icon. */
256 set_display_filename(capture_file *cf)
260 gchar *done_fmt = " File: %s Drops: %u";
262 gchar *win_name_fmt = "%s - Ethereal";
265 if (!cf->is_tempfile) {
266 /* Get the last component of the file name, and put that in the
268 name_ptr = get_basename(cf->filename);
270 /* The file we read is a temporary file from a live capture;
271 we don't mention its name in the status bar. */
272 name_ptr = "<capture>";
275 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
276 done_msg = g_malloc(msg_len);
277 snprintf(done_msg, msg_len, done_fmt, name_ptr, cf->drops);
278 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
281 msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
282 win_name = g_malloc(msg_len);
283 snprintf(win_name, msg_len, win_name_fmt, name_ptr);
284 set_main_window_name(win_name);
289 read_cap_file(capture_file *cf, int *err)
291 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
294 char errmsg_errno[1024+1];
295 gchar err_str[2048+1];
298 name_ptr = get_basename(cf->filename);
300 msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
301 load_msg = g_malloc(msg_len);
302 snprintf(load_msg, msg_len, load_fmt, name_ptr);
303 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
306 cf->update_progbar = TRUE;
307 /* Update the progress bar when it gets to this value. */
308 cf->progbar_nextstep = 0;
309 /* When we reach the value that triggers a progress bar update,
310 bump that value by this amount. */
311 cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
319 while ((data_offset = wtap_read(cf->wth, err)) > 0) {
320 if (cf->state == FILE_READ_ABORTED) {
321 /* Well, the user decided to abort the read. Close the capture
322 file, and return READ_ABORTED so our caller can do whatever is
323 appropriate when that happens. */
324 close_cap_file(cf, info_bar);
325 return (READ_ABORTED);
327 read_packet(cf, data_offset);
330 /* We're done reading sequentially through the file. */
331 cf->state = FILE_READ_DONE;
333 /* Close the sequential I/O side, to free up memory it requires. */
334 wtap_sequential_close(cf->wth);
336 /* Set the file encapsulation type now; we don't know what it is until
337 we've looked at all the packets, as we don't know until then whether
338 there's more than one type (and thus whether it's
339 WTAP_ENCAP_PER_PACKET). */
340 cf->lnk_t = wtap_file_encap(cf->wth);
342 cf->current_frame = cf->first_displayed;
345 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
346 gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
348 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
349 set_display_filename(cf);
351 /* Enable menu items that make sense if you have a capture file you've
353 set_menus_for_capture_file(TRUE);
354 set_menus_for_unsaved_capture_file(!cf->user_saved);
356 /* Enable menu items that make sense if you have some captured packets. */
357 set_menus_for_captured_packets(TRUE);
359 /* If we have any displayed packets to select, select the first of those
360 packets by making the first row the selected row. */
361 if (cf->first_displayed != NULL)
362 gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
364 if (data_offset < 0) {
365 /* Put up a message box noting that the read failed somewhere along
366 the line. Don't throw out the stuff we managed to read, though,
370 case WTAP_ERR_UNSUPPORTED_ENCAP:
371 errmsg = "The capture file is for a network type that Ethereal doesn't support.";
374 case WTAP_ERR_CANT_READ:
375 errmsg = "An attempt to read from the file failed for"
376 " some unknown reason.";
379 case WTAP_ERR_SHORT_READ:
380 errmsg = "The capture file appears to have been cut short"
381 " in the middle of a packet.";
384 case WTAP_ERR_BAD_RECORD:
385 errmsg = "The capture file appears to be damaged or corrupt.";
389 sprintf(errmsg_errno, "An error occurred while reading the"
390 " capture file: %s.", wtap_strerror(*err));
391 errmsg = errmsg_errno;
394 snprintf(err_str, sizeof err_str, errmsg);
395 simple_dialog(ESD_TYPE_WARN, NULL, err_str);
398 return (READ_SUCCESS);
403 start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
408 err = open_cap_file(fname, is_tempfile, cf);
410 /* Disable menu items that make no sense if you're currently running
412 set_menus_for_capture_in_progress(TRUE);
414 /* Enable menu items that make sense if you have some captured
415 packets (yes, I know, we don't have any *yet*). */
416 set_menus_for_captured_packets(TRUE);
418 for (i = 0; i < cf->cinfo.num_cols; i++) {
419 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
420 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
422 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
423 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
424 cf->cinfo.col_width[i]);
425 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
429 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
430 " <live capture in progress>");
436 continue_tail_cap_file(capture_file *cf, int to_read, int *err)
440 gtk_clist_freeze(GTK_CLIST(packet_list));
442 while (to_read != 0 && (data_offset = wtap_read(cf->wth, err)) > 0) {
443 if (cf->state == FILE_READ_ABORTED) {
444 /* Well, the user decided to exit Ethereal. Break out of the
445 loop, and let the code below (which is called even if there
446 aren't any packets left to read) exit. */
449 read_packet(cf, data_offset);
453 gtk_clist_thaw(GTK_CLIST(packet_list));
455 /* XXX - this cheats and looks inside the packet list to find the final
457 if (auto_scroll_live && cf->plist_end != NULL)
458 gtk_clist_moveto(GTK_CLIST(packet_list),
459 GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
461 if (cf->state == FILE_READ_ABORTED) {
462 /* Well, the user decided to exit Ethereal. Return READ_ABORTED
463 so that our caller can kill off the capture child process;
464 this will cause an EOF on the pipe from the child, so
465 "finish_tail_cap_file()" will be called, and it will clean up
468 } else if (data_offset < 0) {
469 /* We got an error reading the capture file.
470 XXX - pop up a dialog box? */
473 return (READ_SUCCESS);
477 finish_tail_cap_file(capture_file *cf, int *err)
481 gtk_clist_freeze(GTK_CLIST(packet_list));
483 while ((data_offset = wtap_read(cf->wth, err)) > 0) {
484 if (cf->state == FILE_READ_ABORTED) {
485 /* Well, the user decided to abort the read. Break out of the
486 loop, and let the code below (which is called even if there
487 aren't any packets left to read) exit. */
490 read_packet(cf, data_offset);
493 if (cf->state == FILE_READ_ABORTED) {
494 /* Well, the user decided to abort the read. We're only called
495 when the child capture process closes the pipe to us (meaning
496 it's probably exited), so we can just close the capture
497 file; we return READ_ABORTED so our caller can do whatever
498 is appropriate when that happens. */
499 close_cap_file(cf, info_bar);
504 if (auto_scroll_live && cf->plist_end != NULL)
505 /* XXX - this cheats and looks inside the packet list to find the final
507 gtk_clist_moveto(GTK_CLIST(packet_list),
508 GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
510 /* We're done reading sequentially through the file. */
511 cf->state = FILE_READ_DONE;
513 /* We're done reading sequentially through the file; close the
514 sequential I/O side, to free up memory it requires. */
515 wtap_sequential_close(cf->wth);
517 /* Set the file encapsulation type now; we don't know what it is until
518 we've looked at all the packets, as we don't know until then whether
519 there's more than one type (and thus whether it's
520 WTAP_ENCAP_PER_PACKET). */
521 cf->lnk_t = wtap_file_encap(cf->wth);
523 /* Pop the "<live capture in progress>" message off the status bar. */
524 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
526 set_display_filename(cf);
528 /* Enable menu items that make sense if you're not currently running
530 set_menus_for_capture_in_progress(FALSE);
532 /* Enable menu items that make sense if you have a capture file
533 you've finished reading. */
534 set_menus_for_capture_file(TRUE);
535 set_menus_for_unsaved_capture_file(!cf->user_saved);
537 if (data_offset < 0) {
538 /* We got an error reading the capture file.
539 XXX - pop up a dialog box? */
542 return (READ_SUCCESS);
544 #endif /* HAVE_LIBPCAP */
547 color_filter_t *colorf;
548 proto_tree *protocol_tree;
551 } apply_color_filter_args;
554 * If no color filter has been applied, apply this one.
555 * (The "if no color filter has been applied" is to handle the case where
556 * more than one color filter matches the packet.)
559 apply_color_filter(gpointer filter_arg, gpointer argp)
561 color_filter_t *colorf = filter_arg;
562 apply_color_filter_args *args = argp;
564 if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
565 if (dfilter_apply(colorf->c_colorfilter, args->protocol_tree, args->pd, args->fdata->cap_len))
566 args->colorf = colorf;
571 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
572 union wtap_pseudo_header *pseudo_header, const u_char *buf)
574 apply_color_filter_args args;
576 proto_tree *protocol_tree = NULL;
578 /* We don't yet have a color filter to apply. */
581 /* If we don't have the time stamp of the first packet in the
582 capture, it's because this is the first packet. Save the time
583 stamp of this packet as the time stamp of the first packet. */
584 if (!firstsec && !firstusec) {
585 firstsec = fdata->abs_secs;
586 firstusec = fdata->abs_usecs;
589 /* Get the time elapsed between the first packet and this packet. */
590 cf->esec = fdata->abs_secs - firstsec;
591 if (firstusec <= fdata->abs_usecs) {
592 cf->eusec = fdata->abs_usecs - firstusec;
594 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
598 fdata->cinfo = &cf->cinfo;
599 for (i = 0; i < fdata->cinfo->num_cols; i++) {
600 fdata->cinfo->col_data[i][0] = '\0';
603 /* Apply the filters */
604 if (cf->dfcode != NULL || filter_list != NULL) {
605 protocol_tree = proto_tree_create_root();
606 dissect_packet(pseudo_header, buf, fdata, protocol_tree);
607 if (cf->dfcode != NULL)
608 fdata->flags.passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, buf, fdata->cap_len) ? 1 : 0;
610 fdata->flags.passed_dfilter = 1;
612 /* Apply color filters, if we have any. */
613 if (filter_list != NULL) {
614 args.protocol_tree = protocol_tree;
617 g_slist_foreach(filter_list, apply_color_filter, &args);
619 proto_tree_free(protocol_tree);
623 if (enabled_plugins_number > 0)
624 protocol_tree = proto_tree_create_root();
626 dissect_packet(pseudo_header, buf, fdata, protocol_tree);
627 fdata->flags.passed_dfilter = 1;
630 proto_tree_free(protocol_tree);
634 if (fdata->flags.passed_dfilter) {
635 /* This frame passed the display filter, so add it to the clist. */
637 /* If we don't have the time stamp of the previous displayed packet,
638 it's because this is the first displayed packet. Save the time
639 stamp of this packet as the time stamp of the previous displayed
641 if (!prevsec && !prevusec) {
642 prevsec = fdata->abs_secs;
643 prevusec = fdata->abs_usecs;
646 /* Get the time elapsed between the first packet and this packet. */
647 fdata->rel_secs = cf->esec;
648 fdata->rel_usecs = cf->eusec;
650 /* Get the time elapsed between the previous displayed packet and
652 fdata->del_secs = fdata->abs_secs - prevsec;
653 if (prevusec <= fdata->abs_usecs) {
654 fdata->del_usecs = fdata->abs_usecs - prevusec;
656 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
659 prevsec = fdata->abs_secs;
660 prevusec = fdata->abs_usecs;
662 fill_in_columns(fdata);
664 /* If we haven't yet seen the first frame, this is it.
666 XXX - we must do this before we add the row to the display,
667 as, if the display's GtkCList's selection mode is
668 GTK_SELECTION_BROWSE, when the first entry is added to it,
669 "select_packet()" will be called, and it will fetch the row
670 data for the 0th row, and will get a null pointer rather than
671 "fdata", as "gtk_clist_append()" won't yet have returned and
672 thus "gtk_clist_set_row_data()" won't yet have been called.
674 We thus need to leave behind bread crumbs so that
675 "select_packet()" can find this frame. See the comment
676 in "select_packet()". */
677 if (cf->first_displayed == NULL)
678 cf->first_displayed = fdata;
680 /* This is the last frame we've seen so far. */
681 cf->last_displayed = fdata;
683 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
684 gtk_clist_set_row_data(GTK_CLIST(packet_list), row, fdata);
686 if (filter_list != NULL && (args.colorf != NULL)) {
687 gtk_clist_set_background(GTK_CLIST(packet_list), row,
688 &args.colorf->bg_color);
689 gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
690 &args.colorf->fg_color);
692 gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
693 gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
696 /* This frame didn't pass the display filter, so it's not being added
697 to the clist, and thus has no row. */
705 read_packet(capture_file *cf, int offset)
707 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
708 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
709 const u_char *buf = wtap_buf_ptr(cf->wth);
712 proto_tree *protocol_tree;
713 frame_data *plist_end;
717 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
718 when we update it, we have to run the GTK+ main loop to get it
719 to repaint what's pending, and doing so may involve an "ioctl()"
720 to see if there's any pending input from an X server, and doing
721 that for every packet can be costly, especially on a big file.
723 Do so only if we were told to do so; when reading a capture file
724 being updated by a live capture, we don't do so (as we're not
725 "done" until the capture stops, so we don't know how close to
728 if (cf->update_progbar && offset >= cf->progbar_nextstep) {
729 file_pos = lseek(cf->filed, 0, SEEK_CUR);
730 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
731 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), prog_val);
732 cf->progbar_nextstep += cf->progbar_quantum;
733 while (gtk_events_pending())
734 gtk_main_iteration();
737 /* Allocate the next list entry, and add it to the list. */
738 fdata = g_mem_chunk_alloc(cf->plist_chunk);
743 fdata->pkt_len = phdr->len;
744 fdata->cap_len = phdr->caplen;
745 fdata->file_off = offset;
746 fdata->lnk_t = phdr->pkt_encap;
747 fdata->abs_secs = phdr->ts.tv_sec;
748 fdata->abs_usecs = phdr->ts.tv_usec;
749 fdata->flags.encoding = CHAR_ASCII;
750 fdata->flags.visited = 0;
755 protocol_tree = proto_tree_create_root();
756 dissect_packet(pseudo_header, buf, fdata, protocol_tree);
757 passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata->cap_len);
758 proto_tree_free(protocol_tree);
761 plist_end = cf->plist_end;
762 fdata->prev = plist_end;
763 if (plist_end != NULL)
764 plist_end->next = fdata;
767 cf->plist_end = fdata;
770 fdata->num = cf->count;
771 add_packet_to_packet_list(fdata, cf, pseudo_header, buf);
773 /* XXX - if we didn't have read filters, or if we could avoid
774 allocating the "frame_data" structure until we knew whether
775 the frame passed the read filter, we could use a G_ALLOC_ONLY
778 ...but, at least in one test I did, where I just made the chunk
779 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
780 seem to save a noticeable amount of time or space. */
781 g_mem_chunk_free(cf->plist_chunk, fdata);
786 filter_packets(capture_file *cf, gchar *dftext)
790 if (dftext == NULL) {
791 /* The new filter is an empty filter (i.e., display all packets). */
795 * We have a filter; try to compile it.
797 if (dfilter_compile(dftext, &dfcode) != 0) {
798 /* The attempt failed; report an error. */
799 simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
804 if (dfcode == NULL) {
805 /* Yes - free the filter text, and set it to null. */
811 /* We have a valid filter. Replace the current filter. */
812 if (cf->dfilter != NULL)
814 cf->dfilter = dftext;
815 if (cf->dfcode != NULL)
816 dfilter_destroy(cf->dfcode);
819 /* Now go through the list of packets we've read from the capture file,
820 applying the current display filter, and, if the packet passes the
821 display filter, add it to the summary display, appropriately
822 colored. (That's how we colorize the display - it's like filtering
823 the display, only we don't install a new filter.) */
824 colorize_packets(cf);
829 colorize_packets(capture_file *cf)
832 guint32 progbar_quantum;
833 guint32 progbar_nextstep;
835 frame_data *selected_frame;
839 /* Which frame, if any, is the currently selected frame?
840 XXX - should the selected frame or the focus frame be the "current"
841 frame, that frame being the one from which "Find Frame" searches
843 selected_frame = cf->current_frame;
845 /* We don't yet know what row that frame will be on, if any, after we
846 rebuild the clist, however. */
849 /* We need to re-initialize all the state information that protocols
850 keep, because we're making a fresh pass through all the packets. */
852 /* Initialize the table of conversations. */
855 /* Initialize protocol-specific variables */
856 init_all_protocols();
858 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
860 /* Freeze the packet list while we redo it, so we don't get any
861 screen updates while it happens. */
862 gtk_clist_freeze(GTK_CLIST(packet_list));
865 gtk_clist_clear(GTK_CLIST(packet_list));
867 /* We don't yet know which will be the first and last frames displayed. */
868 cf->first_displayed = NULL;
869 cf->last_displayed = NULL;
871 /* Iterate through the list of packets, calling a routine
872 to run the filter on the packet, see if it matches, and
873 put it in the display list if so. */
879 /* Update the progress bar when it gets to this value. */
880 progbar_nextstep = 0;
881 /* When we reach the value that triggers a progress bar update,
882 bump that value by this amount. */
883 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
884 /* Count of packets at which we've looked. */
887 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
889 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
890 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
891 when we update it, we have to run the GTK+ main loop to get it
892 to repaint what's pending, and doing so may involve an "ioctl()"
893 to see if there's any pending input from an X server, and doing
894 that for every packet can be costly, especially on a big file. */
895 if (count >= progbar_nextstep) {
896 /* let's not divide by zero. I should never be started
897 * with count == 0, so let's assert that
899 g_assert(cf->count > 0);
901 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
902 (gfloat) count / cf->count);
904 progbar_nextstep += progbar_quantum;
905 while (gtk_events_pending())
906 gtk_main_iteration();
911 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
912 cf->pd, fdata->cap_len);
914 row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd);
915 if (fdata == selected_frame)
919 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
921 /* Unfreeze the packet list. */
922 gtk_clist_thaw(GTK_CLIST(packet_list));
924 if (selected_row != -1) {
925 /* The frame that was selected passed the filter; select it, make it
926 the focus row, and make it visible. */
927 set_selected_row(selected_row);
928 finfo_selected = NULL;
930 /* The selected frame didn't pass the filter; make the first frame
931 the current frame, and leave it unselected. */
933 cf->current_frame = cf->first_displayed;
938 print_packets(capture_file *cf, print_args_t *print_args)
942 guint32 progbar_quantum;
943 guint32 progbar_nextstep;
945 proto_tree *protocol_tree;
946 gint *col_widths = NULL;
948 gboolean print_separator;
949 char *line_buf = NULL;
950 int line_buf_len = 256;
955 cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
956 if (cf->print_fh == NULL)
957 return FALSE; /* attempt to open destination failed */
959 print_preamble(cf->print_fh, print_args->format);
961 if (print_args->print_summary) {
962 /* We're printing packet summaries. Allocate the line buffer at
963 its initial length. */
964 line_buf = g_malloc(line_buf_len + 1);
966 /* Find the widths for each of the columns - maximum of the
967 width of the title and the width of the data - and print
968 the column titles. */
969 col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
972 for (i = 0; i < cf->cinfo.num_cols; i++) {
973 /* Don't pad the last column. */
974 if (i == cf->cinfo.num_cols - 1)
977 col_widths[i] = strlen(cf->cinfo.col_title[i]);
978 data_width = get_column_char_width(get_column_format(i));
979 if (data_width > col_widths[i])
980 col_widths[i] = data_width;
983 /* Find the length of the string for this column. */
984 column_len = strlen(cf->cinfo.col_title[i]);
985 if (col_widths[i] > column_len)
986 column_len = col_widths[i];
988 /* Make sure there's room in the line buffer for the column; if not,
989 double its length. */
990 line_len += column_len + 1; /* "+1" for space or \n */
991 if (line_len > line_buf_len) {
993 line_buf = g_realloc(line_buf, line_buf_len + 1);
996 /* Right-justify the packet number column. */
997 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
998 sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_title[i]);
1000 sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
1002 if (i == cf->cinfo.num_cols - 1)
1008 print_line(cf->print_fh, print_args->format, line_buf);
1011 print_separator = FALSE;
1013 /* The protocol tree will be "visible", i.e., printed, only if we're
1014 not printing a summary. */
1015 proto_tree_is_visible = !print_args->print_summary;
1017 /* Update the progress bar when it gets to this value. */
1018 progbar_nextstep = 0;
1019 /* When we reach the value that triggers a progress bar update,
1020 bump that value by this amount. */
1021 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1022 /* Count of packets at which we've looked. */
1025 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
1027 /* Iterate through the list of packets, printing the packets that
1028 were selected by the current display filter. */
1029 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1030 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1031 when we update it, we have to run the GTK+ main loop to get it
1032 to repaint what's pending, and doing so may involve an "ioctl()"
1033 to see if there's any pending input from an X server, and doing
1034 that for every packet can be costly, especially on a big file. */
1035 if (count >= progbar_nextstep) {
1036 /* let's not divide by zero. I should never be started
1037 * with count == 0, so let's assert that
1039 g_assert(cf->count > 0);
1041 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1042 (gfloat) count / cf->count);
1043 progbar_nextstep += progbar_quantum;
1044 while (gtk_events_pending())
1045 gtk_main_iteration();
1049 if (fdata->flags.passed_dfilter) {
1050 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1051 cf->pd, fdata->cap_len);
1052 if (print_args->print_summary) {
1053 /* Fill in the column information, but don't bother creating
1054 the logical protocol tree. */
1055 fdata->cinfo = &cf->cinfo;
1056 for (i = 0; i < fdata->cinfo->num_cols; i++) {
1057 fdata->cinfo->col_data[i][0] = '\0';
1059 dissect_packet(&cf->pseudo_header, cf->pd, fdata, NULL);
1060 fill_in_columns(fdata);
1063 for (i = 0; i < cf->cinfo.num_cols; i++) {
1064 /* Find the length of the string for this column. */
1065 column_len = strlen(cf->cinfo.col_data[i]);
1066 if (col_widths[i] > column_len)
1067 column_len = col_widths[i];
1069 /* Make sure there's room in the line buffer for the column; if not,
1070 double its length. */
1071 line_len += column_len + 1; /* "+1" for space or \n */
1072 if (line_len > line_buf_len) {
1074 line_buf = g_realloc(line_buf, line_buf_len + 1);
1077 /* Right-justify the packet number column. */
1078 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1079 sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_data[i]);
1081 sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
1083 if (i == cf->cinfo.num_cols - 1)
1089 print_line(cf->print_fh, print_args->format, line_buf);
1091 if (print_separator)
1092 print_line(cf->print_fh, print_args->format, "\n");
1094 /* Create the logical protocol tree. */
1095 protocol_tree = proto_tree_create_root();
1096 dissect_packet(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
1098 /* Print the information in that tree. */
1099 proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
1100 cf->pd, fdata, cf->print_fh);
1102 proto_tree_free(protocol_tree);
1104 if (print_args->print_hex) {
1105 /* Print the full packet data as hex. */
1106 print_hex_data(cf->print_fh, print_args->format, cf->pd,
1107 fdata->cap_len, fdata->flags.encoding);
1110 /* Print a blank line if we print anything after this. */
1111 print_separator = TRUE;
1116 if (col_widths != NULL)
1118 if (line_buf != NULL)
1121 print_finale(cf->print_fh, print_args->format);
1123 close_print_dest(print_args->to_file, cf->print_fh);
1125 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1127 cf->print_fh = NULL;
1129 proto_tree_is_visible = FALSE;
1134 /* Scan through the packet list and change all columns that use the
1135 "command-line-specified" time stamp format to use the current
1136 value of that format. */
1138 change_time_formats(capture_file *cf)
1145 /* Freeze the packet list while we redo it, so we don't get any
1146 screen updates while it happens. */
1149 /* Iterate through the list of packets, checking whether the packet
1150 is in a row of the summary list and, if so, whether there are
1151 any columns that show the time in the "command-line-specified"
1152 format and, if so, update that row. */
1153 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1154 /* Find what row this packet is in. */
1155 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1158 /* This packet is in the summary list, on row "row". */
1160 /* XXX - there really should be a way of checking "cf->cinfo" for this;
1161 the answer isn't going to change from packet to packet, so we should
1162 simply skip all the "change_time_formats()" work if we're not
1163 changing anything. */
1164 fdata->cinfo = &cf->cinfo;
1165 if (check_col(fdata, COL_CLS_TIME)) {
1166 /* There are columns that show the time in the "command-line-specified"
1167 format; update them. */
1168 for (i = 0; i < cf->cinfo.num_cols; i++) {
1169 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1170 /* This is one of the columns that shows the time in
1171 "command-line-specified" format; update it. */
1172 cf->cinfo.col_data[i][0] = '\0';
1173 col_set_cls_time(fdata, i);
1174 gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
1175 cf->cinfo.col_data[i]);
1182 /* Set the column widths of those columns that show the time in
1183 "command-line-specified" format. */
1184 pl_style = gtk_widget_get_style(packet_list);
1185 for (i = 0; i < cf->cinfo.num_cols; i++) {
1186 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1187 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1188 gdk_string_width(pl_style->font, get_column_longest_string(COL_CLS_TIME)));
1192 /* Unfreeze the packet list. */
1197 clear_tree_and_hex_views(void)
1199 /* Clear the hex dump. */
1200 gtk_text_freeze(GTK_TEXT(byte_view));
1201 gtk_text_set_point(GTK_TEXT(byte_view), 0);
1202 gtk_text_forward_delete(GTK_TEXT(byte_view),
1203 gtk_text_get_length(GTK_TEXT(byte_view)));
1204 gtk_text_thaw(GTK_TEXT(byte_view));
1206 /* Remove all nodes in ctree. This is how it's done in testgtk.c in GTK+ */
1207 gtk_clist_clear ( GTK_CLIST(tree_view) );
1212 find_packet(capture_file *cf, dfilter *sfcode)
1214 frame_data *start_fd;
1216 frame_data *new_fd = NULL;
1217 guint32 progbar_quantum;
1218 guint32 progbar_nextstep;
1220 proto_tree *protocol_tree;
1221 gboolean frame_matched;
1224 start_fd = cf->current_frame;
1225 if (start_fd != NULL) {
1226 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
1228 /* Iterate through the list of packets, starting at the packet we've
1229 picked, calling a routine to run the filter on the packet, see if
1230 it matches, and stop if so. */
1234 /* Update the progress bar when it gets to this value. */
1235 progbar_nextstep = 0;
1236 /* When we reach the value that triggers a progress bar update,
1237 bump that value by this amount. */
1238 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1239 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
1243 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1244 when we update it, we have to run the GTK+ main loop to get it
1245 to repaint what's pending, and doing so may involve an "ioctl()"
1246 to see if there's any pending input from an X server, and doing
1247 that for every packet can be costly, especially on a big file. */
1248 if (count >= progbar_nextstep) {
1249 /* let's not divide by zero. I should never be started
1250 * with count == 0, so let's assert that
1252 g_assert(cf->count > 0);
1254 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1255 (gfloat) count / cf->count);
1257 progbar_nextstep += progbar_quantum;
1258 while (gtk_events_pending())
1259 gtk_main_iteration();
1262 /* Go past the current frame. */
1263 if (cf->sbackward) {
1264 /* Go on to the previous frame. */
1265 fdata = fdata->prev;
1267 fdata = cf->plist_end; /* wrap around */
1269 /* Go on to the next frame. */
1270 fdata = fdata->next;
1272 fdata = cf->plist; /* wrap around */
1277 /* Is this packet in the display? */
1278 if (fdata->flags.passed_dfilter) {
1279 /* Yes. Does it match the search filter? */
1280 protocol_tree = proto_tree_create_root();
1281 wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
1282 cf->pd, fdata->cap_len);
1283 dissect_packet(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
1284 frame_matched = dfilter_apply(sfcode, protocol_tree, cf->pd, fdata->cap_len);
1285 proto_tree_free(protocol_tree);
1286 if (frame_matched) {
1288 break; /* found it! */
1292 if (fdata == start_fd) {
1293 /* We're back to the frame we were on originally, and that frame
1294 doesn't match the search filter. The search failed. */
1299 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1302 if (new_fd != NULL) {
1303 /* We found a frame. Find what row it's in. */
1304 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), new_fd);
1305 g_assert(row != -1);
1307 /* Select that row, make it the focus row, and make it visible. */
1308 set_selected_row(row);
1309 return TRUE; /* success */
1311 return FALSE; /* failure */
1315 goto_frame(capture_file *cf, guint fnumber)
1320 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
1324 return NO_SUCH_FRAME; /* we didn't find that frame */
1325 if (!fdata->flags.passed_dfilter)
1326 return FRAME_NOT_DISPLAYED; /* the frame with that number isn't displayed */
1328 /* We found that frame, and it's currently being displayed.
1329 Find what row it's in. */
1330 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1331 g_assert(row != -1);
1333 /* Select that row, make it the focus row, and make it visible. */
1334 set_selected_row(row);
1338 /* Select the packet on a given row. */
1340 select_packet(capture_file *cf, int row)
1344 /* Get the frame data struct pointer for this frame */
1345 fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
1347 if (fdata == NULL) {
1348 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
1349 the first entry is added to it by "real_insert_row()", that row
1350 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
1351 our version and the vanilla GTK+ version).
1353 This means that a "select-row" signal is emitted; this causes
1354 "packet_list_select_cb()" to be called, which causes "select_packet()"
1357 "select_packet()" fetches, above, the data associated with the
1358 row that was selected; however, as "gtk_clist_append()", which
1359 called "real_insert_row()", hasn't yet returned, we haven't yet
1360 associated any data with that row, so we get back a null pointer.
1362 We can't assume that there's only one frame in the frame list,
1363 either, as we may be filtering the display.
1365 We therefore assume that, if "row" is 0, i.e. the first row
1366 is being selected, and "cf->first_displayed" equals
1367 "cf->last_displayed", i.e. there's only one frame being
1368 displayed, that frame is the frame we want.
1370 This means we have to set "cf->first_displayed" and
1371 "cf->last_displayed" before adding the row to the
1372 GtkCList; see the comment in "add_packet_to_packet_list()". */
1374 if (row == 0 && cf->first_displayed == cf->last_displayed)
1375 fdata = cf->first_displayed;
1378 /* Record that this frame is the current frame. */
1379 cf->current_frame = fdata;
1381 /* Get the data in that frame. */
1382 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1383 cf->pd, fdata->cap_len);
1385 /* Create the logical protocol tree. */
1386 if (cf->protocol_tree)
1387 proto_tree_free(cf->protocol_tree);
1388 cf->protocol_tree = proto_tree_create_root();
1389 proto_tree_is_visible = TRUE;
1390 dissect_packet(&cf->pseudo_header, cf->pd, cf->current_frame,
1392 proto_tree_is_visible = FALSE;
1394 /* Display the GUI protocol tree and hex dump. */
1395 clear_tree_and_hex_views();
1396 proto_tree_draw(cf->protocol_tree, tree_view);
1397 packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->current_frame->cap_len,
1398 -1, -1, cf->current_frame->flags.encoding);
1400 /* A packet is selected. */
1401 set_menus_for_selected_packet(TRUE);
1404 /* Unselect the selected packet, if any. */
1406 unselect_packet(capture_file *cf)
1408 /* Destroy the protocol tree for that packet. */
1409 if (cf->protocol_tree != NULL) {
1410 proto_tree_free(cf->protocol_tree);
1411 cf->protocol_tree = NULL;
1414 finfo_selected = NULL;
1416 /* Clear out the display of that packet. */
1417 clear_tree_and_hex_views();
1419 /* No packet is selected. */
1420 set_menus_for_selected_packet(FALSE);
1423 /* Set the selected row and the focus row of the packet list to the specified
1424 row, and make it visible if it's not currently visible. */
1426 set_selected_row(int row)
1428 if (gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) != GTK_VISIBILITY_FULL)
1429 gtk_clist_moveto(GTK_CLIST(packet_list), row, -1, 0.0, 0.0);
1431 /* XXX - why is there no "gtk_clist_set_focus_row()", so that we
1432 can make the row for the frame we found the focus row?
1436 http://www.gnome.org/mailing-lists/archives/gtk-list/2000-January/0038.shtml
1439 GTK_CLIST(packet_list)->focus_row = row;
1441 gtk_clist_select_row(GTK_CLIST(packet_list), row, -1);
1445 freeze_clist(capture_file *cf)
1449 /* Make the column sizes static, so they don't adjust while
1450 we're reading the capture file (freezing the clist doesn't
1451 seem to suffice). */
1452 for (i = 0; i < cf->cinfo.num_cols; i++)
1453 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1454 gtk_clist_freeze(GTK_CLIST(packet_list));
1458 thaw_clist(capture_file *cf)
1462 for (i = 0; i < cf->cinfo.num_cols; i++) {
1463 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1464 /* Set this column's width to the appropriate value. */
1465 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1466 cf->cinfo.col_width[i]);
1468 /* Make this column's size dynamic, so that it adjusts to the
1469 appropriate size. */
1470 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1473 gtk_clist_thaw(GTK_CLIST(packet_list));
1475 /* Hopefully, the columns have now gotten their appropriate sizes;
1476 make them resizeable - a column that auto-resizes cannot be
1477 resized by the user, and *vice versa*. */
1478 for (i = 0; i < cf->cinfo.num_cols; i++)
1479 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1483 save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
1486 gchar *from_filename;
1487 gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
1491 int from_fd, to_fd, nread, nwritten;
1494 struct wtap_pkthdr hdr;
1495 union wtap_pseudo_header pseudo_header;
1498 name_ptr = get_basename(fname);
1499 msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
1500 save_msg = g_malloc(msg_len);
1501 snprintf(save_msg, msg_len, save_fmt, name_ptr);
1502 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
1505 if (!save_filtered && save_format == cf->cd_t) {
1506 /* We're not filtering packets, and we're saving it in the format
1507 it's already in, so we can just move or copy the raw data. */
1509 /* In this branch, we set "err" only if we get an error, so we
1510 must first clear it. */
1512 if (cf->is_tempfile) {
1513 /* The file being saved is a temporary file from a live
1514 capture, so it doesn't need to stay around under that name;
1515 first, try renaming the capture buffer file to the new name. */
1517 if (rename(cf->filename, fname) == 0) {
1518 /* That succeeded - there's no need to copy the source file. */
1519 from_filename = NULL;
1522 if (errno == EXDEV) {
1523 /* They're on different file systems, so we have to copy the
1526 from_filename = cf->filename;
1528 /* The rename failed, but not because they're on different
1529 file systems - put up an error message. (Or should we
1530 just punt and try to copy? The only reason why I'd
1531 expect the rename to fail and the copy to succeed would
1532 be if we didn't have permission to remove the file from
1533 the temporary directory, and that might be fixable - but
1534 is it worth requiring the user to go off and fix it?) */
1536 simple_dialog(ESD_TYPE_WARN, NULL,
1537 file_rename_error_message(err), fname);
1543 from_filename = cf->filename;
1546 /* It's a permanent file, so we should copy it, and not remove the
1549 from_filename = cf->filename;
1551 /* Copy the file, if we haven't moved it. */
1553 /* Copy the raw bytes of the file. */
1554 from_fd = open(from_filename, O_RDONLY | O_BINARY);
1557 simple_dialog(ESD_TYPE_WARN, NULL,
1558 file_open_error_message(err, TRUE), from_filename);
1562 /* Use open() instead of creat() so that we can pass the O_BINARY
1563 flag, which is relevant on Win32; it appears that "creat()"
1564 may open the file in text mode, not binary mode, but we want
1565 to copy the raw bytes of the file, so we need the output file
1566 to be open in binary mode. */
1567 to_fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1570 simple_dialog(ESD_TYPE_WARN, NULL,
1571 file_open_error_message(err, TRUE), fname);
1576 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
1577 nwritten = write(to_fd, pd, nread);
1578 if (nwritten < nread) {
1582 err = WTAP_ERR_SHORT_WRITE;
1583 simple_dialog(ESD_TYPE_WARN, NULL,
1584 file_write_error_message(err), fname);
1592 simple_dialog(ESD_TYPE_WARN, NULL,
1593 file_read_error_message(err), from_filename);
1599 if (close(to_fd) < 0) {
1601 simple_dialog(ESD_TYPE_WARN, NULL,
1602 file_close_error_message(err), fname);
1607 /* Either we're filtering packets, or we're saving in a different
1608 format; we can't do that by copying or moving the capture file,
1609 we have to do it by writing the packets out in Wiretap. */
1610 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
1612 simple_dialog(ESD_TYPE_WARN, NULL,
1613 file_open_error_message(err, TRUE), fname);
1617 /* XXX - have a way to save only the packets currently selected by
1620 If we do that, should we make that file the current file? If so,
1621 it means we can no longer get at the other packets. What does
1623 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1624 /* XXX - do a progress bar */
1625 if (!save_filtered || fdata->flags.passed_dfilter) {
1626 /* Either we're saving all frames, or we're saving filtered frames
1627 and this one passed the display filter - save it. */
1628 hdr.ts.tv_sec = fdata->abs_secs;
1629 hdr.ts.tv_usec = fdata->abs_usecs;
1630 hdr.caplen = fdata->cap_len;
1631 hdr.len = fdata->pkt_len;
1632 hdr.pkt_encap = fdata->lnk_t;
1633 wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1634 pd, fdata->cap_len);
1636 if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
1637 simple_dialog(ESD_TYPE_WARN, NULL,
1638 file_write_error_message(err), fname);
1639 wtap_dump_close(pdh, &err);
1645 if (!wtap_dump_close(pdh, &err)) {
1646 simple_dialog(ESD_TYPE_WARN, NULL,
1647 file_close_error_message(err), fname);
1654 /* Pop the "Saving:" message off the status bar. */
1655 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
1657 if (!save_filtered) {
1658 /* We saved the entire capture, not just some packets from it.
1659 Open and read the file we saved it to.
1661 XXX - this is somewhat of a waste; we already have the
1662 packets, all this gets us is updated file type information
1663 (which we could just stuff into "cf"), and having the new
1664 file be the one we have opened and from which we're reading
1665 the data, and it means we have to spend time opening and
1666 reading the file, which could be a significant amount of
1667 time if the file is large. */
1668 cf->user_saved = TRUE;
1670 if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
1671 /* XXX - report errors if this fails? */
1672 switch (read_cap_file(cf, &err)) {
1676 /* Just because we got an error, that doesn't mean we were unable
1677 to read any of the file; we handle what we could get from the
1682 /* Exit by leaving the main loop, so that any quit functions
1683 we registered get called. */
1687 set_menus_for_unsaved_capture_file(FALSE);
1695 file_open_error_message(int err, int for_writing)
1698 static char errmsg_errno[1024+1];
1702 case WTAP_ERR_NOT_REGULAR_FILE:
1703 errmsg = "The file \"%s\" is invalid.";
1706 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1707 case WTAP_ERR_UNSUPPORTED:
1708 /* Seen only when opening a capture file for reading. */
1709 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1712 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1713 /* Seen only when opening a capture file for writing. */
1714 errmsg = "Ethereal does not support writing capture files in that format.";
1717 case WTAP_ERR_UNSUPPORTED_ENCAP:
1718 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1720 errmsg = "Ethereal cannot save this capture in that format.";
1722 errmsg = "The file \"%s\" is a capture for a network type that Ethereal doesn't support.";
1725 case WTAP_ERR_BAD_RECORD:
1726 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1729 case WTAP_ERR_CANT_OPEN:
1731 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1733 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1736 case WTAP_ERR_SHORT_READ:
1737 errmsg = "The file \"%s\" appears to have been cut short"
1738 " in the middle of a packet.";
1741 case WTAP_ERR_SHORT_WRITE:
1742 errmsg = "A full header couldn't be written to the file \"%s\".";
1747 errmsg = "The path to the file \"%s\" does not exist.";
1749 errmsg = "The file \"%s\" does not exist.";
1754 errmsg = "You do not have permission to create or write to the file \"%s\".";
1756 errmsg = "You do not have permission to read the file \"%s\".";
1760 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
1761 wtap_strerror(err));
1762 errmsg = errmsg_errno;
1769 file_rename_error_message(int err)
1772 static char errmsg_errno[1024+1];
1777 errmsg = "The path to the file \"%s\" does not exist.";
1781 errmsg = "You do not have permission to move the capture file to \"%s\".";
1785 sprintf(errmsg_errno, "The file \"%%s\" could not be moved: %s.",
1786 wtap_strerror(err));
1787 errmsg = errmsg_errno;
1794 file_read_error_message(int err)
1796 static char errmsg_errno[1024+1];
1798 sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.",
1799 wtap_strerror(err));
1800 return errmsg_errno;
1804 file_write_error_message(int err)
1807 static char errmsg_errno[1024+1];
1812 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1817 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1822 sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.",
1823 wtap_strerror(err));
1824 errmsg = errmsg_errno;
1830 /* Check for write errors - if the file is being written to an NFS server,
1831 a write error may not show up until the file is closed, as NFS clients
1832 might not send writes to the server until the "write()" call finishes,
1833 so that the write may fail on the server but the "write()" may succeed. */
1835 file_close_error_message(int err)
1838 static char errmsg_errno[1024+1];
1842 case WTAP_ERR_CANT_CLOSE:
1843 errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
1846 case WTAP_ERR_SHORT_WRITE:
1847 errmsg = "Not all the data could be written to the file \"%s\".";
1851 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1856 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1861 sprintf(errmsg_errno, "An error occurred while closing the file \"%%s\": %s.",
1862 wtap_strerror(err));
1863 errmsg = errmsg_errno;