4 * $Id: file.c,v 1.190 2000/06/27 04:35:44 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 wtap_dispatch_cb(u_char *, const struct wtap_pkthdr *, int,
97 union wtap_pseudo_header *, const u_char *);
99 static void set_selected_row(int row);
101 static void freeze_clist(capture_file *cf);
102 static void thaw_clist(capture_file *cf);
104 static char *file_rename_error_message(int err);
105 static char *file_close_error_message(int err);
107 /* Update the progress bar this many times when reading a file. */
108 #define N_PROGBAR_UPDATES 100
110 /* Number of "frame_data" structures per memory chunk.
111 XXX - is this the right number? */
112 #define FRAME_DATA_CHUNK_SIZE 1024
115 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
123 wth = wtap_open_offline(fname, &err, TRUE);
127 /* Find the size of the file. */
130 if (fstat(fd, &cf_stat) < 0) {
136 /* The open succeeded. Close whatever capture file we had open,
137 and fill in the information for this file. */
138 close_cap_file(cf, info_bar);
140 /* Initialize the table of conversations. */
143 /* Initialize protocol-specific variables */
144 init_all_protocols();
148 cf->f_len = cf_stat.st_size;
150 /* Set the file name because we need it to set the follow stream filter.
151 XXX - is that still true? We need it for other reasons, though,
153 cf->filename = g_strdup(fname);
155 /* Indicate whether it's a permanent or temporary file. */
156 cf->is_tempfile = is_tempfile;
158 /* If it's a temporary capture buffer file, mark it as not saved. */
159 cf->user_saved = !is_tempfile;
161 cf->cd_t = wtap_file_type(cf->wth);
166 cf->snap = wtap_snapshot_length(cf->wth);
167 cf->update_progbar = FALSE;
168 cf->progbar_quantum = 0;
169 cf->progbar_nextstep = 0;
170 firstsec = 0, firstusec = 0;
171 prevsec = 0, prevusec = 0;
173 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
175 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
177 g_assert(cf->plist_chunk);
182 simple_dialog(ESD_TYPE_WARN, NULL,
183 file_open_error_message(err, FALSE), fname);
187 /* Reset everything to a pristine state */
189 close_cap_file(capture_file *cf, void *w)
191 /* Destroy all popup packet windows, as they refer to packets in the
192 capture file we're closing. */
193 destroy_packet_wins();
199 /* We have no file open... */
200 if (cf->filename != NULL) {
201 /* If it's a temporary file, remove it. */
203 unlink(cf->filename);
204 g_free(cf->filename);
207 /* ...which means we have nothing to save. */
208 cf->user_saved = FALSE;
210 if (cf->plist_chunk != NULL) {
211 g_mem_chunk_destroy(cf->plist_chunk);
212 cf->plist_chunk = NULL;
214 if (cf->rfcode != NULL) {
215 dfilter_destroy(cf->rfcode);
219 cf->plist_end = NULL;
220 unselect_packet(cf); /* nothing to select */
221 cf->first_displayed = NULL;
222 cf->last_displayed = NULL;
224 /* Clear the packet list. */
225 gtk_clist_freeze(GTK_CLIST(packet_list));
226 gtk_clist_clear(GTK_CLIST(packet_list));
227 gtk_clist_thaw(GTK_CLIST(packet_list));
229 /* Clear any file-related status bar messages.
230 XXX - should be "clear *ALL* file-related status bar messages;
231 will there ever be more than one on the stack? */
232 gtk_statusbar_pop(GTK_STATUSBAR(w), file_ctx);
234 /* Restore the standard title bar message. */
235 set_main_window_name("The Ethereal Network Analyzer");
237 /* Disable all menu items that make sense only if you have a capture. */
238 set_menus_for_capture_file(FALSE);
239 set_menus_for_unsaved_capture_file(FALSE);
240 set_menus_for_captured_packets(FALSE);
241 set_menus_for_selected_packet(FALSE);
242 set_menus_for_capture_in_progress(FALSE);
245 /* Set the file name in the status line, in the name for the main window,
246 and in the name for the main window's icon. */
248 set_display_filename(capture_file *cf)
252 gchar *done_fmt = " File: %s Drops: %u";
254 gchar *win_name_fmt = "%s - Ethereal";
257 if (!cf->is_tempfile) {
258 /* Get the last component of the file name, and put that in the
260 name_ptr = get_basename(cf->filename);
262 /* The file we read is a temporary file from a live capture;
263 we don't mention its name in the status bar. */
264 name_ptr = "<capture>";
267 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
268 done_msg = g_malloc(msg_len);
269 snprintf(done_msg, msg_len, done_fmt, name_ptr, cf->drops);
270 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
273 msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
274 win_name = g_malloc(msg_len);
275 snprintf(win_name, msg_len, win_name_fmt, name_ptr);
276 set_main_window_name(win_name);
281 read_cap_file(capture_file *cf)
283 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
288 char errmsg_errno[1024+1];
289 gchar err_str[2048+1];
291 name_ptr = get_basename(cf->filename);
293 msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
294 load_msg = g_malloc(msg_len);
295 snprintf(load_msg, msg_len, load_fmt, name_ptr);
296 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
299 cf->update_progbar = TRUE;
300 /* Update the progress bar when it gets to this value. */
301 cf->progbar_nextstep = 0;
302 /* When we reach the value that triggers a progress bar update,
303 bump that value by this amount. */
304 cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
311 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
312 /* Set the file encapsulation type now; we don't know what it is until
313 we've looked at all the packets, as we don't know until then whether
314 there's more than one type (and thus whether it's
315 WTAP_ENCAP_PER_PACKET). */
317 /* We're done reading sequentially through the file; close the
318 sequential I/O side, to free up memory it requires. */
319 wtap_sequential_close(cf->wth);
321 cf->lnk_t = wtap_file_encap(cf->wth);
322 cf->current_frame = cf->first_displayed;
325 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
326 gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
328 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
329 set_display_filename(cf);
331 /* Enable menu items that make sense if you have a capture file you've
333 set_menus_for_capture_file(TRUE);
334 set_menus_for_unsaved_capture_file(!cf->user_saved);
336 /* Enable menu items that make sense if you have some captured packets. */
337 set_menus_for_captured_packets(TRUE);
339 /* If we have any displayed packets to select, select the first of those
340 packets by making the first row the selected row. */
341 if (cf->first_displayed != NULL)
342 gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
345 /* Put up a message box noting that the read failed somewhere along
346 the line. Don't throw out the stuff we managed to read, though,
350 case WTAP_ERR_UNSUPPORTED_ENCAP:
351 errmsg = "The capture file is for a network type that Ethereal doesn't support.";
354 case WTAP_ERR_CANT_READ:
355 errmsg = "An attempt to read from the file failed for"
356 " some unknown reason.";
359 case WTAP_ERR_SHORT_READ:
360 errmsg = "The capture file appears to have been cut short"
361 " in the middle of a packet.";
364 case WTAP_ERR_BAD_RECORD:
365 errmsg = "The capture file appears to be damaged or corrupt.";
369 sprintf(errmsg_errno, "An error occurred while reading the"
370 " capture file: %s.", wtap_strerror(err));
371 errmsg = errmsg_errno;
374 snprintf(err_str, sizeof err_str, errmsg);
375 simple_dialog(ESD_TYPE_WARN, NULL, err_str);
383 start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
388 err = open_cap_file(fname, is_tempfile, cf);
390 /* Disable menu items that make no sense if you're currently running
392 set_menus_for_capture_in_progress(TRUE);
394 /* Enable menu items that make sense if you have some captured
395 packets (yes, I know, we don't have any *yet*). */
396 set_menus_for_captured_packets(TRUE);
398 for (i = 0; i < cf->cinfo.num_cols; i++) {
399 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
400 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
402 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
403 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
404 cf->cinfo.col_width[i]);
405 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
409 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
410 " <live capture in progress>");
416 continue_tail_cap_file(capture_file *cf, int to_read)
420 gtk_clist_freeze(GTK_CLIST(packet_list));
422 wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf, &err);
424 gtk_clist_thaw(GTK_CLIST(packet_list));
426 /* XXX - this cheats and looks inside the packet list to find the final
428 if (auto_scroll_live && cf->plist_end != NULL)
429 gtk_clist_moveto(GTK_CLIST(packet_list),
430 GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
435 finish_tail_cap_file(capture_file *cf)
439 gtk_clist_freeze(GTK_CLIST(packet_list));
441 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
444 if (auto_scroll_live && cf->plist_end != NULL)
445 /* XXX - this cheats and looks inside the packet list to find the final
447 gtk_clist_moveto(GTK_CLIST(packet_list),
448 GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
450 /* We're done reading sequentially through the file; close the
451 sequential I/O side, to free up memory it requires. */
452 wtap_sequential_close(cf->wth);
454 /* Set the file encapsulation type now; we don't know what it is until
455 we've looked at all the packets, as we don't know until then whether
456 there's more than one type (and thus whether it's
457 WTAP_ENCAP_PER_PACKET). */
458 cf->lnk_t = wtap_file_encap(cf->wth);
460 /* Pop the "<live capture in progress>" message off the status bar. */
461 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
463 set_display_filename(cf);
465 /* Enable menu items that make sense if you're not currently running
467 set_menus_for_capture_in_progress(FALSE);
469 /* Enable menu items that make sense if you have a capture file
470 you've finished reading. */
471 set_menus_for_capture_file(TRUE);
472 set_menus_for_unsaved_capture_file(!cf->user_saved);
476 #endif /* HAVE_LIBPCAP */
479 color_filter_t *colorf;
480 proto_tree *protocol_tree;
483 } apply_color_filter_args;
486 * If no color filter has been applied, apply this one.
487 * (The "if no color filter has been applied" is to handle the case where
488 * more than one color filter matches the packet.)
491 apply_color_filter(gpointer filter_arg, gpointer argp)
493 color_filter_t *colorf = filter_arg;
494 apply_color_filter_args *args = argp;
496 if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
497 if (dfilter_apply(colorf->c_colorfilter, args->protocol_tree, args->pd, args->fdata->cap_len))
498 args->colorf = colorf;
503 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
504 union wtap_pseudo_header *pseudo_header, const u_char *buf)
506 apply_color_filter_args args;
508 proto_tree *protocol_tree = NULL;
510 /* We don't yet have a color filter to apply. */
513 /* If we don't have the time stamp of the first packet in the
514 capture, it's because this is the first packet. Save the time
515 stamp of this packet as the time stamp of the first packet. */
516 if (!firstsec && !firstusec) {
517 firstsec = fdata->abs_secs;
518 firstusec = fdata->abs_usecs;
521 /* Get the time elapsed between the first packet and this packet. */
522 cf->esec = fdata->abs_secs - firstsec;
523 if (firstusec <= fdata->abs_usecs) {
524 cf->eusec = fdata->abs_usecs - firstusec;
526 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
530 fdata->cinfo = &cf->cinfo;
531 for (i = 0; i < fdata->cinfo->num_cols; i++) {
532 fdata->cinfo->col_data[i][0] = '\0';
535 /* Apply the filters */
536 if (cf->dfcode != NULL || filter_list != NULL) {
537 protocol_tree = proto_tree_create_root();
538 dissect_packet(pseudo_header, buf, fdata, protocol_tree);
539 if (cf->dfcode != NULL)
540 fdata->flags.passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, buf, fdata->cap_len) ? 1 : 0;
542 fdata->flags.passed_dfilter = 1;
544 /* Apply color filters, if we have any. */
545 if (filter_list != NULL) {
546 args.protocol_tree = protocol_tree;
549 g_slist_foreach(filter_list, apply_color_filter, &args);
551 proto_tree_free(protocol_tree);
555 if (enabled_plugins_number > 0)
556 protocol_tree = proto_tree_create_root();
558 dissect_packet(pseudo_header, buf, fdata, protocol_tree);
559 fdata->flags.passed_dfilter = 1;
562 proto_tree_free(protocol_tree);
566 if (fdata->flags.passed_dfilter) {
567 /* This frame passed the display filter, so add it to the clist. */
569 /* If we don't have the time stamp of the previous displayed packet,
570 it's because this is the first displayed packet. Save the time
571 stamp of this packet as the time stamp of the previous displayed
573 if (!prevsec && !prevusec) {
574 prevsec = fdata->abs_secs;
575 prevusec = fdata->abs_usecs;
578 /* Get the time elapsed between the first packet and this packet. */
579 fdata->rel_secs = cf->esec;
580 fdata->rel_usecs = cf->eusec;
582 /* Get the time elapsed between the previous displayed packet and
584 fdata->del_secs = fdata->abs_secs - prevsec;
585 if (prevusec <= fdata->abs_usecs) {
586 fdata->del_usecs = fdata->abs_usecs - prevusec;
588 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
591 prevsec = fdata->abs_secs;
592 prevusec = fdata->abs_usecs;
594 fill_in_columns(fdata);
596 /* If we haven't yet seen the first frame, this is it.
598 XXX - we must do this before we add the row to the display,
599 as, if the display's GtkCList's selection mode is
600 GTK_SELECTION_BROWSE, when the first entry is added to it,
601 "select_packet()" will be called, and it will fetch the row
602 data for the 0th row, and will get a null pointer rather than
603 "fdata", as "gtk_clist_append()" won't yet have returned and
604 thus "gtk_clist_set_row_data()" won't yet have been called.
606 We thus need to leave behind bread crumbs so that
607 "select_packet()" can find this frame. See the comment
608 in "select_packet()". */
609 if (cf->first_displayed == NULL)
610 cf->first_displayed = fdata;
612 /* This is the last frame we've seen so far. */
613 cf->last_displayed = fdata;
615 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
616 gtk_clist_set_row_data(GTK_CLIST(packet_list), row, fdata);
618 if (filter_list != NULL && (args.colorf != NULL)) {
619 gtk_clist_set_background(GTK_CLIST(packet_list), row,
620 &args.colorf->bg_color);
621 gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
622 &args.colorf->fg_color);
624 gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
625 gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
628 /* This frame didn't pass the display filter, so it's not being added
629 to the clist, and thus has no row. */
637 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
638 union wtap_pseudo_header *pseudo_header, const u_char *buf)
641 capture_file *cf = (capture_file *) user;
643 proto_tree *protocol_tree;
644 frame_data *plist_end;
648 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
649 when we update it, we have to run the GTK+ main loop to get it
650 to repaint what's pending, and doing so may involve an "ioctl()"
651 to see if there's any pending input from an X server, and doing
652 that for every packet can be costly, especially on a big file.
654 Do so only if we were told to do so; when reading a capture file
655 being updated by a live capture, we don't do so (as we're not
656 "done" until the capture stops, so we don't know how close to
659 if (cf->update_progbar && offset >= cf->progbar_nextstep) {
660 file_pos = lseek(cf->filed, 0, SEEK_CUR);
661 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
662 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), prog_val);
663 cf->progbar_nextstep += cf->progbar_quantum;
664 while (gtk_events_pending())
665 gtk_main_iteration();
668 /* Allocate the next list entry, and add it to the list. */
669 fdata = g_mem_chunk_alloc(cf->plist_chunk);
674 fdata->pkt_len = phdr->len;
675 fdata->cap_len = phdr->caplen;
676 fdata->file_off = offset;
677 fdata->lnk_t = phdr->pkt_encap;
678 fdata->abs_secs = phdr->ts.tv_sec;
679 fdata->abs_usecs = phdr->ts.tv_usec;
680 fdata->flags.encoding = CHAR_ASCII;
681 fdata->flags.visited = 0;
686 protocol_tree = proto_tree_create_root();
687 dissect_packet(pseudo_header, buf, fdata, protocol_tree);
688 passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata->cap_len);
689 proto_tree_free(protocol_tree);
692 plist_end = cf->plist_end;
693 fdata->prev = plist_end;
694 if (plist_end != NULL)
695 plist_end->next = fdata;
698 cf->plist_end = fdata;
701 fdata->num = cf->count;
702 add_packet_to_packet_list(fdata, cf, pseudo_header, buf);
704 /* XXX - if we didn't have read filters, or if we could avoid
705 allocating the "frame_data" structure until we knew whether
706 the frame passed the read filter, we could use a G_ALLOC_ONLY
709 ...but, at least in one test I did, where I just made the chunk
710 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
711 seem to save a noticeable amount of time or space. */
712 g_mem_chunk_free(cf->plist_chunk, fdata);
717 filter_packets(capture_file *cf, gchar *dftext)
721 if (dftext == NULL) {
722 /* The new filter is an empty filter (i.e., display all packets). */
726 * We have a filter; try to compile it.
728 if (dfilter_compile(dftext, &dfcode) != 0) {
729 /* The attempt failed; report an error. */
730 simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
735 if (dfcode == NULL) {
736 /* Yes - free the filter text, and set it to null. */
742 /* We have a valid filter. Replace the current filter. */
743 if (cf->dfilter != NULL)
745 cf->dfilter = dftext;
746 if (cf->dfcode != NULL)
747 dfilter_destroy(cf->dfcode);
750 /* Now go through the list of packets we've read from the capture file,
751 applying the current display filter, and, if the packet passes the
752 display filter, add it to the summary display, appropriately
753 colored. (That's how we colorize the display - it's like filtering
754 the display, only we don't install a new filter.) */
755 colorize_packets(cf);
760 colorize_packets(capture_file *cf)
763 guint32 progbar_quantum;
764 guint32 progbar_nextstep;
766 frame_data *selected_frame;
770 /* Which frame, if any, is the currently selected frame?
771 XXX - should the selected frame or the focus frame be the "current"
772 frame, that frame being the one from which "Find Frame" searches
774 selected_frame = cf->current_frame;
776 /* We don't yet know what row that frame will be on, if any, after we
777 rebuild the clist, however. */
780 /* We need to re-initialize all the state information that protocols
781 keep, because we're making a fresh pass through all the packets. */
783 /* Initialize the table of conversations. */
786 /* Initialize protocol-specific variables */
787 init_all_protocols();
789 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
791 /* Freeze the packet list while we redo it, so we don't get any
792 screen updates while it happens. */
793 gtk_clist_freeze(GTK_CLIST(packet_list));
796 gtk_clist_clear(GTK_CLIST(packet_list));
798 /* We don't yet know which will be the first and last frames displayed. */
799 cf->first_displayed = NULL;
800 cf->last_displayed = NULL;
802 /* Iterate through the list of packets, calling a routine
803 to run the filter on the packet, see if it matches, and
804 put it in the display list if so. */
810 /* Update the progress bar when it gets to this value. */
811 progbar_nextstep = 0;
812 /* When we reach the value that triggers a progress bar update,
813 bump that value by this amount. */
814 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
815 /* Count of packets at which we've looked. */
818 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
820 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
821 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
822 when we update it, we have to run the GTK+ main loop to get it
823 to repaint what's pending, and doing so may involve an "ioctl()"
824 to see if there's any pending input from an X server, and doing
825 that for every packet can be costly, especially on a big file. */
826 if (count >= progbar_nextstep) {
827 /* let's not divide by zero. I should never be started
828 * with count == 0, so let's assert that
830 g_assert(cf->count > 0);
832 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
833 (gfloat) count / cf->count);
835 progbar_nextstep += progbar_quantum;
836 while (gtk_events_pending())
837 gtk_main_iteration();
842 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
843 cf->pd, fdata->cap_len);
845 row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd);
846 if (fdata == selected_frame)
850 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
852 /* Unfreeze the packet list. */
853 gtk_clist_thaw(GTK_CLIST(packet_list));
855 if (selected_row != -1) {
856 /* The frame that was selected passed the filter; select it, make it
857 the focus row, and make it visible. */
858 set_selected_row(selected_row);
859 finfo_selected = NULL;
861 /* The selected frame didn't pass the filter; make the first frame
862 the current frame, and leave it unselected. */
864 cf->current_frame = cf->first_displayed;
869 print_packets(capture_file *cf, print_args_t *print_args)
873 guint32 progbar_quantum;
874 guint32 progbar_nextstep;
876 proto_tree *protocol_tree;
877 gint *col_widths = NULL;
879 gboolean print_separator;
880 char *line_buf = NULL;
881 int line_buf_len = 256;
886 cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
887 if (cf->print_fh == NULL)
888 return FALSE; /* attempt to open destination failed */
890 print_preamble(cf->print_fh, print_args->format);
892 if (print_args->print_summary) {
893 /* We're printing packet summaries. Allocate the line buffer at
894 its initial length. */
895 line_buf = g_malloc(line_buf_len + 1);
897 /* Find the widths for each of the columns - maximum of the
898 width of the title and the width of the data - and print
899 the column titles. */
900 col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
903 for (i = 0; i < cf->cinfo.num_cols; i++) {
904 /* Don't pad the last column. */
905 if (i == cf->cinfo.num_cols - 1)
908 col_widths[i] = strlen(cf->cinfo.col_title[i]);
909 data_width = get_column_char_width(get_column_format(i));
910 if (data_width > col_widths[i])
911 col_widths[i] = data_width;
914 /* Find the length of the string for this column. */
915 column_len = strlen(cf->cinfo.col_title[i]);
916 if (col_widths[i] > column_len)
917 column_len = col_widths[i];
919 /* Make sure there's room in the line buffer for the column; if not,
920 double its length. */
921 line_len += column_len + 1; /* "+1" for space or \n */
922 if (line_len > line_buf_len) {
924 line_buf = g_realloc(line_buf, line_buf_len + 1);
927 /* Right-justify the packet number column. */
928 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
929 sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_title[i]);
931 sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
933 if (i == cf->cinfo.num_cols - 1)
939 print_line(cf->print_fh, print_args->format, line_buf);
942 print_separator = FALSE;
944 /* The protocol tree will be "visible", i.e., printed, only if we're
945 not printing a summary. */
946 proto_tree_is_visible = !print_args->print_summary;
948 /* Update the progress bar when it gets to this value. */
949 progbar_nextstep = 0;
950 /* When we reach the value that triggers a progress bar update,
951 bump that value by this amount. */
952 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
953 /* Count of packets at which we've looked. */
956 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
958 /* Iterate through the list of packets, printing the packets that
959 were selected by the current display filter. */
960 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
961 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
962 when we update it, we have to run the GTK+ main loop to get it
963 to repaint what's pending, and doing so may involve an "ioctl()"
964 to see if there's any pending input from an X server, and doing
965 that for every packet can be costly, especially on a big file. */
966 if (count >= progbar_nextstep) {
967 /* let's not divide by zero. I should never be started
968 * with count == 0, so let's assert that
970 g_assert(cf->count > 0);
972 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
973 (gfloat) count / cf->count);
974 progbar_nextstep += progbar_quantum;
975 while (gtk_events_pending())
976 gtk_main_iteration();
980 if (fdata->flags.passed_dfilter) {
981 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
982 cf->pd, fdata->cap_len);
983 if (print_args->print_summary) {
984 /* Fill in the column information, but don't bother creating
985 the logical protocol tree. */
986 fdata->cinfo = &cf->cinfo;
987 for (i = 0; i < fdata->cinfo->num_cols; i++) {
988 fdata->cinfo->col_data[i][0] = '\0';
990 dissect_packet(&cf->pseudo_header, cf->pd, fdata, NULL);
991 fill_in_columns(fdata);
994 for (i = 0; i < cf->cinfo.num_cols; i++) {
995 /* Find the length of the string for this column. */
996 column_len = strlen(cf->cinfo.col_data[i]);
997 if (col_widths[i] > column_len)
998 column_len = col_widths[i];
1000 /* Make sure there's room in the line buffer for the column; if not,
1001 double its length. */
1002 line_len += column_len + 1; /* "+1" for space or \n */
1003 if (line_len > line_buf_len) {
1005 line_buf = g_realloc(line_buf, line_buf_len + 1);
1008 /* Right-justify the packet number column. */
1009 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1010 sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_data[i]);
1012 sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
1014 if (i == cf->cinfo.num_cols - 1)
1020 print_line(cf->print_fh, print_args->format, line_buf);
1022 if (print_separator)
1023 print_line(cf->print_fh, print_args->format, "\n");
1025 /* Create the logical protocol tree. */
1026 protocol_tree = proto_tree_create_root();
1027 dissect_packet(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
1029 /* Print the information in that tree. */
1030 proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
1031 cf->pd, fdata, cf->print_fh);
1033 proto_tree_free(protocol_tree);
1035 if (print_args->print_hex) {
1036 /* Print the full packet data as hex. */
1037 print_hex_data(cf->print_fh, print_args->format, cf->pd,
1038 fdata->cap_len, fdata->flags.encoding);
1041 /* Print a blank line if we print anything after this. */
1042 print_separator = TRUE;
1047 if (col_widths != NULL)
1049 if (line_buf != NULL)
1052 print_finale(cf->print_fh, print_args->format);
1054 close_print_dest(print_args->to_file, cf->print_fh);
1056 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1058 cf->print_fh = NULL;
1060 proto_tree_is_visible = FALSE;
1065 /* Scan through the packet list and change all columns that use the
1066 "command-line-specified" time stamp format to use the current
1067 value of that format. */
1069 change_time_formats(capture_file *cf)
1076 /* Freeze the packet list while we redo it, so we don't get any
1077 screen updates while it happens. */
1080 /* Iterate through the list of packets, checking whether the packet
1081 is in a row of the summary list and, if so, whether there are
1082 any columns that show the time in the "command-line-specified"
1083 format and, if so, update that row. */
1084 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1085 /* Find what row this packet is in. */
1086 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1089 /* This packet is in the summary list, on row "row". */
1091 /* XXX - there really should be a way of checking "cf->cinfo" for this;
1092 the answer isn't going to change from packet to packet, so we should
1093 simply skip all the "change_time_formats()" work if we're not
1094 changing anything. */
1095 fdata->cinfo = &cf->cinfo;
1096 if (check_col(fdata, COL_CLS_TIME)) {
1097 /* There are columns that show the time in the "command-line-specified"
1098 format; update them. */
1099 for (i = 0; i < cf->cinfo.num_cols; i++) {
1100 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1101 /* This is one of the columns that shows the time in
1102 "command-line-specified" format; update it. */
1103 cf->cinfo.col_data[i][0] = '\0';
1104 col_set_cls_time(fdata, i);
1105 gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
1106 cf->cinfo.col_data[i]);
1113 /* Set the column widths of those columns that show the time in
1114 "command-line-specified" format. */
1115 pl_style = gtk_widget_get_style(packet_list);
1116 for (i = 0; i < cf->cinfo.num_cols; i++) {
1117 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1118 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1119 gdk_string_width(pl_style->font, get_column_longest_string(COL_CLS_TIME)));
1123 /* Unfreeze the packet list. */
1128 clear_tree_and_hex_views(void)
1130 /* Clear the hex dump. */
1131 gtk_text_freeze(GTK_TEXT(byte_view));
1132 gtk_text_set_point(GTK_TEXT(byte_view), 0);
1133 gtk_text_forward_delete(GTK_TEXT(byte_view),
1134 gtk_text_get_length(GTK_TEXT(byte_view)));
1135 gtk_text_thaw(GTK_TEXT(byte_view));
1137 /* Remove all nodes in ctree. This is how it's done in testgtk.c in GTK+ */
1138 gtk_clist_clear ( GTK_CLIST(tree_view) );
1143 find_packet(capture_file *cf, dfilter *sfcode)
1145 frame_data *start_fd;
1147 frame_data *new_fd = NULL;
1148 guint32 progbar_quantum;
1149 guint32 progbar_nextstep;
1151 proto_tree *protocol_tree;
1152 gboolean frame_matched;
1155 start_fd = cf->current_frame;
1156 if (start_fd != NULL) {
1157 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
1159 /* Iterate through the list of packets, starting at the packet we've
1160 picked, calling a routine to run the filter on the packet, see if
1161 it matches, and stop if so. */
1165 /* Update the progress bar when it gets to this value. */
1166 progbar_nextstep = 0;
1167 /* When we reach the value that triggers a progress bar update,
1168 bump that value by this amount. */
1169 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1170 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
1174 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1175 when we update it, we have to run the GTK+ main loop to get it
1176 to repaint what's pending, and doing so may involve an "ioctl()"
1177 to see if there's any pending input from an X server, and doing
1178 that for every packet can be costly, especially on a big file. */
1179 if (count >= progbar_nextstep) {
1180 /* let's not divide by zero. I should never be started
1181 * with count == 0, so let's assert that
1183 g_assert(cf->count > 0);
1185 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1186 (gfloat) count / cf->count);
1188 progbar_nextstep += progbar_quantum;
1189 while (gtk_events_pending())
1190 gtk_main_iteration();
1193 /* Go past the current frame. */
1194 if (cf->sbackward) {
1195 /* Go on to the previous frame. */
1196 fdata = fdata->prev;
1198 fdata = cf->plist_end; /* wrap around */
1200 /* Go on to the next frame. */
1201 fdata = fdata->next;
1203 fdata = cf->plist; /* wrap around */
1208 /* Is this packet in the display? */
1209 if (fdata->flags.passed_dfilter) {
1210 /* Yes. Does it match the search filter? */
1211 protocol_tree = proto_tree_create_root();
1212 wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
1213 cf->pd, fdata->cap_len);
1214 dissect_packet(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
1215 frame_matched = dfilter_apply(sfcode, protocol_tree, cf->pd, fdata->cap_len);
1216 proto_tree_free(protocol_tree);
1217 if (frame_matched) {
1219 break; /* found it! */
1223 if (fdata == start_fd) {
1224 /* We're back to the frame we were on originally, and that frame
1225 doesn't match the search filter. The search failed. */
1230 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1233 if (new_fd != NULL) {
1234 /* We found a frame. Find what row it's in. */
1235 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), new_fd);
1236 g_assert(row != -1);
1238 /* Select that row, make it the focus row, and make it visible. */
1239 set_selected_row(row);
1240 return TRUE; /* success */
1242 return FALSE; /* failure */
1246 goto_frame(capture_file *cf, guint fnumber)
1251 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
1255 return NO_SUCH_FRAME; /* we didn't find that frame */
1256 if (!fdata->flags.passed_dfilter)
1257 return FRAME_NOT_DISPLAYED; /* the frame with that number isn't displayed */
1259 /* We found that frame, and it's currently being displayed.
1260 Find what row it's in. */
1261 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata);
1262 g_assert(row != -1);
1264 /* Select that row, make it the focus row, and make it visible. */
1265 set_selected_row(row);
1269 /* Select the packet on a given row. */
1271 select_packet(capture_file *cf, int row)
1275 /* Get the frame data struct pointer for this frame */
1276 fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
1278 if (fdata == NULL) {
1279 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
1280 the first entry is added to it by "real_insert_row()", that row
1281 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
1282 our version and the vanilla GTK+ version).
1284 This means that a "select-row" signal is emitted; this causes
1285 "packet_list_select_cb()" to be called, which causes "select_packet()"
1288 "select_packet()" fetches, above, the data associated with the
1289 row that was selected; however, as "gtk_clist_append()", which
1290 called "real_insert_row()", hasn't yet returned, we haven't yet
1291 associated any data with that row, so we get back a null pointer.
1293 We can't assume that there's only one frame in the frame list,
1294 either, as we may be filtering the display.
1296 We therefore assume that, if "row" is 0, i.e. the first row
1297 is being selected, and "cf->first_displayed" equals
1298 "cf->last_displayed", i.e. there's only one frame being
1299 displayed, that frame is the frame we want.
1301 This means we have to set "cf->first_displayed" and
1302 "cf->last_displayed" before adding the row to the
1303 GtkCList; see the comment in "add_packet_to_packet_list()". */
1305 if (row == 0 && cf->first_displayed == cf->last_displayed)
1306 fdata = cf->first_displayed;
1309 /* Record that this frame is the current frame. */
1310 cf->current_frame = fdata;
1312 /* Get the data in that frame. */
1313 wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1314 cf->pd, fdata->cap_len);
1316 /* Create the logical protocol tree. */
1317 if (cf->protocol_tree)
1318 proto_tree_free(cf->protocol_tree);
1319 cf->protocol_tree = proto_tree_create_root();
1320 proto_tree_is_visible = TRUE;
1321 dissect_packet(&cf->pseudo_header, cf->pd, cf->current_frame,
1323 proto_tree_is_visible = FALSE;
1325 /* Display the GUI protocol tree and hex dump. */
1326 clear_tree_and_hex_views();
1327 proto_tree_draw(cf->protocol_tree, tree_view);
1328 packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->current_frame->cap_len,
1329 -1, -1, cf->current_frame->flags.encoding);
1331 /* A packet is selected. */
1332 set_menus_for_selected_packet(TRUE);
1335 /* Unselect the selected packet, if any. */
1337 unselect_packet(capture_file *cf)
1339 /* Destroy the protocol tree for that packet. */
1340 if (cf->protocol_tree != NULL) {
1341 proto_tree_free(cf->protocol_tree);
1342 cf->protocol_tree = NULL;
1345 finfo_selected = NULL;
1347 /* Clear out the display of that packet. */
1348 clear_tree_and_hex_views();
1350 /* No packet is selected. */
1351 set_menus_for_selected_packet(FALSE);
1354 /* Set the selected row and the focus row of the packet list to the specified
1355 row, and make it visible if it's not currently visible. */
1357 set_selected_row(int row)
1359 if (gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) != GTK_VISIBILITY_FULL)
1360 gtk_clist_moveto(GTK_CLIST(packet_list), row, -1, 0.0, 0.0);
1362 /* XXX - why is there no "gtk_clist_set_focus_row()", so that we
1363 can make the row for the frame we found the focus row?
1367 http://www.gnome.org/mailing-lists/archives/gtk-list/2000-January/0038.shtml
1370 GTK_CLIST(packet_list)->focus_row = row;
1372 gtk_clist_select_row(GTK_CLIST(packet_list), row, -1);
1376 freeze_clist(capture_file *cf)
1380 /* Make the column sizes static, so they don't adjust while
1381 we're reading the capture file (freezing the clist doesn't
1382 seem to suffice). */
1383 for (i = 0; i < cf->cinfo.num_cols; i++)
1384 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1385 gtk_clist_freeze(GTK_CLIST(packet_list));
1389 thaw_clist(capture_file *cf)
1393 for (i = 0; i < cf->cinfo.num_cols; i++) {
1394 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1395 /* Set this column's width to the appropriate value. */
1396 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1397 cf->cinfo.col_width[i]);
1399 /* Make this column's size dynamic, so that it adjusts to the
1400 appropriate size. */
1401 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1404 gtk_clist_thaw(GTK_CLIST(packet_list));
1406 /* Hopefully, the columns have now gotten their appropriate sizes;
1407 make them resizeable - a column that auto-resizes cannot be
1408 resized by the user, and *vice versa*. */
1409 for (i = 0; i < cf->cinfo.num_cols; i++)
1410 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1414 save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
1417 gchar *from_filename;
1418 gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
1422 int from_fd, to_fd, nread, nwritten;
1425 struct wtap_pkthdr hdr;
1426 union wtap_pseudo_header pseudo_header;
1429 name_ptr = get_basename(fname);
1430 msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
1431 save_msg = g_malloc(msg_len);
1432 snprintf(save_msg, msg_len, save_fmt, name_ptr);
1433 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
1436 if (!save_filtered && save_format == cf->cd_t) {
1437 /* We're not filtering packets, and we're saving it in the format
1438 it's already in, so we can just move or copy the raw data. */
1440 /* In this branch, we set "err" only if we get an error, so we
1441 must first clear it. */
1443 if (cf->is_tempfile) {
1444 /* The file being saved is a temporary file from a live
1445 capture, so it doesn't need to stay around under that name;
1446 first, try renaming the capture buffer file to the new name. */
1448 if (rename(cf->filename, fname) == 0) {
1449 /* That succeeded - there's no need to copy the source file. */
1450 from_filename = NULL;
1453 if (errno == EXDEV) {
1454 /* They're on different file systems, so we have to copy the
1457 from_filename = cf->filename;
1459 /* The rename failed, but not because they're on different
1460 file systems - put up an error message. (Or should we
1461 just punt and try to copy? The only reason why I'd
1462 expect the rename to fail and the copy to succeed would
1463 be if we didn't have permission to remove the file from
1464 the temporary directory, and that might be fixable - but
1465 is it worth requiring the user to go off and fix it?) */
1467 simple_dialog(ESD_TYPE_WARN, NULL,
1468 file_rename_error_message(err), fname);
1474 from_filename = cf->filename;
1477 /* It's a permanent file, so we should copy it, and not remove the
1480 from_filename = cf->filename;
1482 /* Copy the file, if we haven't moved it. */
1484 /* Copy the raw bytes of the file. */
1485 from_fd = open(from_filename, O_RDONLY | O_BINARY);
1488 simple_dialog(ESD_TYPE_WARN, NULL,
1489 file_open_error_message(err, TRUE), from_filename);
1493 /* Use open() instead of creat() so that we can pass the O_BINARY
1494 flag, which is relevant on Win32; it appears that "creat()"
1495 may open the file in text mode, not binary mode, but we want
1496 to copy the raw bytes of the file, so we need the output file
1497 to be open in binary mode. */
1498 to_fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1501 simple_dialog(ESD_TYPE_WARN, NULL,
1502 file_open_error_message(err, TRUE), fname);
1507 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
1508 nwritten = write(to_fd, pd, nread);
1509 if (nwritten < nread) {
1513 err = WTAP_ERR_SHORT_WRITE;
1514 simple_dialog(ESD_TYPE_WARN, NULL,
1515 file_write_error_message(err), fname);
1523 simple_dialog(ESD_TYPE_WARN, NULL,
1524 file_read_error_message(err), from_filename);
1530 if (close(to_fd) < 0) {
1532 simple_dialog(ESD_TYPE_WARN, NULL,
1533 file_close_error_message(err), fname);
1538 /* Either we're filtering packets, or we're saving in a different
1539 format; we can't do that by copying or moving the capture file,
1540 we have to do it by writing the packets out in Wiretap. */
1541 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
1543 simple_dialog(ESD_TYPE_WARN, NULL,
1544 file_open_error_message(err, TRUE), fname);
1548 /* XXX - have a way to save only the packets currently selected by
1551 If we do that, should we make that file the current file? If so,
1552 it means we can no longer get at the other packets. What does
1554 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1555 /* XXX - do a progress bar */
1556 if (!save_filtered || fdata->flags.passed_dfilter) {
1557 /* Either we're saving all frames, or we're saving filtered frames
1558 and this one passed the display filter - save it. */
1559 hdr.ts.tv_sec = fdata->abs_secs;
1560 hdr.ts.tv_usec = fdata->abs_usecs;
1561 hdr.caplen = fdata->cap_len;
1562 hdr.len = fdata->pkt_len;
1563 hdr.pkt_encap = fdata->lnk_t;
1564 wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1565 pd, fdata->cap_len);
1567 if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
1568 simple_dialog(ESD_TYPE_WARN, NULL,
1569 file_write_error_message(err), fname);
1570 wtap_dump_close(pdh, &err);
1576 if (!wtap_dump_close(pdh, &err)) {
1577 simple_dialog(ESD_TYPE_WARN, NULL,
1578 file_close_error_message(err), fname);
1585 /* Pop the "Saving:" message off the status bar. */
1586 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
1588 if (!save_filtered) {
1589 /* We saved the entire capture, not just some packets from it.
1590 Open and read the file we saved it to.
1592 XXX - this is somewhat of a waste; we already have the
1593 packets, all this gets us is updated file type information
1594 (which we could just stuff into "cf"), and having the new
1595 file be the one we have opened and from which we're reading
1596 the data, and it means we have to spend time opening and
1597 reading the file, which could be a significant amount of
1598 time if the file is large. */
1599 cf->user_saved = TRUE;
1601 if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
1602 /* XXX - report errors if this fails? */
1603 err = read_cap_file(cf);
1604 set_menus_for_unsaved_capture_file(FALSE);
1612 file_open_error_message(int err, int for_writing)
1615 static char errmsg_errno[1024+1];
1619 case WTAP_ERR_NOT_REGULAR_FILE:
1620 errmsg = "The file \"%s\" is invalid.";
1623 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1624 case WTAP_ERR_UNSUPPORTED:
1625 /* Seen only when opening a capture file for reading. */
1626 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1629 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1630 /* Seen only when opening a capture file for writing. */
1631 errmsg = "Ethereal does not support writing capture files in that format.";
1634 case WTAP_ERR_UNSUPPORTED_ENCAP:
1635 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1637 errmsg = "Ethereal cannot save this capture in that format.";
1639 errmsg = "The file \"%s\" is a capture for a network type that Ethereal doesn't support.";
1642 case WTAP_ERR_BAD_RECORD:
1643 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1646 case WTAP_ERR_CANT_OPEN:
1648 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1650 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1653 case WTAP_ERR_SHORT_READ:
1654 errmsg = "The file \"%s\" appears to have been cut short"
1655 " in the middle of a packet.";
1658 case WTAP_ERR_SHORT_WRITE:
1659 errmsg = "A full header couldn't be written to the file \"%s\".";
1664 errmsg = "The path to the file \"%s\" does not exist.";
1666 errmsg = "The file \"%s\" does not exist.";
1671 errmsg = "You do not have permission to create or write to the file \"%s\".";
1673 errmsg = "You do not have permission to read the file \"%s\".";
1677 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
1678 wtap_strerror(err));
1679 errmsg = errmsg_errno;
1686 file_rename_error_message(int err)
1689 static char errmsg_errno[1024+1];
1694 errmsg = "The path to the file \"%s\" does not exist.";
1698 errmsg = "You do not have permission to move the capture file to \"%s\".";
1702 sprintf(errmsg_errno, "The file \"%%s\" could not be moved: %s.",
1703 wtap_strerror(err));
1704 errmsg = errmsg_errno;
1711 file_read_error_message(int err)
1713 static char errmsg_errno[1024+1];
1715 sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.",
1716 wtap_strerror(err));
1717 return errmsg_errno;
1721 file_write_error_message(int err)
1724 static char errmsg_errno[1024+1];
1729 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1734 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1739 sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.",
1740 wtap_strerror(err));
1741 errmsg = errmsg_errno;
1747 /* Check for write errors - if the file is being written to an NFS server,
1748 a write error may not show up until the file is closed, as NFS clients
1749 might not send writes to the server until the "write()" call finishes,
1750 so that the write may fail on the server but the "write()" may succeed. */
1752 file_close_error_message(int err)
1755 static char errmsg_errno[1024+1];
1759 case WTAP_ERR_CANT_CLOSE:
1760 errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
1763 case WTAP_ERR_SHORT_WRITE:
1764 errmsg = "Not all the data could be written to the file \"%s\".";
1768 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1773 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1778 sprintf(errmsg_errno, "An error occurred while closing the file \"%%s\": %s.",
1779 wtap_strerror(err));
1780 errmsg = errmsg_errno;