4 * $Id: file.c,v 1.62 1999/08/13 23:47:42 gram Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
48 #ifdef NEED_SNPRINTF_H
54 # include "snprintf.h"
57 #ifdef NEED_STRERROR_H
61 #ifdef HAVE_SYS_TYPES_H
62 # include <sys/types.h>
65 #ifdef HAVE_NETINET_IN_H
66 # include <netinet/in.h>
76 #include "gtkpacket.h"
79 #include "packet-ncp.h"
81 extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view;
82 extern guint file_ctx;
84 extern int sync_pipe[];
88 static guint32 firstsec, firstusec;
89 static guint32 lastsec, lastusec;
91 static dfilter *rfcode = NULL;
93 static void wtap_dispatch_cb(u_char *, const struct wtap_pkthdr *, int,
96 static void freeze_clist(capture_file *cf);
97 static void thaw_clist(capture_file *cf);
99 static gint dfilter_progress_cb(gpointer p);
102 open_cap_file(char *fname, capture_file *cf) {
105 /* First, make sure the file is valid */
106 if (stat(fname, &cf_stat))
109 if (! S_ISREG(cf_stat.st_mode) && ! S_ISFIFO(cf_stat.st_mode))
110 return (OPEN_CAP_FILE_NOT_REGULAR);
113 /* Next, try to open the file */
114 cf->fh = fopen(fname, "r");
118 fseek(cf->fh, 0L, SEEK_END);
119 cf->f_len = ftell(cf->fh);
122 /* set the file name beacuse we need it to set the follow stream filter */
123 cf->filename = g_strdup( fname );
125 /* Next, find out what type of file we're dealing with */
126 cf->cd_t = WTAP_FILE_UNKNOWN;
127 cf->cd_t_desc = "unknown";
133 firstsec = 0, firstusec = 0;
134 lastsec = 0, lastusec = 0;
136 cf->wth = wtap_open_offline(fname);
137 if (cf->wth == NULL) {
139 /* XXX - we assume that, because we were able to open it above,
140 this must have failed because it's not a capture file in
141 a format we can read. */
142 return (OPEN_CAP_FILE_UNKNOWN_FORMAT);
145 cf->fh = wtap_file(cf->wth);
146 cf->cd_t = wtap_file_type(cf->wth);
147 cf->cd_t_desc = wtap_file_type_string(cf->wth);
148 cf->snap = wtap_snapshot_length(cf->wth);
152 /* Reset everything to a pristine state */
154 close_cap_file(capture_file *cf, void *w, guint context) {
155 frame_data *fd, *fd_next;
165 for (fd = cf->plist; fd != NULL; fd = fd_next) {
170 cf->plist_end = NULL;
171 unselect_packet(cf); /* nothing to select */
173 gtk_clist_freeze(GTK_CLIST(packet_list));
174 gtk_clist_clear(GTK_CLIST(packet_list));
175 gtk_clist_thaw(GTK_CLIST(packet_list));
176 gtk_statusbar_pop(GTK_STATUSBAR(w), context);
178 /* Disable all menu items that make sense only if you have a capture. */
179 set_menu_sensitivity("/File/Save", FALSE);
180 set_menu_sensitivity("/File/Save As...", FALSE);
181 set_menu_sensitivity("/File/Close", FALSE);
182 set_menu_sensitivity("/File/Reload", FALSE);
183 set_menu_sensitivity("/File/Print...", FALSE);
184 set_menu_sensitivity("/Display/Options...", FALSE);
185 set_menu_sensitivity("/Tools/Summary", FALSE);
189 load_cap_file(char *fname, char *rfilter, capture_file *cf) {
190 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
191 gchar *done_fmt = " File: %s Drops: %d";
192 gchar *err_fmt = " Error: Could not load '%s'";
197 close_cap_file(cf, info_bar, file_ctx);
199 /* Initialize protocol-specific variables */
202 if ((name_ptr = (gchar *) strrchr(fname, '/')) == NULL)
208 rfcode = dfilter_new();
209 if (dfilter_compile(rfcode, rfilter) != 0) {
210 simple_dialog(ESD_TYPE_WARN, NULL,
211 "Unable to parse filter string \"%s\".", rfilter);
216 err = open_cap_file(fname, cf);
218 simple_dialog(ESD_TYPE_WARN, NULL,
219 file_open_error_message(err, FALSE), fname);
223 load_msg = g_malloc(strlen(name_ptr) + strlen(load_fmt) + 2);
224 sprintf(load_msg, load_fmt, name_ptr);
225 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
227 timeout = gtk_timeout_add(250, file_progress_cb, (gpointer) cf);
230 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf);
233 cf->fh = fopen(fname, "r");
236 gtk_timeout_remove(timeout);
237 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
239 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
241 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
242 load_msg = g_realloc(load_msg, msg_len);
244 if (cf->user_saved || !cf->save_file)
245 snprintf(load_msg, msg_len, done_fmt, name_ptr, cf->drops);
247 snprintf(load_msg, msg_len, done_fmt, "<none>", cf->drops);
249 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
252 /* name_ptr[-1] = '\0'; Why is this here? It causes problems with capture files */
254 /* Remember the new read filter string. */
255 if (cf->rfilter != NULL)
257 cf->rfilter = rfilter;
259 /* Enable menu items that make sense if you have a capture. */
260 set_menu_sensitivity("/File/Close", TRUE);
261 set_menu_sensitivity("/File/Reload", TRUE);
262 set_menu_sensitivity("/File/Print...", TRUE);
263 set_menu_sensitivity("/Display/Options...", TRUE);
264 set_menu_sensitivity("/Tools/Summary", TRUE);
268 msg_len = strlen(name_ptr) + strlen(err_fmt) + 2;
269 load_msg = g_malloc(msg_len);
270 snprintf(load_msg, msg_len, err_fmt, name_ptr);
271 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
274 g_free(rfilter); /* assumed to be "g_strdup()"ed, if not null */
280 cap_file_input_cb (gpointer data, gint source, GdkInputCondition condition) {
282 capture_file *cf = (capture_file *)data;
283 char buffer[256], *p = buffer, *q = buffer;
286 gboolean exit_loop = FALSE;
288 /* avoid reentrancy problems and stack overflow */
289 gtk_input_remove(cap_input_id);
291 if ((nread = read(sync_pipe[0], buffer, 256)) <= 0) {
293 /* The child has closed the sync pipe, meaning it's not going to be
294 capturing any more packets. Read what remains of the capture file,
295 and stop capture (restore menu items) */
296 gtk_clist_freeze(GTK_CLIST(packet_list));
298 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf);
304 set_menu_sensitivity("/File/Open...", TRUE);
305 set_menu_sensitivity("/File/Close", TRUE);
306 set_menu_sensitivity("/File/Save As...", TRUE);
307 set_menu_sensitivity("/File/Print...", TRUE);
308 set_menu_sensitivity("/File/Reload", TRUE);
310 set_menu_sensitivity("/Capture/Start...", TRUE);
312 set_menu_sensitivity("/Tools/Summary", TRUE);
313 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, " File: <none>");
317 buffer[nread] = '\0';
320 /* look for (possibly multiple) '*' */
328 /* XXX should handle the case of a pipe full (i.e. no star found) */
337 gtk_clist_freeze(GTK_CLIST(packet_list));
338 wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf);
339 gtk_clist_thaw(GTK_CLIST(packet_list));
341 /* restore pipe handler */
342 cap_input_id = gtk_input_add_full (sync_pipe[0],
351 tail_cap_file(char *fname, capture_file *cf) {
355 close_cap_file(cf, info_bar, file_ctx);
357 /* Initialize protocol-specific variables */
360 err = open_cap_file(fname, cf);
361 if ((err == 0) && (cf->cd_t != WTAP_FILE_UNKNOWN)) {
363 set_menu_sensitivity("/File/Open...", FALSE);
365 set_menu_sensitivity("/Capture/Start...", FALSE);
368 for (i = 0; i < cf->cinfo.num_cols; i++) {
369 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
370 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
372 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
373 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
374 cf->cinfo.col_width[i]);
375 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
379 cf->fh = fopen(fname, "r");
381 cap_input_id = gtk_input_add_full (sync_pipe[0],
387 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
388 " <live capture in progress>");
398 compute_time_stamps(frame_data *fdata, capture_file *cf)
400 /* If we don't have the time stamp of the first packet, it's because this
401 is the first packet. Save the time stamp of this packet as the time
402 stamp of the first packet. */
403 if (!firstsec && !firstusec) {
404 firstsec = fdata->abs_secs;
405 firstusec = fdata->abs_usecs;
408 /* Do the same for the time stamp of the previous packet. */
409 if (!lastsec && !lastusec) {
410 lastsec = fdata->abs_secs;
411 lastusec = fdata->abs_usecs;
414 /* Get the time elapsed between the first packet and this packet. */
415 cf->esec = fdata->abs_secs - firstsec;
416 if (firstusec <= fdata->abs_usecs) {
417 cf->eusec = fdata->abs_usecs - firstusec;
419 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
422 fdata->rel_secs = cf->esec;
423 fdata->rel_usecs = cf->eusec;
425 /* Do the same for the previous packet */
426 fdata->del_secs = fdata->abs_secs - lastsec;
427 if (lastusec <= fdata->abs_usecs) {
428 fdata->del_usecs = fdata->abs_usecs - lastusec;
430 fdata->del_usecs = (fdata->abs_usecs + 1000000) - lastusec;
433 lastsec = fdata->abs_secs;
434 lastusec = fdata->abs_usecs;
438 add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf)
441 proto_tree *protocol_tree;
443 compute_time_stamps(fdata, cf);
445 fdata->cinfo = &cf->cinfo;
446 for (i = 0; i < fdata->cinfo->num_cols; i++) {
447 fdata->cinfo->col_data[i][0] = '\0';
449 if (check_col(fdata, COL_NUMBER))
450 col_add_fstr(fdata, COL_NUMBER, "%d", cf->count);
451 /* Apply the display filter */
452 if (DFILTER_CONTAINS_FILTER(cf->dfcode)) {
453 protocol_tree = proto_tree_create_root();
454 dissect_packet(buf, fdata, protocol_tree);
455 fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
456 proto_tree_free(protocol_tree);
459 dissect_packet(buf, fdata, NULL);
460 fdata->passed_dfilter = TRUE;
462 if (fdata->passed_dfilter) {
463 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
466 /* If this was the selected packet, remember the row it's in, so
467 we can re-select it. ("selected_packet" is 0-origin, as it's
468 a GList index; "count", however, is 1-origin.) */
469 if (cf->selected_packet == cf->count - 1)
470 cf->selected_row = row;
472 fdata->row = -1; /* not in the display */
477 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
480 capture_file *cf = (capture_file *) user;
482 proto_tree *protocol_tree;
483 frame_data *plist_end;
485 while (gtk_events_pending())
486 gtk_main_iteration();
488 /* Allocate the next list entry, and add it to the list. */
489 fdata = (frame_data *) g_malloc(sizeof(frame_data));
492 fdata->pkt_len = phdr->len;
493 fdata->cap_len = phdr->caplen;
494 fdata->file_off = offset;
495 fdata->lnk_t = phdr->pkt_encap;
496 fdata->abs_secs = phdr->ts.tv_sec;
497 fdata->abs_usecs = phdr->ts.tv_usec;
498 fdata->flags = phdr->flags;
503 protocol_tree = proto_tree_create_root();
504 dissect_packet(buf, fdata, protocol_tree);
505 passed = dfilter_apply(rfcode, protocol_tree, cf->pd);
506 proto_tree_free(protocol_tree);
509 plist_end = cf->plist_end;
510 if (plist_end != NULL)
511 plist_end->next = fdata;
514 cf->plist_end = fdata;
517 add_packet_to_packet_list(fdata, cf, buf);
523 filter_packets(capture_file *cf)
528 if (cf->dfilter == NULL) {
529 dfilter_clear_filter(cf->dfcode);
533 * Compile the filter.
535 if (dfilter_compile(cf->dfcode, cf->dfilter) != 0) {
536 simple_dialog(ESD_TYPE_WARN, NULL,
537 "Unable to parse filter string \"%s\".", cf->dfilter);
542 /* Freeze the packet list while we redo it, so we don't get any
543 screen updates while it happens. */
544 gtk_clist_freeze(GTK_CLIST(packet_list));
547 gtk_clist_clear(GTK_CLIST(packet_list));
549 /* If a packet was selected, we don't know yet what row, if any, it'll
551 cf->selected_row = -1;
554 * Iterate through the list of packets, calling a routine
555 * to run the filter on the packet, see if it matches, and
556 * put it in the display list if so.
562 cf->unfiltered_count = cf->count;
565 /* timeout = gtk_timeout_add(250, dfilter_progress_cb, cf);*/
566 for (fd = cf->plist; fd != NULL; fd = fd->next) {
569 fseek(cf->fh, fd->file_off, SEEK_SET);
570 fread(cf->pd, sizeof(guint8), fd->cap_len, cf->fh);
572 add_packet_to_packet_list(fd, cf, cf->pd);
574 if (cf->count % 20 == 0) {
575 dfilter_progress_cb(cf);
578 /* gtk_timeout_remove(timeout);*/
580 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
582 if (cf->selected_row != -1) {
583 /* We had a selected packet and it passed the filter. */
584 gtk_clist_select_row(GTK_CLIST(packet_list), cf->selected_row, -1);
586 /* If we had one, it didn't pass the filter. */
590 /* Unfreeze the packet list. */
591 gtk_clist_thaw(GTK_CLIST(packet_list));
594 /* Update the progress bar */
596 dfilter_progress_cb(gpointer p) {
597 capture_file *cf = (capture_file*)p;
599 /* let's not divide by zero. I should never be started
600 * with unfiltered_count == 0, so let's assert that
602 g_assert(cf->unfiltered_count > 0);
604 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
605 (gfloat) cf->count / cf->unfiltered_count);
607 /* Have GTK+ repaint what is pending */
608 while (gtk_events_pending ()) {
609 gtk_main_iteration();
616 print_packets(capture_file *cf, int to_file, const char *dest)
619 proto_tree *protocol_tree;
621 cf->print_fh = open_print_dest(to_file, dest);
622 if (cf->print_fh == NULL)
623 return FALSE; /* attempt to open destination failed */
625 /* XXX - printing multiple frames in PostScript looks as if it's
626 tricky - you have to deal with page boundaries, I think -
627 and I'll have to spend some time learning enough about
628 PostScript to figure it out, so, for now, we only print
629 multiple frames as text. */
631 print_preamble(cf->print_fh);
635 * Iterate through the list of packets, printing each of them.
638 for (fd = cf->plist; fd != NULL; fd = fd->next) {
641 fseek(cf->fh, fd->file_off, SEEK_SET);
642 fread(cf->pd, sizeof(guint8), fd->cap_len, cf->fh);
644 /* create the logical protocol tree */
645 protocol_tree = proto_tree_create_root();
646 dissect_packet(cf->pd, fd, protocol_tree);
648 /* Print the packet */
649 proto_tree_print(cf->count, (GNode *)protocol_tree, cf->pd, fd, cf->print_fh);
651 proto_tree_free(protocol_tree);
655 print_finale(cf->print_fh);
658 close_print_dest(to_file, cf->print_fh);
663 /* Scan through the packet list and change all columns that use the
664 "command-line-specified" time stamp format to use the current
665 value of that format. */
667 change_time_formats(capture_file *cf)
673 /* Freeze the packet list while we redo it, so we don't get any
674 screen updates while it happens. */
678 * Iterate through the list of packets, calling a routine
679 * to run the filter on the packet, see if it matches, and
680 * put it in the display list if so.
687 for (fd = cf->plist; fd != NULL; fd = fd->next) {
690 /* XXX - there really should be a way of checking "cf->cinfo" for this;
691 the answer isn't going to change from packet to packet, so we should
692 simply skip all the "change_time_formats()" work if we're not
693 changing anything. */
694 if (check_col(fd, COL_CLS_TIME)) {
695 /* There are columns that show the time in the "command-line-specified"
696 format; update them. */
697 compute_time_stamps(fd, cf);
699 for (i = 0; i < cf->cinfo.num_cols; i++) {
700 cf->cinfo.col_data[i][0] = '\0';
702 col_add_cls_time(fd);
703 for (i = 0; i < cf->cinfo.num_cols; i++) {
704 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
705 /* This is one of the columns that shows the time in
706 "command-line-specified" format; update it. */
707 gtk_clist_set_text(GTK_CLIST(packet_list), cf->count - 1, i,
708 cf->cinfo.col_data[i]);
714 /* Set the column widths of those columns that show the time in
715 "command-line-specified" format. */
716 pl_style = gtk_widget_get_style(packet_list);
717 for (i = 0; i < cf->cinfo.num_cols; i++) {
718 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
719 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
720 get_column_width(COL_CLS_TIME, pl_style->font));
724 /* Unfreeze the packet list. */
729 clear_tree_and_hex_views(void)
731 /* Clear the hex dump. */
732 gtk_text_freeze(GTK_TEXT(byte_view));
733 gtk_text_set_point(GTK_TEXT(byte_view), 0);
734 gtk_text_forward_delete(GTK_TEXT(byte_view),
735 gtk_text_get_length(GTK_TEXT(byte_view)));
736 gtk_text_thaw(GTK_TEXT(byte_view));
738 /* Clear the protocol tree view. */
739 gtk_tree_clear_items(GTK_TREE(tree_view), 0,
740 g_list_length(GTK_TREE(tree_view)->children));
743 /* Select the packet on a given row. */
745 select_packet(capture_file *cf, int row)
750 /* Clear out whatever's currently in the hex dump. */
751 gtk_text_freeze(GTK_TEXT(byte_view));
752 gtk_text_set_point(GTK_TEXT(byte_view), 0);
753 gtk_text_forward_delete(GTK_TEXT(byte_view),
754 gtk_text_get_length(GTK_TEXT(byte_view)));
756 /* Search through the list of frames to see which one is in
758 for (fd = cf->plist, i = 0; fd != NULL; fd = fd->next, i++) {
764 /* Remember the ordinal number of that frame. */
765 cf->selected_packet = i;
767 /* Get the data in that frame. */
768 fseek(cf->fh, cf->fd->file_off, SEEK_SET);
769 fread(cf->pd, sizeof(guint8), cf->fd->cap_len, cf->fh);
771 /* Create the logical protocol tree. */
772 if (cf->protocol_tree)
773 proto_tree_free(cf->protocol_tree);
774 cf->protocol_tree = proto_tree_create_root();
775 dissect_packet(cf->pd, cf->fd, cf->protocol_tree);
777 /* Display the GUI protocol tree and hex dump. */
778 clear_tree_and_hex_views();
779 proto_tree_draw(cf->protocol_tree, tree_view);
780 packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->fd->cap_len, -1, -1);
781 gtk_text_thaw(GTK_TEXT(byte_view));
783 /* A packet is selected, so "File/Print Packet" has something to print. */
784 set_menu_sensitivity("/File/Print Packet", TRUE);
787 /* Unselect the selected packet, if any. */
789 unselect_packet(capture_file *cf)
791 cf->selected_packet = -1; /* nothing there to be selected */
792 cf->selected_row = -1;
794 /* Destroy the protocol tree for that packet. */
795 if (cf->protocol_tree != NULL) {
796 proto_tree_free(cf->protocol_tree);
797 cf->protocol_tree = NULL;
800 /* Clear out the display of that packet. */
801 clear_tree_and_hex_views();
803 /* No packet is selected, so "File/Print Packet" has nothing to print. */
804 set_menu_sensitivity("/File/Print Packet", FALSE);
808 freeze_clist(capture_file *cf)
812 /* Make the column sizes static, so they don't adjust while
813 we're reading the capture file (freezing the clist doesn't
815 for (i = 0; i < cf->cinfo.num_cols; i++)
816 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
817 gtk_clist_freeze(GTK_CLIST(packet_list));
821 thaw_clist(capture_file *cf)
825 for (i = 0; i < cf->cinfo.num_cols; i++) {
826 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
827 /* Set this column's width to the appropriate value. */
828 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
829 cf->cinfo.col_width[i]);
831 /* Make this column's size dynamic, so that it adjusts to the
833 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
836 gtk_clist_thaw(GTK_CLIST(packet_list));
838 /* Hopefully, the columns have now gotten their appropriate sizes;
839 make them resizeable - a column that auto-resizes cannot be
840 resized by the user, and *vice versa*. */
841 for (i = 0; i < cf->cinfo.num_cols; i++)
842 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
845 /* Tries to mv a file. If unsuccessful, tries to cp the file.
846 * Returns 0 on failure to do either, 1 on success of either
849 file_mv(char *from, char *to)
852 #define COPY_BUFFER_SIZE 8192
857 /* try a hard link */
858 retval = link(from, to);
863 retval = file_cp(from, to);
876 * Returns 0 on failure to do either, 1 on success of either
879 file_cp(char *from, char *to)
882 #define COPY_BUFFER_SIZE 8192
884 int from_fd, to_fd, nread, nwritten;
887 buffer = g_malloc(COPY_BUFFER_SIZE);
889 from_fd = open(from, O_RDONLY);
891 simple_dialog(ESD_TYPE_WARN, NULL,
892 file_open_error_message(errno, TRUE), from);
896 to_fd = creat(to, 0644);
898 simple_dialog(ESD_TYPE_WARN, NULL,
899 file_open_error_message(errno, TRUE), to);
904 while( (nread = read(from_fd, buffer, COPY_BUFFER_SIZE)) > 0) {
905 nwritten = write(to_fd, buffer, nread);
906 if (nwritten < nread) {
908 simple_dialog(ESD_TYPE_WARN, NULL,
909 file_write_error_message(errno), to);
911 simple_dialog(ESD_TYPE_WARN, NULL,
912 "The file \"%s\" could not be saved: tried writing %d, wrote %d.\n",
913 to, nread, nwritten);
921 simple_dialog(ESD_TYPE_WARN, NULL,
922 file_read_error_message(errno), from);
934 file_open_error_message(int err, int for_writing)
937 static char errmsg_errno[1024+1];
941 case OPEN_CAP_FILE_NOT_REGULAR:
942 errmsg = "The file \"%s\" is invalid.";
945 case OPEN_CAP_FILE_UNKNOWN_FORMAT:
946 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
951 errmsg = "The path to the file \"%s\" does not exist.";
953 errmsg = "The file \"%s\" does not exist.";
958 errmsg = "You do not have permission to create or write to the file \"%s\".";
960 errmsg = "You do not have permission to open the file \"%s\".";
964 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.", strerror(err));
965 errmsg = errmsg_errno;
972 file_read_error_message(int err)
974 static char errmsg_errno[1024+1];
976 sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.", strerror(err));
981 file_write_error_message(int err)
984 static char errmsg_errno[1024+1];
989 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
994 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
999 sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.", strerror(err));
1000 errmsg = errmsg_errno;