4 * $Id: file.c,v 1.69 1999/08/15 00:55:22 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"
78 #include "timestamp.h"
80 #include "packet-ncp.h"
82 extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view;
83 extern guint file_ctx;
85 extern int sync_pipe[];
89 static guint32 firstsec, firstusec;
90 static guint32 prevsec, prevusec;
92 static dfilter *rfcode = NULL;
94 static void wtap_dispatch_cb(u_char *, const struct wtap_pkthdr *, int,
97 static void freeze_clist(capture_file *cf);
98 static void thaw_clist(capture_file *cf);
100 static gint dfilter_progress_cb(gpointer p);
103 open_cap_file(char *fname, capture_file *cf) {
109 /* First, make sure the file is valid */
110 if (stat(fname, &cf_stat)) {
115 if (! S_ISREG(cf_stat.st_mode) && ! S_ISFIFO(cf_stat.st_mode)) {
116 err = OPEN_CAP_FILE_NOT_REGULAR;
121 /* Next, try to open the file.
122 XXX - we only need to do this because "wtap_open_offline()"
123 doesn't return an indication of whether the open failed because
124 we don't have access to the file, or because it's not a valid
125 capture file, so we first have to open it with "fopen()" to
126 make sure we have access to it as a boring ordinary file. */
127 fh = fopen(fname, "r");
134 /* Next, try to open it as a wiretap capture file. */
135 wth = wtap_open_offline(fname);
137 /* XXX - we assume that, because we were able to open it above,
138 this must have failed because it's not a capture file in
139 a format we can read. */
140 err = OPEN_CAP_FILE_UNKNOWN_FORMAT;
144 /* The open succeeded. Close whatever capture file we had open,
145 and fill in the information for this file. */
146 close_cap_file(cf, info_bar, file_ctx);
148 /* Initialize protocol-specific variables */
152 cf->fh = wtap_file(cf->wth);
153 cf->f_len = cf_stat.st_size;
155 /* set the file name because we need it to set the follow stream filter */
156 cf->filename = g_strdup(fname);
158 cf->cd_t = wtap_file_type(cf->wth);
159 cf->cd_t_desc = wtap_file_type_string(cf->wth);
164 cf->snap = wtap_snapshot_length(cf->wth);
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, guint context) {
179 frame_data *fd, *fd_next;
189 for (fd = cf->plist; fd != NULL; fd = fd_next) {
194 cf->plist_end = NULL;
195 unselect_packet(cf); /* nothing to select */
197 gtk_clist_freeze(GTK_CLIST(packet_list));
198 gtk_clist_clear(GTK_CLIST(packet_list));
199 gtk_clist_thaw(GTK_CLIST(packet_list));
200 gtk_statusbar_pop(GTK_STATUSBAR(w), context);
202 /* Disable all menu items that make sense only if you have a capture. */
203 set_menu_sensitivity("/File/Save", FALSE);
204 set_menu_sensitivity("/File/Save As...", FALSE);
205 set_menu_sensitivity("/File/Close", FALSE);
206 set_menu_sensitivity("/File/Reload", FALSE);
207 set_menu_sensitivity("/File/Print...", FALSE);
208 set_menu_sensitivity("/Display/Options...", FALSE);
209 set_menu_sensitivity("/Tools/Summary", FALSE);
213 read_cap_file(char *fname, char *rfilter, capture_file *cf) {
214 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
215 gchar *done_fmt = " File: %s Drops: %d";
216 gchar *err_fmt = " Error: Could not load '%s'";
220 if ((name_ptr = (gchar *) strrchr(fname, '/')) == NULL)
226 rfcode = dfilter_new();
227 if (dfilter_compile(rfcode, rfilter) != 0) {
228 simple_dialog(ESD_TYPE_WARN, NULL,
229 "Unable to parse filter string \"%s\".", rfilter);
234 load_msg = g_malloc(strlen(name_ptr) + strlen(load_fmt) + 2);
235 sprintf(load_msg, load_fmt, name_ptr);
236 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
238 timeout = gtk_timeout_add(250, file_progress_cb, (gpointer) cf);
241 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf);
244 cf->fh = fopen(fname, "r");
247 gtk_timeout_remove(timeout);
248 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
250 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
252 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
253 load_msg = g_realloc(load_msg, msg_len);
255 if (cf->user_saved || !cf->save_file)
256 snprintf(load_msg, msg_len, done_fmt, name_ptr, cf->drops);
258 snprintf(load_msg, msg_len, done_fmt, "<none>", cf->drops);
260 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
263 /* name_ptr[-1] = '\0'; Why is this here? It causes problems with capture files */
265 /* Remember the new read filter string. */
266 if (cf->rfilter != NULL)
268 cf->rfilter = rfilter;
270 /* Enable menu items that make sense if you have a capture. */
271 set_menu_sensitivity("/File/Close", TRUE);
272 set_menu_sensitivity("/File/Reload", TRUE);
273 set_menu_sensitivity("/File/Print...", TRUE);
274 set_menu_sensitivity("/Display/Options...", TRUE);
275 set_menu_sensitivity("/Tools/Summary", TRUE);
279 msg_len = strlen(name_ptr) + strlen(err_fmt) + 2;
280 load_msg = g_malloc(msg_len);
281 snprintf(load_msg, msg_len, err_fmt, name_ptr);
282 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
285 g_free(rfilter); /* assumed to be "g_strdup()"ed, if not null */
291 cap_file_input_cb (gpointer data, gint source, GdkInputCondition condition) {
293 capture_file *cf = (capture_file *)data;
294 char buffer[256], *p = buffer, *q = buffer;
297 gboolean exit_loop = FALSE;
299 /* avoid reentrancy problems and stack overflow */
300 gtk_input_remove(cap_input_id);
302 if ((nread = read(sync_pipe[0], buffer, 256)) <= 0) {
304 /* The child has closed the sync pipe, meaning it's not going to be
305 capturing any more packets. Read what remains of the capture file,
306 and stop capture (restore menu items) */
307 gtk_clist_freeze(GTK_CLIST(packet_list));
309 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf);
315 set_menu_sensitivity("/File/Open...", TRUE);
316 set_menu_sensitivity("/File/Close", TRUE);
317 set_menu_sensitivity("/File/Save As...", TRUE);
318 set_menu_sensitivity("/File/Print...", TRUE);
319 set_menu_sensitivity("/File/Reload", TRUE);
321 set_menu_sensitivity("/Capture/Start...", TRUE);
323 set_menu_sensitivity("/Tools/Summary", TRUE);
324 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, " File: <none>");
328 buffer[nread] = '\0';
331 /* look for (possibly multiple) '*' */
339 /* XXX should handle the case of a pipe full (i.e. no star found) */
348 gtk_clist_freeze(GTK_CLIST(packet_list));
349 wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf);
350 gtk_clist_thaw(GTK_CLIST(packet_list));
352 /* restore pipe handler */
353 cap_input_id = gtk_input_add_full (sync_pipe[0],
362 tail_cap_file(char *fname, capture_file *cf) {
366 err = open_cap_file(fname, cf);
367 if ((err == 0) && (cf->cd_t != WTAP_FILE_UNKNOWN)) {
369 set_menu_sensitivity("/File/Open...", FALSE);
370 set_menu_sensitivity("/Display/Options...", TRUE);
372 set_menu_sensitivity("/Capture/Start...", FALSE);
375 for (i = 0; i < cf->cinfo.num_cols; i++) {
376 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
377 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
379 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
380 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
381 cf->cinfo.col_width[i]);
382 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
386 cf->fh = fopen(fname, "r");
388 cap_input_id = gtk_input_add_full (sync_pipe[0],
394 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
395 " <live capture in progress>");
404 /* To do: Add check_col checks to the col_add* routines */
407 col_add_abs_time(frame_data *fd, gint el)
413 tmp = localtime(&then);
414 col_add_fstr(fd, el, "%02d:%02d:%02d.%04ld",
418 (long)fd->abs_usecs/100);
422 col_add_rel_time(frame_data *fd, gint el)
424 col_add_fstr(fd, el, "%d.%06d", fd->rel_secs, fd->rel_usecs);
428 col_add_delta_time(frame_data *fd, gint el)
430 col_add_fstr(fd, el, "%d.%06d", fd->del_secs, fd->del_usecs);
433 /* Add "command-line-specified" time. */
435 col_add_cls_time(frame_data *fd)
437 switch (timestamp_type) {
439 col_add_abs_time(fd, COL_CLS_TIME);
443 col_add_rel_time(fd, COL_CLS_TIME);
447 col_add_delta_time(fd, COL_CLS_TIME);
453 add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf)
456 proto_tree *protocol_tree;
458 /* If we don't have the time stamp of the first packet in the
459 capture, it's because this is the first packet. Save the time
460 stamp of this packet as the time stamp of the first packet. */
461 if (!firstsec && !firstusec) {
462 firstsec = fdata->abs_secs;
463 firstusec = fdata->abs_usecs;
466 /* Get the time elapsed between the first packet and this packet. */
467 cf->esec = fdata->abs_secs - firstsec;
468 if (firstusec <= fdata->abs_usecs) {
469 cf->eusec = fdata->abs_usecs - firstusec;
471 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
475 fdata->cinfo = &cf->cinfo;
476 for (i = 0; i < fdata->cinfo->num_cols; i++) {
477 fdata->cinfo->col_data[i][0] = '\0';
480 /* Apply the display filter */
481 if (DFILTER_CONTAINS_FILTER(cf->dfcode)) {
482 protocol_tree = proto_tree_create_root();
483 dissect_packet(buf, fdata, protocol_tree);
484 fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
485 proto_tree_free(protocol_tree);
488 dissect_packet(buf, fdata, NULL);
489 fdata->passed_dfilter = TRUE;
491 if (fdata->passed_dfilter) {
492 if (check_col(fdata, COL_NUMBER))
493 col_add_fstr(fdata, COL_NUMBER, "%d", cf->count);
495 /* If we don't have the time stamp of the previous displayed packet,
496 it's because this is the first displayed packet. Save the time
497 stamp of this packet as the time stamp of the previous displayed
499 if (!prevsec && !prevusec) {
500 prevsec = fdata->abs_secs;
501 prevusec = fdata->abs_usecs;
504 /* Get the time elapsed between the first packet and this packet. */
505 fdata->rel_secs = cf->esec;
506 fdata->rel_usecs = cf->eusec;
508 /* Get the time elapsed between the previous displayed packet and
510 fdata->del_secs = fdata->abs_secs - prevsec;
511 if (prevusec <= fdata->abs_usecs) {
512 fdata->del_usecs = fdata->abs_usecs - prevusec;
514 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
517 prevsec = fdata->abs_secs;
518 prevusec = fdata->abs_usecs;
520 /* Set any time stamp columns. */
521 if (check_col(fdata, COL_CLS_TIME))
522 col_add_cls_time(fdata);
523 if (check_col(fdata, COL_ABS_TIME))
524 col_add_abs_time(fdata, COL_ABS_TIME);
525 if (check_col(fdata, COL_REL_TIME))
526 col_add_rel_time(fdata, COL_REL_TIME);
527 if (check_col(fdata, COL_DELTA_TIME))
528 col_add_delta_time(fdata, COL_DELTA_TIME);
530 if (check_col(fdata, COL_PACKET_LENGTH))
531 col_add_fstr(fdata, COL_PACKET_LENGTH, "%d", fdata->pkt_len);
533 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
536 /* If this was the selected packet, remember the row it's in, so
537 we can re-select it. ("selected_packet" is 0-origin, as it's
538 a GList index; "count", however, is 1-origin.) */
539 if (cf->selected_packet == cf->count - 1)
540 cf->selected_row = row;
542 fdata->row = -1; /* not in the display */
547 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
550 capture_file *cf = (capture_file *) user;
552 proto_tree *protocol_tree;
553 frame_data *plist_end;
555 while (gtk_events_pending())
556 gtk_main_iteration();
558 /* Allocate the next list entry, and add it to the list. */
559 fdata = (frame_data *) g_malloc(sizeof(frame_data));
562 fdata->pkt_len = phdr->len;
563 fdata->cap_len = phdr->caplen;
564 fdata->file_off = offset;
565 fdata->lnk_t = phdr->pkt_encap;
566 fdata->abs_secs = phdr->ts.tv_sec;
567 fdata->abs_usecs = phdr->ts.tv_usec;
568 fdata->flags = phdr->flags;
573 if (DFILTER_CONTAINS_FILTER(rfcode)) {
574 protocol_tree = proto_tree_create_root();
575 dissect_packet(buf, fdata, protocol_tree);
576 passed = dfilter_apply(rfcode, protocol_tree, cf->pd);
577 proto_tree_free(protocol_tree);
581 plist_end = cf->plist_end;
582 if (plist_end != NULL)
583 plist_end->next = fdata;
586 cf->plist_end = fdata;
589 add_packet_to_packet_list(fdata, cf, buf);
595 filter_packets(capture_file *cf)
600 if (cf->dfilter == NULL) {
601 dfilter_clear_filter(cf->dfcode);
605 * Compile the filter.
607 if (dfilter_compile(cf->dfcode, cf->dfilter) != 0) {
608 simple_dialog(ESD_TYPE_WARN, NULL,
609 "Unable to parse filter string \"%s\".", cf->dfilter);
614 /* Freeze the packet list while we redo it, so we don't get any
615 screen updates while it happens. */
616 gtk_clist_freeze(GTK_CLIST(packet_list));
619 gtk_clist_clear(GTK_CLIST(packet_list));
621 /* If a packet was selected, we don't know yet what row, if any, it'll
623 cf->selected_row = -1;
625 /* Iterate through the list of packets, calling a routine
626 to run the filter on the packet, see if it matches, and
627 put it in the display list if so. */
632 cf->unfiltered_count = cf->count;
635 /* timeout = gtk_timeout_add(250, dfilter_progress_cb, cf);*/
636 for (fd = cf->plist; fd != NULL; fd = fd->next) {
639 fseek(cf->fh, fd->file_off, SEEK_SET);
640 fread(cf->pd, sizeof(guint8), fd->cap_len, cf->fh);
642 add_packet_to_packet_list(fd, cf, cf->pd);
644 if (cf->count % 20 == 0) {
645 dfilter_progress_cb(cf);
648 /* gtk_timeout_remove(timeout);*/
650 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
652 if (cf->selected_row != -1) {
653 /* We had a selected packet and it passed the filter. */
654 gtk_clist_select_row(GTK_CLIST(packet_list), cf->selected_row, -1);
656 /* If we had one, it didn't pass the filter. */
660 /* Unfreeze the packet list. */
661 gtk_clist_thaw(GTK_CLIST(packet_list));
664 /* Update the progress bar */
666 dfilter_progress_cb(gpointer p) {
667 capture_file *cf = (capture_file*)p;
669 /* let's not divide by zero. I should never be started
670 * with unfiltered_count == 0, so let's assert that
672 g_assert(cf->unfiltered_count > 0);
674 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
675 (gfloat) cf->count / cf->unfiltered_count);
677 /* Have GTK+ repaint what is pending */
678 while (gtk_events_pending ()) {
679 gtk_main_iteration();
686 print_packets(capture_file *cf, int to_file, const char *dest)
689 proto_tree *protocol_tree;
691 cf->print_fh = open_print_dest(to_file, dest);
692 if (cf->print_fh == NULL)
693 return FALSE; /* attempt to open destination failed */
695 /* XXX - printing multiple frames in PostScript looks as if it's
696 tricky - you have to deal with page boundaries, I think -
697 and I'll have to spend some time learning enough about
698 PostScript to figure it out, so, for now, we only print
699 multiple frames as text. */
701 print_preamble(cf->print_fh);
704 /* Iterate through the list of packets, printing each of them. */
706 for (fd = cf->plist; fd != NULL; fd = fd->next) {
709 fseek(cf->fh, fd->file_off, SEEK_SET);
710 fread(cf->pd, sizeof(guint8), fd->cap_len, cf->fh);
712 /* create the logical protocol tree */
713 protocol_tree = proto_tree_create_root();
714 dissect_packet(cf->pd, fd, protocol_tree);
716 /* Print the packet */
717 proto_tree_print(cf->count, (GNode *)protocol_tree, cf->pd, fd, cf->print_fh);
719 proto_tree_free(protocol_tree);
723 print_finale(cf->print_fh);
726 close_print_dest(to_file, cf->print_fh);
731 /* Scan through the packet list and change all columns that use the
732 "command-line-specified" time stamp format to use the current
733 value of that format. */
735 change_time_formats(capture_file *cf)
741 /* Freeze the packet list while we redo it, so we don't get any
742 screen updates while it happens. */
745 /* Iterate through the list of packets, checking whether the packet
746 is in a row of the summary list and, if so, whether there are
747 any columns that show the time in the "command-line-specified"
748 format and, if so, update that row. */
749 for (fd = cf->plist; fd != NULL; fd = fd->next) {
751 /* This packet is in the summary list, on row "fd->row". */
753 /* XXX - there really should be a way of checking "cf->cinfo" for this;
754 the answer isn't going to change from packet to packet, so we should
755 simply skip all the "change_time_formats()" work if we're not
756 changing anything. */
757 fd->cinfo = &cf->cinfo;
758 if (check_col(fd, COL_CLS_TIME)) {
759 /* There are columns that show the time in the "command-line-specified"
760 format; update them. */
761 for (i = 0; i < cf->cinfo.num_cols; i++) {
762 cf->cinfo.col_data[i][0] = '\0';
764 col_add_cls_time(fd);
765 for (i = 0; i < cf->cinfo.num_cols; i++) {
766 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
767 /* This is one of the columns that shows the time in
768 "command-line-specified" format; update it. */
769 gtk_clist_set_text(GTK_CLIST(packet_list), fd->row, i,
770 cf->cinfo.col_data[i]);
777 /* Set the column widths of those columns that show the time in
778 "command-line-specified" format. */
779 pl_style = gtk_widget_get_style(packet_list);
780 for (i = 0; i < cf->cinfo.num_cols; i++) {
781 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
782 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
783 get_column_width(COL_CLS_TIME, pl_style->font));
787 /* Unfreeze the packet list. */
792 clear_tree_and_hex_views(void)
794 /* Clear the hex dump. */
795 gtk_text_freeze(GTK_TEXT(byte_view));
796 gtk_text_set_point(GTK_TEXT(byte_view), 0);
797 gtk_text_forward_delete(GTK_TEXT(byte_view),
798 gtk_text_get_length(GTK_TEXT(byte_view)));
799 gtk_text_thaw(GTK_TEXT(byte_view));
801 /* Clear the protocol tree view. */
802 gtk_tree_clear_items(GTK_TREE(tree_view), 0,
803 g_list_length(GTK_TREE(tree_view)->children));
806 /* Select the packet on a given row. */
808 select_packet(capture_file *cf, int row)
813 /* Clear out whatever's currently in the hex dump. */
814 gtk_text_freeze(GTK_TEXT(byte_view));
815 gtk_text_set_point(GTK_TEXT(byte_view), 0);
816 gtk_text_forward_delete(GTK_TEXT(byte_view),
817 gtk_text_get_length(GTK_TEXT(byte_view)));
819 /* Search through the list of frames to see which one is in
821 for (fd = cf->plist, i = 0; fd != NULL; fd = fd->next, i++) {
827 /* Remember the ordinal number of that frame. */
828 cf->selected_packet = i;
830 /* Get the data in that frame. */
831 fseek(cf->fh, cf->fd->file_off, SEEK_SET);
832 fread(cf->pd, sizeof(guint8), cf->fd->cap_len, cf->fh);
834 /* Create the logical protocol tree. */
835 if (cf->protocol_tree)
836 proto_tree_free(cf->protocol_tree);
837 cf->protocol_tree = proto_tree_create_root();
838 dissect_packet(cf->pd, cf->fd, cf->protocol_tree);
840 /* Display the GUI protocol tree and hex dump. */
841 clear_tree_and_hex_views();
842 proto_tree_draw(cf->protocol_tree, tree_view);
843 packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->fd->cap_len, -1, -1);
844 gtk_text_thaw(GTK_TEXT(byte_view));
846 /* A packet is selected, so "File/Print Packet" has something to print. */
847 set_menu_sensitivity("/File/Print Packet", TRUE);
850 /* Unselect the selected packet, if any. */
852 unselect_packet(capture_file *cf)
854 cf->selected_packet = -1; /* nothing there to be selected */
855 cf->selected_row = -1;
857 /* Destroy the protocol tree for that packet. */
858 if (cf->protocol_tree != NULL) {
859 proto_tree_free(cf->protocol_tree);
860 cf->protocol_tree = NULL;
863 /* Clear out the display of that packet. */
864 clear_tree_and_hex_views();
866 /* No packet is selected, so "File/Print Packet" has nothing to print. */
867 set_menu_sensitivity("/File/Print Packet", FALSE);
871 freeze_clist(capture_file *cf)
875 /* Make the column sizes static, so they don't adjust while
876 we're reading the capture file (freezing the clist doesn't
878 for (i = 0; i < cf->cinfo.num_cols; i++)
879 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
880 gtk_clist_freeze(GTK_CLIST(packet_list));
884 thaw_clist(capture_file *cf)
888 for (i = 0; i < cf->cinfo.num_cols; i++) {
889 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
890 /* Set this column's width to the appropriate value. */
891 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
892 cf->cinfo.col_width[i]);
894 /* Make this column's size dynamic, so that it adjusts to the
896 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
899 gtk_clist_thaw(GTK_CLIST(packet_list));
901 /* Hopefully, the columns have now gotten their appropriate sizes;
902 make them resizeable - a column that auto-resizes cannot be
903 resized by the user, and *vice versa*. */
904 for (i = 0; i < cf->cinfo.num_cols; i++)
905 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
908 /* Tries to mv a file. If unsuccessful, tries to cp the file.
909 * Returns 0 on failure to do either, 1 on success of either
912 file_mv(char *from, char *to)
915 #define COPY_BUFFER_SIZE 8192
920 /* try a hard link */
921 retval = link(from, to);
926 retval = file_cp(from, to);
939 * Returns 0 on failure to do either, 1 on success of either
942 file_cp(char *from, char *to)
945 #define COPY_BUFFER_SIZE 8192
947 int from_fd, to_fd, nread, nwritten;
950 buffer = g_malloc(COPY_BUFFER_SIZE);
952 from_fd = open(from, O_RDONLY);
954 simple_dialog(ESD_TYPE_WARN, NULL,
955 file_open_error_message(errno, TRUE), from);
959 to_fd = creat(to, 0644);
961 simple_dialog(ESD_TYPE_WARN, NULL,
962 file_open_error_message(errno, TRUE), to);
967 while( (nread = read(from_fd, buffer, COPY_BUFFER_SIZE)) > 0) {
968 nwritten = write(to_fd, buffer, nread);
969 if (nwritten < nread) {
971 simple_dialog(ESD_TYPE_WARN, NULL,
972 file_write_error_message(errno), to);
974 simple_dialog(ESD_TYPE_WARN, NULL,
975 "The file \"%s\" could not be saved: tried writing %d, wrote %d.\n",
976 to, nread, nwritten);
984 simple_dialog(ESD_TYPE_WARN, NULL,
985 file_read_error_message(errno), from);
997 file_open_error_message(int err, int for_writing)
1000 static char errmsg_errno[1024+1];
1004 case OPEN_CAP_FILE_NOT_REGULAR:
1005 errmsg = "The file \"%s\" is invalid.";
1008 case OPEN_CAP_FILE_UNKNOWN_FORMAT:
1009 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1014 errmsg = "The path to the file \"%s\" does not exist.";
1016 errmsg = "The file \"%s\" does not exist.";
1021 errmsg = "You do not have permission to create or write to the file \"%s\".";
1023 errmsg = "You do not have permission to open the file \"%s\".";
1027 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.", strerror(err));
1028 errmsg = errmsg_errno;
1035 file_read_error_message(int err)
1037 static char errmsg_errno[1024+1];
1039 sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.", strerror(err));
1040 return errmsg_errno;
1044 file_write_error_message(int err)
1047 static char errmsg_errno[1024+1];
1052 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1057 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1062 sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.", strerror(err));
1063 errmsg = errmsg_errno;