4 * $Id: file.c,v 1.173 2000/03/28 08:11:43 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,
99 static void freeze_clist(capture_file *cf);
100 static void thaw_clist(capture_file *cf);
102 static char *file_rename_error_message(int err);
103 static char *file_close_error_message(int err);
105 /* Update the progress bar this many times when reading a file. */
106 #define N_PROGBAR_UPDATES 100
109 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
117 wth = wtap_open_offline(fname, &err);
121 /* Find the size of the file. */
124 if (fstat(fd, &cf_stat) < 0) {
130 /* The open succeeded. Close whatever capture file we had open,
131 and fill in the information for this file. */
132 close_cap_file(cf, info_bar);
134 /* Initialize the table of conversations. */
137 /* Initialize protocol-specific variables */
138 init_all_protocols();
143 cf->f_len = cf_stat.st_size;
145 /* Set the file name because we need it to set the follow stream filter.
146 XXX - is that still true? We need it for other reasons, though,
148 cf->filename = g_strdup(fname);
150 /* Indicate whether it's a permanent or temporary file. */
151 cf->is_tempfile = is_tempfile;
153 /* If it's a temporary capture buffer file, mark it as not saved. */
154 cf->user_saved = !is_tempfile;
156 cf->cd_t = wtap_file_type(cf->wth);
161 cf->snap = wtap_snapshot_length(cf->wth);
162 cf->update_progbar = FALSE;
163 cf->progbar_quantum = 0;
164 cf->progbar_nextstep = 0;
165 firstsec = 0, firstusec = 0;
166 prevsec = 0, prevusec = 0;
171 simple_dialog(ESD_TYPE_WARN, NULL,
172 file_open_error_message(err, FALSE), fname);
176 /* Reset everything to a pristine state */
178 close_cap_file(capture_file *cf, void *w)
180 frame_data *fd, *fd_next;
182 /* Destroy all popup packet windows, as they refer to packets in the
183 capture file we're closing. */
184 destroy_packet_wins();
194 /* We have no file open... */
195 if (cf->filename != NULL) {
196 /* If it's a temporary file, remove it. */
198 unlink(cf->filename);
199 g_free(cf->filename);
202 /* ...which means we have nothing to save. */
203 cf->user_saved = FALSE;
205 for (fd = cf->plist; fd != NULL; fd = fd_next) {
209 if (cf->rfcode != NULL) {
210 dfilter_destroy(cf->rfcode);
214 cf->plist_end = NULL;
215 unselect_packet(cf); /* nothing to select */
216 cf->first_displayed = NULL;
217 cf->last_displayed = NULL;
219 /* Clear the packet list. */
220 gtk_clist_freeze(GTK_CLIST(packet_list));
221 gtk_clist_clear(GTK_CLIST(packet_list));
222 gtk_clist_thaw(GTK_CLIST(packet_list));
224 /* Clear any file-related status bar messages.
225 XXX - should be "clear *ALL* file-related status bar messages;
226 will there ever be more than one on the stack? */
227 gtk_statusbar_pop(GTK_STATUSBAR(w), file_ctx);
229 /* Restore the standard title bar message. */
230 set_main_window_name("The Ethereal Network Analyzer");
232 /* Disable all menu items that make sense only if you have a capture. */
233 set_menus_for_capture_file(FALSE);
234 set_menus_for_unsaved_capture_file(FALSE);
235 set_menus_for_captured_packets(FALSE);
236 set_menus_for_selected_packet(FALSE);
237 set_menus_for_capture_in_progress(FALSE);
240 /* Set the file name in the status line, in the name for the main window,
241 and in the name for the main window's icon. */
243 set_display_filename(capture_file *cf)
247 gchar *done_fmt = " File: %s Drops: %u";
249 gchar *win_name_fmt = "%s - Ethereal";
252 if (!cf->is_tempfile) {
253 /* Get the last component of the file name, and put that in the
255 name_ptr = get_basename(cf->filename);
257 /* The file we read is a temporary file from a live capture;
258 we don't mention its name in the status bar. */
259 name_ptr = "<capture>";
262 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
263 done_msg = g_malloc(msg_len);
264 snprintf(done_msg, msg_len, done_fmt, name_ptr, cf->drops);
265 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
268 msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
269 win_name = g_malloc(msg_len);
270 snprintf(win_name, msg_len, win_name_fmt, name_ptr);
271 set_main_window_name(win_name);
276 read_cap_file(capture_file *cf)
278 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
283 char errmsg_errno[1024+1];
284 gchar err_str[2048+1];
286 name_ptr = get_basename(cf->filename);
288 msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
289 load_msg = g_malloc(msg_len);
290 snprintf(load_msg, msg_len, load_fmt, name_ptr);
291 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
294 cf->update_progbar = TRUE;
295 /* Update the progress bar when it gets to this value. */
296 cf->progbar_nextstep = 0;
297 /* When we reach the value that triggers a progress bar update,
298 bump that value by this amount. */
299 cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
306 proto_tree_is_visible = FALSE;
307 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
308 /* Set the file encapsulation type now; we don't know what it is until
309 we've looked at all the packets, as we don't know until then whether
310 there's more than one type (and thus whether it's
311 WTAP_ENCAP_PER_PACKET). */
312 cf->lnk_t = wtap_file_encap(cf->wth);
315 cf->filed = open(cf->filename, O_RDONLY|O_BINARY);
316 cf->fh = filed_open(cf->filed, "rb");
317 cf->current_frame = cf->first_displayed;
320 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
321 gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
323 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
324 set_display_filename(cf);
326 /* Enable menu items that make sense if you have a capture file you've
328 set_menus_for_capture_file(TRUE);
329 set_menus_for_unsaved_capture_file(!cf->user_saved);
331 /* Enable menu items that make sense if you have some captured packets. */
332 set_menus_for_captured_packets(TRUE);
334 /* If we have any displayed packets to select, select the first of those
335 packets by making the first row the selected row. */
336 if (cf->first_displayed != NULL)
337 gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
340 /* Put up a message box noting that the read failed somewhere along
341 the line. Don't throw out the stuff we managed to read, though,
345 case WTAP_ERR_UNSUPPORTED_ENCAP:
346 errmsg = "The capture file is for a network type that Ethereal doesn't support.";
349 case WTAP_ERR_CANT_READ:
350 errmsg = "An attempt to read from the file failed for"
351 " some unknown reason.";
354 case WTAP_ERR_SHORT_READ:
355 errmsg = "The capture file appears to have been cut short"
356 " in the middle of a packet.";
359 case WTAP_ERR_BAD_RECORD:
360 errmsg = "The capture file appears to be damaged or corrupt.";
364 sprintf(errmsg_errno, "An error occurred while reading the"
365 " capture file: %s.", wtap_strerror(err));
366 errmsg = errmsg_errno;
369 snprintf(err_str, sizeof err_str, errmsg);
370 simple_dialog(ESD_TYPE_WARN, NULL, err_str);
378 start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
383 err = open_cap_file(fname, is_tempfile, cf);
385 /* Disable menu items that make no sense if you're currently running
387 set_menus_for_capture_in_progress(TRUE);
389 /* Enable menu items that make sense if you have some captured
390 packets (yes, I know, we don't have any *yet*). */
391 set_menus_for_captured_packets(TRUE);
393 for (i = 0; i < cf->cinfo.num_cols; i++) {
394 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
395 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
397 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
398 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
399 cf->cinfo.col_width[i]);
400 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
404 /* Yes, "open_cap_file()" set this - but it set it to a file handle
405 from Wiretap, which will be closed when we close the file; we
406 want it to remain open even after that, so that we can read
407 packet data from it. */
408 cf->fh = file_open(fname, "rb");
410 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
411 " <live capture in progress>");
417 continue_tail_cap_file(capture_file *cf, int to_read)
421 gtk_clist_freeze(GTK_CLIST(packet_list));
423 wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf, &err);
425 gtk_clist_thaw(GTK_CLIST(packet_list));
427 /* XXX - this cheats and looks inside the packet list to find the final
429 if (auto_scroll_live && cf->plist_end != NULL)
430 gtk_clist_moveto(GTK_CLIST(packet_list),
431 GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
436 finish_tail_cap_file(capture_file *cf)
440 gtk_clist_freeze(GTK_CLIST(packet_list));
442 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
445 if (auto_scroll_live && cf->plist_end != NULL)
446 /* XXX - this cheats and looks inside the packet list to find the final
448 gtk_clist_moveto(GTK_CLIST(packet_list),
449 GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
451 /* Set the file encapsulation type now; we don't know what it is until
452 we've looked at all the packets, as we don't know until then whether
453 there's more than one type (and thus whether it's
454 WTAP_ENCAP_PER_PACKET). */
455 cf->lnk_t = wtap_file_encap(cf->wth);
457 /* There's nothing more to read from the capture file - close it. */
461 /* Pop the "<live capture in progress>" message off the status bar. */
462 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
464 set_display_filename(cf);
466 /* Enable menu items that make sense if you're not currently running
468 set_menus_for_capture_in_progress(FALSE);
470 /* Enable menu items that make sense if you have a capture file
471 you've finished reading. */
472 set_menus_for_capture_file(TRUE);
473 set_menus_for_unsaved_capture_file(!cf->user_saved);
477 #endif /* HAVE_LIBPCAP */
480 color_filter_t *colorf;
481 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))
498 args->colorf = colorf;
503 add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf)
505 apply_color_filter_args args;
507 proto_tree *protocol_tree = NULL;
509 /* We don't yet have a color filter to apply. */
512 /* If we don't have the time stamp of the first packet in the
513 capture, it's because this is the first packet. Save the time
514 stamp of this packet as the time stamp of the first packet. */
515 if (!firstsec && !firstusec) {
516 firstsec = fdata->abs_secs;
517 firstusec = fdata->abs_usecs;
520 /* Get the time elapsed between the first packet and this packet. */
521 cf->esec = fdata->abs_secs - firstsec;
522 if (firstusec <= fdata->abs_usecs) {
523 cf->eusec = fdata->abs_usecs - firstusec;
525 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
529 fdata->cinfo = &cf->cinfo;
530 for (i = 0; i < fdata->cinfo->num_cols; i++) {
531 fdata->cinfo->col_data[i][0] = '\0';
534 /* Apply the filters */
535 if (cf->dfcode != NULL || filter_list != NULL) {
536 protocol_tree = proto_tree_create_root();
537 dissect_packet(buf, fdata, protocol_tree);
538 if (cf->dfcode != NULL)
539 fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, buf);
541 fdata->passed_dfilter = TRUE;
543 /* Apply color filters, if we have any. */
544 if (filter_list != NULL) {
545 args.protocol_tree = protocol_tree;
547 g_slist_foreach(filter_list, apply_color_filter, &args);
549 proto_tree_free(protocol_tree);
554 protocol_tree = proto_tree_create_root();
556 dissect_packet(buf, fdata, protocol_tree);
557 fdata->passed_dfilter = TRUE;
560 proto_tree_free(protocol_tree);
564 if (fdata->passed_dfilter) {
565 /* If we don't have the time stamp of the previous displayed packet,
566 it's because this is the first displayed packet. Save the time
567 stamp of this packet as the time stamp of the previous displayed
569 if (!prevsec && !prevusec) {
570 prevsec = fdata->abs_secs;
571 prevusec = fdata->abs_usecs;
574 /* Get the time elapsed between the first packet and this packet. */
575 fdata->rel_secs = cf->esec;
576 fdata->rel_usecs = cf->eusec;
578 /* Get the time elapsed between the previous displayed packet and
580 fdata->del_secs = fdata->abs_secs - prevsec;
581 if (prevusec <= fdata->abs_usecs) {
582 fdata->del_usecs = fdata->abs_usecs - prevusec;
584 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
587 prevsec = fdata->abs_secs;
588 prevusec = fdata->abs_usecs;
590 fill_in_columns(fdata);
592 /* If we haven't yet seen the first frame, this is it.
594 XXX - we must do this before we add the row to the display,
595 as, if the display's GtkCList's selection mode is
596 GTK_SELECTION_BROWSE, when the first entry is added to it,
597 "select_packet()" will be called, and it will fetch the row
598 data for the 0th row, and will get a null pointer rather than
599 "fdata", as "gtk_clist_append()" won't yet have returned and
600 thus "gtk_clist_set_row_data()" won't yet have been called.
602 We thus need to leave behind bread crumbs so that
603 "select_packet()" can find this frame. See the comment
604 in "select_packet()". */
605 if (cf->first_displayed == NULL)
606 cf->first_displayed = fdata;
608 /* This is the last frame we've seen so far. */
609 cf->last_displayed = fdata;
611 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
612 gtk_clist_set_row_data(GTK_CLIST(packet_list), row, fdata);
614 /* If this was the current frame, remember the row it's in, so
615 we can arrange that it's on the screen when we're done. */
616 if (cf->current_frame == fdata)
617 cf->current_row = row;
619 if (filter_list != NULL && (args.colorf != NULL)) {
620 gtk_clist_set_background(GTK_CLIST(packet_list), row,
621 &args.colorf->bg_color);
622 gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
623 &args.colorf->fg_color);
625 gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
626 gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
633 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
636 capture_file *cf = (capture_file *) user;
638 proto_tree *protocol_tree;
639 frame_data *plist_end;
643 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
644 when we update it, we have to run the GTK+ main loop to get it
645 to repaint what's pending, and doing so may involve an "ioctl()"
646 to see if there's any pending input from an X server, and doing
647 that for every packet can be costly, especially on a big file.
649 Do so only if we were told to do so; when reading a capture file
650 being updated by a live capture, we don't do so (as we're not
651 "done" until the capture stops, so we don't know how close to
654 if (cf->update_progbar && offset >= cf->progbar_nextstep) {
655 file_pos = lseek(cf->filed, 0, SEEK_CUR);
656 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
657 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), prog_val);
658 cf->progbar_nextstep += cf->progbar_quantum;
659 while (gtk_events_pending())
660 gtk_main_iteration();
663 /* Allocate the next list entry, and add it to the list. */
664 fdata = (frame_data *) g_malloc(sizeof(frame_data));
669 fdata->pkt_len = phdr->len;
670 fdata->cap_len = phdr->caplen;
671 fdata->file_off = offset;
672 fdata->lnk_t = phdr->pkt_encap;
673 fdata->abs_secs = phdr->ts.tv_sec;
674 fdata->abs_usecs = phdr->ts.tv_usec;
675 fdata->encoding = CHAR_ASCII;
676 fdata->pseudo_header = phdr->pseudo_header;
681 protocol_tree = proto_tree_create_root();
682 dissect_packet(buf, fdata, protocol_tree);
683 passed = dfilter_apply(cf->rfcode, protocol_tree, buf);
684 proto_tree_free(protocol_tree);
687 plist_end = cf->plist_end;
688 fdata->prev = plist_end;
689 if (plist_end != NULL)
690 plist_end->next = fdata;
693 cf->plist_end = fdata;
696 fdata->num = cf->count;
697 add_packet_to_packet_list(fdata, cf, buf);
703 filter_packets(capture_file *cf, gchar *dftext)
707 if (dftext == NULL) {
708 /* The new filter is an empty filter (i.e., display all packets). */
712 * We have a filter; try to compile it.
714 if (dfilter_compile(dftext, &dfcode) != 0) {
715 /* The attempt failed; report an error. */
716 simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
721 if (dfcode == NULL) {
722 /* Yes - free the filter text, and set it to null. */
728 /* We have a valid filter. Replace the current filter. */
729 if (cf->dfilter != NULL)
731 cf->dfilter = dftext;
732 if (cf->dfcode != NULL)
733 dfilter_destroy(cf->dfcode);
736 /* Now go through the list of packets we've read from the capture file,
737 applying the current display filter, and, if the packet passes the
738 display filter, add it to the summary display, appropriately
739 colored. (That's how we colorize the display - it's like filtering
740 the display, only we don't install a new filter.) */
741 colorize_packets(cf);
746 colorize_packets(capture_file *cf)
749 guint32 progbar_quantum;
750 guint32 progbar_nextstep;
753 /* We need to re-initialize all the state information that protocols
754 keep, because we're making a fresh pass through all the packets. */
756 /* Initialize the table of conversations. */
759 /* Initialize protocol-specific variables */
760 init_all_protocols();
762 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
764 /* Freeze the packet list while we redo it, so we don't get any
765 screen updates while it happens. */
766 gtk_clist_freeze(GTK_CLIST(packet_list));
769 gtk_clist_clear(GTK_CLIST(packet_list));
771 /* We don't yet know which will be the first and last frames displayed. */
772 cf->first_displayed = NULL;
773 cf->last_displayed = NULL;
775 /* If a packet was selected, we don't know yet what row, if any, it'll
777 cf->current_row = -1;
779 /* Iterate through the list of packets, calling a routine
780 to run the filter on the packet, see if it matches, and
781 put it in the display list if so. */
787 proto_tree_is_visible = FALSE;
789 /* Update the progress bar when it gets to this value. */
790 progbar_nextstep = 0;
791 /* When we reach the value that triggers a progress bar update,
792 bump that value by this amount. */
793 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
794 /* Count of packets at which we've looked. */
797 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
799 for (fd = cf->plist; fd != NULL; fd = fd->next) {
800 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
801 when we update it, we have to run the GTK+ main loop to get it
802 to repaint what's pending, and doing so may involve an "ioctl()"
803 to see if there's any pending input from an X server, and doing
804 that for every packet can be costly, especially on a big file. */
805 if (count >= progbar_nextstep) {
806 /* let's not divide by zero. I should never be started
807 * with count == 0, so let's assert that
809 g_assert(cf->count > 0);
811 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
812 (gfloat) count / cf->count);
814 progbar_nextstep += progbar_quantum;
815 while (gtk_events_pending())
816 gtk_main_iteration();
821 wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
823 add_packet_to_packet_list(fd, cf, cf->pd);
826 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
828 if (cf->current_row != -1) {
829 /* The current frame passed the filter; make sure it's visible. */
830 if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), cf->current_row))
831 gtk_clist_moveto(GTK_CLIST(packet_list), cf->current_row, -1, 0.0, 0.0);
832 if (cf->current_frame_is_selected) {
833 /* It was selected, so re-select it. */
834 gtk_clist_select_row(GTK_CLIST(packet_list), cf->current_row, -1);
836 finfo_selected = NULL;
838 /* The current frame didn't pass the filter; make the first frame
839 the current frame, and leave it unselected. */
841 cf->current_frame = cf->first_displayed;
844 /* Unfreeze the packet list. */
845 gtk_clist_thaw(GTK_CLIST(packet_list));
849 print_packets(capture_file *cf, print_args_t *print_args)
853 guint32 progbar_quantum;
854 guint32 progbar_nextstep;
856 proto_tree *protocol_tree;
857 gint *col_widths = NULL;
859 gboolean print_separator;
860 char *line_buf = NULL;
861 int line_buf_len = 256;
866 cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
867 if (cf->print_fh == NULL)
868 return FALSE; /* attempt to open destination failed */
870 print_preamble(cf->print_fh, print_args->format);
872 if (print_args->print_summary) {
873 /* We're printing packet summaries. Allocate the line buffer at
874 its initial length. */
875 line_buf = g_malloc(line_buf_len + 1);
877 /* Find the widths for each of the columns - maximum of the
878 width of the title and the width of the data - and print
879 the column titles. */
880 col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
883 for (i = 0; i < cf->cinfo.num_cols; i++) {
884 /* Don't pad the last column. */
885 if (i == cf->cinfo.num_cols - 1)
888 col_widths[i] = strlen(cf->cinfo.col_title[i]);
889 data_width = get_column_char_width(get_column_format(i));
890 if (data_width > col_widths[i])
891 col_widths[i] = data_width;
894 /* Find the length of the string for this column. */
895 column_len = strlen(cf->cinfo.col_title[i]);
896 if (col_widths[i] > column_len)
897 column_len = col_widths[i];
899 /* Make sure there's room in the line buffer for the column; if not,
900 double its length. */
901 line_len += column_len + 1; /* "+1" for space or \n */
902 if (line_len > line_buf_len) {
904 line_buf = g_realloc(line_buf, line_buf_len + 1);
907 /* Right-justify the packet number column. */
908 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
909 sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_title[i]);
911 sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
913 if (i == cf->cinfo.num_cols - 1)
919 print_line(cf->print_fh, print_args->format, line_buf);
922 print_separator = FALSE;
923 proto_tree_is_visible = TRUE;
925 /* Update the progress bar when it gets to this value. */
926 progbar_nextstep = 0;
927 /* When we reach the value that triggers a progress bar update,
928 bump that value by this amount. */
929 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
930 /* Count of packets at which we've looked. */
933 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
935 /* Iterate through the list of packets, printing the packets that
936 were selected by the current display filter. */
937 for (fd = cf->plist; fd != NULL; fd = fd->next) {
938 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
939 when we update it, we have to run the GTK+ main loop to get it
940 to repaint what's pending, and doing so may involve an "ioctl()"
941 to see if there's any pending input from an X server, and doing
942 that for every packet can be costly, especially on a big file. */
943 if (count >= progbar_nextstep) {
944 /* let's not divide by zero. I should never be started
945 * with count == 0, so let's assert that
947 g_assert(cf->count > 0);
949 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
950 (gfloat) count / cf->count);
951 progbar_nextstep += progbar_quantum;
952 while (gtk_events_pending())
953 gtk_main_iteration();
957 if (fd->passed_dfilter) {
958 wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
959 if (print_args->print_summary) {
960 /* Fill in the column information, but don't bother creating
961 the logical protocol tree. */
962 fd->cinfo = &cf->cinfo;
963 for (i = 0; i < fd->cinfo->num_cols; i++) {
964 fd->cinfo->col_data[i][0] = '\0';
966 dissect_packet(cf->pd, fd, NULL);
970 for (i = 0; i < cf->cinfo.num_cols; i++) {
971 /* Find the length of the string for this column. */
972 column_len = strlen(cf->cinfo.col_data[i]);
973 if (col_widths[i] > column_len)
974 column_len = col_widths[i];
976 /* Make sure there's room in the line buffer for the column; if not,
977 double its length. */
978 line_len += column_len + 1; /* "+1" for space or \n */
979 if (line_len > line_buf_len) {
981 line_buf = g_realloc(line_buf, line_buf_len + 1);
984 /* Right-justify the packet number column. */
985 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
986 sprintf(cp, "%*s", col_widths[i], cf->cinfo.col_data[i]);
988 sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
990 if (i == cf->cinfo.num_cols - 1)
996 print_line(cf->print_fh, print_args->format, line_buf);
999 print_line(cf->print_fh, print_args->format, "\n");
1001 /* Create the logical protocol tree. */
1002 protocol_tree = proto_tree_create_root();
1003 dissect_packet(cf->pd, fd, protocol_tree);
1005 /* Print the information in that tree. */
1006 proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
1007 cf->pd, fd, cf->print_fh);
1009 proto_tree_free(protocol_tree);
1011 if (print_args->print_hex) {
1012 /* Print the full packet data as hex. */
1013 print_hex_data(cf->print_fh, print_args->format, cf->pd,
1014 fd->cap_len, fd->encoding);
1017 /* Print a blank line if we print anything after this. */
1018 print_separator = TRUE;
1023 if (col_widths != NULL)
1025 if (line_buf != NULL)
1028 print_finale(cf->print_fh, print_args->format);
1030 close_print_dest(print_args->to_file, cf->print_fh);
1032 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1034 cf->print_fh = NULL;
1038 /* Scan through the packet list and change all columns that use the
1039 "command-line-specified" time stamp format to use the current
1040 value of that format. */
1042 change_time_formats(capture_file *cf)
1049 /* Freeze the packet list while we redo it, so we don't get any
1050 screen updates while it happens. */
1053 /* Iterate through the list of packets, checking whether the packet
1054 is in a row of the summary list and, if so, whether there are
1055 any columns that show the time in the "command-line-specified"
1056 format and, if so, update that row. */
1057 for (fd = cf->plist; fd != NULL; fd = fd->next) {
1058 /* Find what row this packet is in. */
1059 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fd);
1062 /* This packet is in the summary list, on row "row". */
1064 /* XXX - there really should be a way of checking "cf->cinfo" for this;
1065 the answer isn't going to change from packet to packet, so we should
1066 simply skip all the "change_time_formats()" work if we're not
1067 changing anything. */
1068 fd->cinfo = &cf->cinfo;
1069 if (check_col(fd, COL_CLS_TIME)) {
1070 /* There are columns that show the time in the "command-line-specified"
1071 format; update them. */
1072 for (i = 0; i < cf->cinfo.num_cols; i++) {
1073 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1074 /* This is one of the columns that shows the time in
1075 "command-line-specified" format; update it. */
1076 cf->cinfo.col_data[i][0] = '\0';
1077 col_set_cls_time(fd, i);
1078 gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
1079 cf->cinfo.col_data[i]);
1086 /* Set the column widths of those columns that show the time in
1087 "command-line-specified" format. */
1088 pl_style = gtk_widget_get_style(packet_list);
1089 for (i = 0; i < cf->cinfo.num_cols; i++) {
1090 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1091 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1092 gdk_string_width(pl_style->font, get_column_longest_string(COL_CLS_TIME)));
1096 /* Unfreeze the packet list. */
1101 clear_tree_and_hex_views(void)
1103 /* Clear the hex dump. */
1104 gtk_text_freeze(GTK_TEXT(byte_view));
1105 gtk_text_set_point(GTK_TEXT(byte_view), 0);
1106 gtk_text_forward_delete(GTK_TEXT(byte_view),
1107 gtk_text_get_length(GTK_TEXT(byte_view)));
1108 gtk_text_thaw(GTK_TEXT(byte_view));
1110 /* Remove all nodes in ctree. This is how it's done in testgtk.c in GTK+ */
1111 gtk_clist_clear ( GTK_CLIST(tree_view) );
1116 find_packet(capture_file *cf, dfilter *sfcode)
1118 frame_data *start_fd;
1120 frame_data *new_fd = NULL;
1121 guint32 progbar_quantum;
1122 guint32 progbar_nextstep;
1124 proto_tree *protocol_tree;
1127 start_fd = cf->current_frame;
1128 if (start_fd != NULL) {
1129 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
1131 /* Iterate through the list of packets, starting at the packet we've
1132 picked, calling a routine to run the filter on the packet, see if
1133 it matches, and stop if so. */
1137 proto_tree_is_visible = FALSE;
1139 /* Update the progress bar when it gets to this value. */
1140 progbar_nextstep = 0;
1141 /* When we reach the value that triggers a progress bar update,
1142 bump that value by this amount. */
1143 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1144 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
1148 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1149 when we update it, we have to run the GTK+ main loop to get it
1150 to repaint what's pending, and doing so may involve an "ioctl()"
1151 to see if there's any pending input from an X server, and doing
1152 that for every packet can be costly, especially on a big file. */
1153 if (count >= progbar_nextstep) {
1154 /* let's not divide by zero. I should never be started
1155 * with count == 0, so let's assert that
1157 g_assert(cf->count > 0);
1159 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1160 (gfloat) count / cf->count);
1162 progbar_nextstep += progbar_quantum;
1163 while (gtk_events_pending())
1164 gtk_main_iteration();
1167 /* Go past the current frame. */
1168 if (cf->sbackward) {
1169 /* Go on to the previous frame. */
1172 fd = cf->plist_end; /* wrap around */
1174 /* Go on to the next frame. */
1177 fd = cf->plist; /* wrap around */
1180 if (fd == start_fd) {
1181 /* We're back to the frame we were on originally. The search
1188 /* Is this packet in the display? */
1189 if (fd->passed_dfilter) {
1190 /* Yes. Does it match the search filter? */
1191 protocol_tree = proto_tree_create_root();
1192 wtap_seek_read(cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1193 dissect_packet(cf->pd, fd, protocol_tree);
1194 if (dfilter_apply(sfcode, protocol_tree, cf->pd)) {
1196 break; /* found it! */
1201 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1204 if (new_fd != NULL) {
1205 /* We found a frame. Find what row it's in. */
1206 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), new_fd);
1207 g_assert(row != -1);
1209 /* Make it visible, and select it. */
1210 if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), row))
1211 gtk_clist_moveto(GTK_CLIST(packet_list), row, -1, 0.0, 0.0);
1213 /* XXX - why is there no "gtk_clist_set_focus_row()", so that we
1214 can make the row for the frame we found the focus row?
1218 http://www.gnome.org/mailing-lists/archives/gtk-list/2000-January/0038.shtml
1221 GTK_CLIST(packet_list)->focus_row = row;
1222 gtk_clist_select_row(GTK_CLIST(packet_list), row, -1);
1223 return TRUE; /* success */
1225 return FALSE; /* failure */
1229 goto_frame(capture_file *cf, guint fnumber)
1234 for (fd = cf->plist; fd != NULL && fd->num < fnumber; fd = fd->next)
1238 return NO_SUCH_FRAME; /* we didn't find that frame */
1239 if (!fd->passed_dfilter)
1240 return FRAME_NOT_DISPLAYED; /* the frame with that number isn't displayed */
1242 /* We found that frame, and it's currently being displayed.
1243 Find what row it's in. */
1244 row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fd);
1245 g_assert(row != -1);
1247 /* Make it visible, and select it. */
1248 if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), row))
1249 gtk_clist_moveto(GTK_CLIST(packet_list), row, -1, 0.0, 0.0);
1251 /* See above complaint about the lack of "gtk_clist_set_focus_row()". */
1252 GTK_CLIST(packet_list)->focus_row = row;
1253 gtk_clist_select_row(GTK_CLIST(packet_list), row, -1);
1257 /* Select the packet on a given row. */
1259 select_packet(capture_file *cf, int row)
1263 /* Get the frame data struct pointer for this frame */
1264 fd = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
1267 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
1268 the first entry is added to it by "real_insert_row()", that row
1269 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
1270 our version and the vanilla GTK+ version).
1272 This means that a "select-row" signal is emitted; this causes
1273 "packet_list_select_cb()" to be called, which causes "select_packet()"
1276 "select_packet()" fetches, above, the data associated with the
1277 row that was selected; however, as "gtk_clist_append()", which
1278 called "real_insert_row()", hasn't yet returned, we haven't yet
1279 associated any data with that row, so we get back a null pointer.
1281 We can't assume that there's only one frame in the frame list,
1282 either, as we may be filtering the display.
1284 We therefore assume that, if "row" is 0, i.e. the first row
1285 is being selected, and "cf->first_displayed" equals
1286 "cf->last_displayed", i.e. there's only one frame being
1287 displayed, that frame is the frame we want.
1289 This means we have to set "cf->first_displayed" and
1290 "cf->last_displayed" before adding the row to the
1291 GtkCList; see the comment in "add_packet_to_packet_list()". */
1293 if (row == 0 && cf->first_displayed == cf->last_displayed)
1294 fd = cf->first_displayed;
1297 /* Record that this frame is the current frame, and that it's selected. */
1298 cf->current_frame = fd;
1299 cf->current_frame_is_selected = TRUE;
1301 /* Get the data in that frame. */
1302 wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1304 /* Create the logical protocol tree. */
1305 if (cf->protocol_tree)
1306 proto_tree_free(cf->protocol_tree);
1307 cf->protocol_tree = proto_tree_create_root();
1308 proto_tree_is_visible = TRUE;
1309 dissect_packet(cf->pd, cf->current_frame, cf->protocol_tree);
1311 /* Display the GUI protocol tree and hex dump. */
1312 clear_tree_and_hex_views();
1313 proto_tree_draw(cf->protocol_tree, tree_view);
1314 packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->current_frame->cap_len,
1315 -1, -1, cf->current_frame->encoding);
1317 /* A packet is selected. */
1318 set_menus_for_selected_packet(TRUE);
1321 /* Unselect the selected packet, if any. */
1323 unselect_packet(capture_file *cf)
1325 cf->current_frame_is_selected = FALSE;
1327 /* Destroy the protocol tree for that packet. */
1328 if (cf->protocol_tree != NULL) {
1329 proto_tree_free(cf->protocol_tree);
1330 cf->protocol_tree = NULL;
1333 finfo_selected = NULL;
1335 /* Clear out the display of that packet. */
1336 clear_tree_and_hex_views();
1338 /* No packet is selected. */
1339 set_menus_for_selected_packet(FALSE);
1343 freeze_clist(capture_file *cf)
1347 /* Make the column sizes static, so they don't adjust while
1348 we're reading the capture file (freezing the clist doesn't
1349 seem to suffice). */
1350 for (i = 0; i < cf->cinfo.num_cols; i++)
1351 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1352 gtk_clist_freeze(GTK_CLIST(packet_list));
1356 thaw_clist(capture_file *cf)
1360 for (i = 0; i < cf->cinfo.num_cols; i++) {
1361 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1362 /* Set this column's width to the appropriate value. */
1363 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1364 cf->cinfo.col_width[i]);
1366 /* Make this column's size dynamic, so that it adjusts to the
1367 appropriate size. */
1368 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1371 gtk_clist_thaw(GTK_CLIST(packet_list));
1373 /* Hopefully, the columns have now gotten their appropriate sizes;
1374 make them resizeable - a column that auto-resizes cannot be
1375 resized by the user, and *vice versa*. */
1376 for (i = 0; i < cf->cinfo.num_cols; i++)
1377 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1381 save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
1384 gchar *from_filename;
1385 gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
1389 int from_fd, to_fd, nread, nwritten;
1392 struct wtap_pkthdr hdr;
1395 name_ptr = get_basename(fname);
1396 msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
1397 save_msg = g_malloc(msg_len);
1398 snprintf(save_msg, msg_len, save_fmt, name_ptr);
1399 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
1402 if (!save_filtered && save_format == cf->cd_t) {
1403 /* We're not filtering packets, and we're saving it in the format
1404 it's already in, so we can just move or copy the raw data. */
1406 /* In this branch, we set "err" only if we get an error, so we
1407 must first clear it. */
1409 if (cf->is_tempfile) {
1410 /* The file being saved is a temporary file from a live
1411 capture, so it doesn't need to stay around under that name;
1412 first, try renaming the capture buffer file to the new name. */
1414 if (rename(cf->filename, fname) == 0) {
1415 /* That succeeded - there's no need to copy the source file. */
1416 from_filename = NULL;
1419 if (errno == EXDEV) {
1420 /* They're on different file systems, so we have to copy the
1423 from_filename = cf->filename;
1425 /* The rename failed, but not because they're on different
1426 file systems - put up an error message. (Or should we
1427 just punt and try to copy? The only reason why I'd
1428 expect the rename to fail and the copy to succeed would
1429 be if we didn't have permission to remove the file from
1430 the temporary directory, and that might be fixable - but
1431 is it worth requiring the user to go off and fix it?) */
1433 simple_dialog(ESD_TYPE_WARN, NULL,
1434 file_rename_error_message(err), fname);
1440 from_filename = cf->filename;
1443 /* It's a permanent file, so we should copy it, and not remove the
1446 from_filename = cf->filename;
1448 /* Copy the file, if we haven't moved it. */
1450 /* Copy the raw bytes of the file. */
1451 from_fd = open(from_filename, O_RDONLY | O_BINARY);
1454 simple_dialog(ESD_TYPE_WARN, NULL,
1455 file_open_error_message(err, TRUE), from_filename);
1459 /* Use open() instead of creat() so that we can pass the O_BINARY
1460 flag, which is relevant on Win32; it appears that "creat()"
1461 may open the file in text mode, not binary mode, but we want
1462 to copy the raw bytes of the file, so we need the output file
1463 to be open in binary mode. */
1464 to_fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1467 simple_dialog(ESD_TYPE_WARN, NULL,
1468 file_open_error_message(err, TRUE), fname);
1473 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
1474 nwritten = write(to_fd, pd, nread);
1475 if (nwritten < nread) {
1479 err = WTAP_ERR_SHORT_WRITE;
1480 simple_dialog(ESD_TYPE_WARN, NULL,
1481 file_write_error_message(err), fname);
1489 simple_dialog(ESD_TYPE_WARN, NULL,
1490 file_read_error_message(err), from_filename);
1496 if (close(to_fd) < 0) {
1498 simple_dialog(ESD_TYPE_WARN, NULL,
1499 file_close_error_message(err), fname);
1504 /* Either we're filtering packets, or we're saving in a different
1505 format; we can't do that by copying or moving the capture file,
1506 we have to do it by writing the packets out in Wiretap. */
1507 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
1509 simple_dialog(ESD_TYPE_WARN, NULL,
1510 file_open_error_message(err, TRUE), fname);
1514 /* XXX - have a way to save only the packets currently selected by
1517 If we do that, should we make that file the current file? If so,
1518 it means we can no longer get at the other packets. What does
1520 for (fd = cf->plist; fd != NULL; fd = fd->next) {
1521 /* XXX - do a progress bar */
1522 if (!save_filtered || fd->passed_dfilter) {
1523 /* Either we're saving all frames, or we're saving filtered frames
1524 and this one passed the display filter - save it. */
1525 hdr.ts.tv_sec = fd->abs_secs;
1526 hdr.ts.tv_usec = fd->abs_usecs;
1527 hdr.caplen = fd->cap_len;
1528 hdr.len = fd->pkt_len;
1529 hdr.pkt_encap = fd->lnk_t;
1530 hdr.pseudo_header = fd->pseudo_header;
1531 wtap_seek_read(cf->cd_t, cf->fh, fd->file_off, pd, fd->cap_len);
1533 if (!wtap_dump(pdh, &hdr, pd, &err)) {
1534 simple_dialog(ESD_TYPE_WARN, NULL,
1535 file_write_error_message(err), fname);
1536 wtap_dump_close(pdh, &err);
1542 if (!wtap_dump_close(pdh, &err)) {
1543 simple_dialog(ESD_TYPE_WARN, NULL,
1544 file_close_error_message(err), fname);
1551 /* Pop the "Saving:" message off the status bar. */
1552 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
1554 if (!save_filtered) {
1555 /* We saved the entire capture, not just some packets from it.
1556 Open and read the file we saved it to.
1558 XXX - this is somewhat of a waste; we already have the
1559 packets, all this gets us is updated file type information
1560 (which we could just stuff into "cf"), and having the new
1561 file be the one we have opened and from which we're reading
1562 the data, and it means we have to spend time opening and
1563 reading the file, which could be a significant amount of
1564 time if the file is large. */
1565 cf->user_saved = TRUE;
1567 if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
1568 /* XXX - report errors if this fails? */
1569 err = read_cap_file(cf);
1570 set_menus_for_unsaved_capture_file(FALSE);
1578 file_open_error_message(int err, int for_writing)
1581 static char errmsg_errno[1024+1];
1585 case WTAP_ERR_NOT_REGULAR_FILE:
1586 errmsg = "The file \"%s\" is invalid.";
1589 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1590 case WTAP_ERR_UNSUPPORTED:
1591 /* Seen only when opening a capture file for reading. */
1592 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1595 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1596 /* Seen only when opening a capture file for writing. */
1597 errmsg = "Ethereal does not support writing capture files in that format.";
1600 case WTAP_ERR_UNSUPPORTED_ENCAP:
1601 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1603 errmsg = "Ethereal cannot save this capture in that format.";
1605 errmsg = "The file \"%s\" is a capture for a network type that Ethereal doesn't support.";
1608 case WTAP_ERR_BAD_RECORD:
1609 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1612 case WTAP_ERR_CANT_OPEN:
1614 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1616 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1619 case WTAP_ERR_SHORT_READ:
1620 errmsg = "The file \"%s\" appears to have been cut short"
1621 " in the middle of a packet.";
1624 case WTAP_ERR_SHORT_WRITE:
1625 errmsg = "A full header couldn't be written to the file \"%s\".";
1630 errmsg = "The path to the file \"%s\" does not exist.";
1632 errmsg = "The file \"%s\" does not exist.";
1637 errmsg = "You do not have permission to create or write to the file \"%s\".";
1639 errmsg = "You do not have permission to read the file \"%s\".";
1643 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
1644 wtap_strerror(err));
1645 errmsg = errmsg_errno;
1652 file_rename_error_message(int err)
1655 static char errmsg_errno[1024+1];
1660 errmsg = "The path to the file \"%s\" does not exist.";
1664 errmsg = "You do not have permission to move the capture file to \"%s\".";
1668 sprintf(errmsg_errno, "The file \"%%s\" could not be moved: %s.",
1669 wtap_strerror(err));
1670 errmsg = errmsg_errno;
1677 file_read_error_message(int err)
1679 static char errmsg_errno[1024+1];
1681 sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.",
1682 wtap_strerror(err));
1683 return errmsg_errno;
1687 file_write_error_message(int err)
1690 static char errmsg_errno[1024+1];
1695 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1700 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1705 sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.",
1706 wtap_strerror(err));
1707 errmsg = errmsg_errno;
1713 /* Check for write errors - if the file is being written to an NFS server,
1714 a write error may not show up until the file is closed, as NFS clients
1715 might not send writes to the server until the "write()" call finishes,
1716 so that the write may fail on the server but the "write()" may succeed. */
1718 file_close_error_message(int err)
1721 static char errmsg_errno[1024+1];
1725 case WTAP_ERR_CANT_CLOSE:
1726 errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
1729 case WTAP_ERR_SHORT_WRITE:
1730 errmsg = "Not all the data could be written to the file \"%s\".";
1734 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1739 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1744 sprintf(errmsg_errno, "An error occurred while closing the file \"%%s\": %s.",
1745 wtap_strerror(err));
1746 errmsg = errmsg_errno;