4 * $Id: file.c,v 1.65 1999/08/14 03:36:30 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.
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);
364 set_menu_sensitivity("/Display/Options...", TRUE);
366 set_menu_sensitivity("/Capture/Start...", FALSE);
369 for (i = 0; i < cf->cinfo.num_cols; i++) {
370 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
371 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
373 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
374 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
375 cf->cinfo.col_width[i]);
376 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
380 cf->fh = fopen(fname, "r");
382 cap_input_id = gtk_input_add_full (sync_pipe[0],
388 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
389 " <live capture in progress>");
399 compute_time_stamps(frame_data *fdata, capture_file *cf)
401 /* If we don't have the time stamp of the first packet, it's because this
402 is the first packet. Save the time stamp of this packet as the time
403 stamp of the first packet. */
404 if (!firstsec && !firstusec) {
405 firstsec = fdata->abs_secs;
406 firstusec = fdata->abs_usecs;
409 /* Do the same for the time stamp of the previous packet. */
410 if (!lastsec && !lastusec) {
411 lastsec = fdata->abs_secs;
412 lastusec = fdata->abs_usecs;
415 /* Get the time elapsed between the first packet and this packet. */
416 cf->esec = fdata->abs_secs - firstsec;
417 if (firstusec <= fdata->abs_usecs) {
418 cf->eusec = fdata->abs_usecs - firstusec;
420 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
423 fdata->rel_secs = cf->esec;
424 fdata->rel_usecs = cf->eusec;
426 /* Do the same for the previous packet */
427 fdata->del_secs = fdata->abs_secs - lastsec;
428 if (lastusec <= fdata->abs_usecs) {
429 fdata->del_usecs = fdata->abs_usecs - lastusec;
431 fdata->del_usecs = (fdata->abs_usecs + 1000000) - lastusec;
434 lastsec = fdata->abs_secs;
435 lastusec = fdata->abs_usecs;
439 add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf)
442 proto_tree *protocol_tree;
444 compute_time_stamps(fdata, cf);
446 fdata->cinfo = &cf->cinfo;
447 for (i = 0; i < fdata->cinfo->num_cols; i++) {
448 fdata->cinfo->col_data[i][0] = '\0';
450 if (check_col(fdata, COL_NUMBER))
451 col_add_fstr(fdata, COL_NUMBER, "%d", cf->count);
452 /* Apply the display filter */
453 if (DFILTER_CONTAINS_FILTER(cf->dfcode)) {
454 protocol_tree = proto_tree_create_root();
455 dissect_packet(buf, fdata, protocol_tree);
456 fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
457 proto_tree_free(protocol_tree);
460 dissect_packet(buf, fdata, NULL);
461 fdata->passed_dfilter = TRUE;
463 if (fdata->passed_dfilter) {
464 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
467 /* If this was the selected packet, remember the row it's in, so
468 we can re-select it. ("selected_packet" is 0-origin, as it's
469 a GList index; "count", however, is 1-origin.) */
470 if (cf->selected_packet == cf->count - 1)
471 cf->selected_row = row;
473 fdata->row = -1; /* not in the display */
478 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
481 capture_file *cf = (capture_file *) user;
483 proto_tree *protocol_tree;
484 frame_data *plist_end;
486 while (gtk_events_pending())
487 gtk_main_iteration();
489 /* Allocate the next list entry, and add it to the list. */
490 fdata = (frame_data *) g_malloc(sizeof(frame_data));
493 fdata->pkt_len = phdr->len;
494 fdata->cap_len = phdr->caplen;
495 fdata->file_off = offset;
496 fdata->lnk_t = phdr->pkt_encap;
497 fdata->abs_secs = phdr->ts.tv_sec;
498 fdata->abs_usecs = phdr->ts.tv_usec;
499 fdata->flags = phdr->flags;
504 protocol_tree = proto_tree_create_root();
505 dissect_packet(buf, fdata, protocol_tree);
506 passed = dfilter_apply(rfcode, protocol_tree, cf->pd);
507 proto_tree_free(protocol_tree);
510 plist_end = cf->plist_end;
511 if (plist_end != NULL)
512 plist_end->next = fdata;
515 cf->plist_end = fdata;
518 add_packet_to_packet_list(fdata, cf, buf);
524 filter_packets(capture_file *cf)
529 if (cf->dfilter == NULL) {
530 dfilter_clear_filter(cf->dfcode);
534 * Compile the filter.
536 if (dfilter_compile(cf->dfcode, cf->dfilter) != 0) {
537 simple_dialog(ESD_TYPE_WARN, NULL,
538 "Unable to parse filter string \"%s\".", cf->dfilter);
543 /* Freeze the packet list while we redo it, so we don't get any
544 screen updates while it happens. */
545 gtk_clist_freeze(GTK_CLIST(packet_list));
548 gtk_clist_clear(GTK_CLIST(packet_list));
550 /* If a packet was selected, we don't know yet what row, if any, it'll
552 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. */
561 cf->unfiltered_count = cf->count;
564 /* timeout = gtk_timeout_add(250, dfilter_progress_cb, cf);*/
565 for (fd = cf->plist; fd != NULL; fd = fd->next) {
568 fseek(cf->fh, fd->file_off, SEEK_SET);
569 fread(cf->pd, sizeof(guint8), fd->cap_len, cf->fh);
571 add_packet_to_packet_list(fd, cf, cf->pd);
573 if (cf->count % 20 == 0) {
574 dfilter_progress_cb(cf);
577 /* gtk_timeout_remove(timeout);*/
579 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
581 if (cf->selected_row != -1) {
582 /* We had a selected packet and it passed the filter. */
583 gtk_clist_select_row(GTK_CLIST(packet_list), cf->selected_row, -1);
585 /* If we had one, it didn't pass the filter. */
589 /* Unfreeze the packet list. */
590 gtk_clist_thaw(GTK_CLIST(packet_list));
593 /* Update the progress bar */
595 dfilter_progress_cb(gpointer p) {
596 capture_file *cf = (capture_file*)p;
598 /* let's not divide by zero. I should never be started
599 * with unfiltered_count == 0, so let's assert that
601 g_assert(cf->unfiltered_count > 0);
603 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
604 (gfloat) cf->count / cf->unfiltered_count);
606 /* Have GTK+ repaint what is pending */
607 while (gtk_events_pending ()) {
608 gtk_main_iteration();
615 print_packets(capture_file *cf, int to_file, const char *dest)
618 proto_tree *protocol_tree;
620 cf->print_fh = open_print_dest(to_file, dest);
621 if (cf->print_fh == NULL)
622 return FALSE; /* attempt to open destination failed */
624 /* XXX - printing multiple frames in PostScript looks as if it's
625 tricky - you have to deal with page boundaries, I think -
626 and I'll have to spend some time learning enough about
627 PostScript to figure it out, so, for now, we only print
628 multiple frames as text. */
630 print_preamble(cf->print_fh);
633 /* Iterate through the list of packets, printing each of them. */
635 for (fd = cf->plist; fd != NULL; fd = fd->next) {
638 fseek(cf->fh, fd->file_off, SEEK_SET);
639 fread(cf->pd, sizeof(guint8), fd->cap_len, cf->fh);
641 /* create the logical protocol tree */
642 protocol_tree = proto_tree_create_root();
643 dissect_packet(cf->pd, fd, protocol_tree);
645 /* Print the packet */
646 proto_tree_print(cf->count, (GNode *)protocol_tree, cf->pd, fd, cf->print_fh);
648 proto_tree_free(protocol_tree);
652 print_finale(cf->print_fh);
655 close_print_dest(to_file, cf->print_fh);
660 /* Scan through the packet list and change all columns that use the
661 "command-line-specified" time stamp format to use the current
662 value of that format. */
664 change_time_formats(capture_file *cf)
670 /* Freeze the packet list while we redo it, so we don't get any
671 screen updates while it happens. */
674 /* Iterate through the list of packets, checking whether the packet
675 is in a row of the summary list and, if so, whether there are
676 any columns that show the time in the "command-line-specified"
677 format and, if so, update that row. */
678 for (fd = cf->plist; fd != NULL; fd = fd->next) {
680 /* This packet is in the summary list, on row "fd->row". */
682 /* XXX - there really should be a way of checking "cf->cinfo" for this;
683 the answer isn't going to change from packet to packet, so we should
684 simply skip all the "change_time_formats()" work if we're not
685 changing anything. */
686 fd->cinfo = &cf->cinfo;
687 if (check_col(fd, COL_CLS_TIME)) {
688 /* There are columns that show the time in the "command-line-specified"
689 format; update them. */
690 for (i = 0; i < cf->cinfo.num_cols; i++) {
691 cf->cinfo.col_data[i][0] = '\0';
693 col_add_cls_time(fd);
694 for (i = 0; i < cf->cinfo.num_cols; i++) {
695 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
696 /* This is one of the columns that shows the time in
697 "command-line-specified" format; update it. */
698 gtk_clist_set_text(GTK_CLIST(packet_list), fd->row, i,
699 cf->cinfo.col_data[i]);
706 /* Set the column widths of those columns that show the time in
707 "command-line-specified" format. */
708 pl_style = gtk_widget_get_style(packet_list);
709 for (i = 0; i < cf->cinfo.num_cols; i++) {
710 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
711 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
712 get_column_width(COL_CLS_TIME, pl_style->font));
716 /* Unfreeze the packet list. */
721 clear_tree_and_hex_views(void)
723 /* Clear the hex dump. */
724 gtk_text_freeze(GTK_TEXT(byte_view));
725 gtk_text_set_point(GTK_TEXT(byte_view), 0);
726 gtk_text_forward_delete(GTK_TEXT(byte_view),
727 gtk_text_get_length(GTK_TEXT(byte_view)));
728 gtk_text_thaw(GTK_TEXT(byte_view));
730 /* Clear the protocol tree view. */
731 gtk_tree_clear_items(GTK_TREE(tree_view), 0,
732 g_list_length(GTK_TREE(tree_view)->children));
735 /* Select the packet on a given row. */
737 select_packet(capture_file *cf, int row)
742 /* Clear out whatever's currently in the hex dump. */
743 gtk_text_freeze(GTK_TEXT(byte_view));
744 gtk_text_set_point(GTK_TEXT(byte_view), 0);
745 gtk_text_forward_delete(GTK_TEXT(byte_view),
746 gtk_text_get_length(GTK_TEXT(byte_view)));
748 /* Search through the list of frames to see which one is in
750 for (fd = cf->plist, i = 0; fd != NULL; fd = fd->next, i++) {
756 /* Remember the ordinal number of that frame. */
757 cf->selected_packet = i;
759 /* Get the data in that frame. */
760 fseek(cf->fh, cf->fd->file_off, SEEK_SET);
761 fread(cf->pd, sizeof(guint8), cf->fd->cap_len, cf->fh);
763 /* Create the logical protocol tree. */
764 if (cf->protocol_tree)
765 proto_tree_free(cf->protocol_tree);
766 cf->protocol_tree = proto_tree_create_root();
767 dissect_packet(cf->pd, cf->fd, cf->protocol_tree);
769 /* Display the GUI protocol tree and hex dump. */
770 clear_tree_and_hex_views();
771 proto_tree_draw(cf->protocol_tree, tree_view);
772 packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->fd->cap_len, -1, -1);
773 gtk_text_thaw(GTK_TEXT(byte_view));
775 /* A packet is selected, so "File/Print Packet" has something to print. */
776 set_menu_sensitivity("/File/Print Packet", TRUE);
779 /* Unselect the selected packet, if any. */
781 unselect_packet(capture_file *cf)
783 cf->selected_packet = -1; /* nothing there to be selected */
784 cf->selected_row = -1;
786 /* Destroy the protocol tree for that packet. */
787 if (cf->protocol_tree != NULL) {
788 proto_tree_free(cf->protocol_tree);
789 cf->protocol_tree = NULL;
792 /* Clear out the display of that packet. */
793 clear_tree_and_hex_views();
795 /* No packet is selected, so "File/Print Packet" has nothing to print. */
796 set_menu_sensitivity("/File/Print Packet", FALSE);
800 freeze_clist(capture_file *cf)
804 /* Make the column sizes static, so they don't adjust while
805 we're reading the capture file (freezing the clist doesn't
807 for (i = 0; i < cf->cinfo.num_cols; i++)
808 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
809 gtk_clist_freeze(GTK_CLIST(packet_list));
813 thaw_clist(capture_file *cf)
817 for (i = 0; i < cf->cinfo.num_cols; i++) {
818 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
819 /* Set this column's width to the appropriate value. */
820 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
821 cf->cinfo.col_width[i]);
823 /* Make this column's size dynamic, so that it adjusts to the
825 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
828 gtk_clist_thaw(GTK_CLIST(packet_list));
830 /* Hopefully, the columns have now gotten their appropriate sizes;
831 make them resizeable - a column that auto-resizes cannot be
832 resized by the user, and *vice versa*. */
833 for (i = 0; i < cf->cinfo.num_cols; i++)
834 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
837 /* Tries to mv a file. If unsuccessful, tries to cp the file.
838 * Returns 0 on failure to do either, 1 on success of either
841 file_mv(char *from, char *to)
844 #define COPY_BUFFER_SIZE 8192
849 /* try a hard link */
850 retval = link(from, to);
855 retval = file_cp(from, to);
868 * Returns 0 on failure to do either, 1 on success of either
871 file_cp(char *from, char *to)
874 #define COPY_BUFFER_SIZE 8192
876 int from_fd, to_fd, nread, nwritten;
879 buffer = g_malloc(COPY_BUFFER_SIZE);
881 from_fd = open(from, O_RDONLY);
883 simple_dialog(ESD_TYPE_WARN, NULL,
884 file_open_error_message(errno, TRUE), from);
888 to_fd = creat(to, 0644);
890 simple_dialog(ESD_TYPE_WARN, NULL,
891 file_open_error_message(errno, TRUE), to);
896 while( (nread = read(from_fd, buffer, COPY_BUFFER_SIZE)) > 0) {
897 nwritten = write(to_fd, buffer, nread);
898 if (nwritten < nread) {
900 simple_dialog(ESD_TYPE_WARN, NULL,
901 file_write_error_message(errno), to);
903 simple_dialog(ESD_TYPE_WARN, NULL,
904 "The file \"%s\" could not be saved: tried writing %d, wrote %d.\n",
905 to, nread, nwritten);
913 simple_dialog(ESD_TYPE_WARN, NULL,
914 file_read_error_message(errno), from);
926 file_open_error_message(int err, int for_writing)
929 static char errmsg_errno[1024+1];
933 case OPEN_CAP_FILE_NOT_REGULAR:
934 errmsg = "The file \"%s\" is invalid.";
937 case OPEN_CAP_FILE_UNKNOWN_FORMAT:
938 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
943 errmsg = "The path to the file \"%s\" does not exist.";
945 errmsg = "The file \"%s\" does not exist.";
950 errmsg = "You do not have permission to create or write to the file \"%s\".";
952 errmsg = "You do not have permission to open the file \"%s\".";
956 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.", strerror(err));
957 errmsg = errmsg_errno;
964 file_read_error_message(int err)
966 static char errmsg_errno[1024+1];
968 sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.", strerror(err));
973 file_write_error_message(int err)
976 static char errmsg_errno[1024+1];
981 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
986 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
991 sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.", strerror(err));
992 errmsg = errmsg_errno;