4 * $Id: file.c,v 1.68 1999/08/15 00:26:09 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'";
221 if ((name_ptr = (gchar *) strrchr(fname, '/')) == NULL)
227 rfcode = dfilter_new();
228 if (dfilter_compile(rfcode, rfilter) != 0) {
229 simple_dialog(ESD_TYPE_WARN, NULL,
230 "Unable to parse filter string \"%s\".", rfilter);
235 err = open_cap_file(fname, cf);
239 load_msg = g_malloc(strlen(name_ptr) + strlen(load_fmt) + 2);
240 sprintf(load_msg, load_fmt, name_ptr);
241 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
243 timeout = gtk_timeout_add(250, file_progress_cb, (gpointer) cf);
246 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf);
249 cf->fh = fopen(fname, "r");
252 gtk_timeout_remove(timeout);
253 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
255 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
257 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
258 load_msg = g_realloc(load_msg, msg_len);
260 if (cf->user_saved || !cf->save_file)
261 snprintf(load_msg, msg_len, done_fmt, name_ptr, cf->drops);
263 snprintf(load_msg, msg_len, done_fmt, "<none>", cf->drops);
265 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
268 /* name_ptr[-1] = '\0'; Why is this here? It causes problems with capture files */
270 /* Remember the new read filter string. */
271 if (cf->rfilter != NULL)
273 cf->rfilter = rfilter;
275 /* Enable menu items that make sense if you have a capture. */
276 set_menu_sensitivity("/File/Close", TRUE);
277 set_menu_sensitivity("/File/Reload", TRUE);
278 set_menu_sensitivity("/File/Print...", TRUE);
279 set_menu_sensitivity("/Display/Options...", TRUE);
280 set_menu_sensitivity("/Tools/Summary", TRUE);
284 msg_len = strlen(name_ptr) + strlen(err_fmt) + 2;
285 load_msg = g_malloc(msg_len);
286 snprintf(load_msg, msg_len, err_fmt, name_ptr);
287 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
290 g_free(rfilter); /* assumed to be "g_strdup()"ed, if not null */
296 cap_file_input_cb (gpointer data, gint source, GdkInputCondition condition) {
298 capture_file *cf = (capture_file *)data;
299 char buffer[256], *p = buffer, *q = buffer;
302 gboolean exit_loop = FALSE;
304 /* avoid reentrancy problems and stack overflow */
305 gtk_input_remove(cap_input_id);
307 if ((nread = read(sync_pipe[0], buffer, 256)) <= 0) {
309 /* The child has closed the sync pipe, meaning it's not going to be
310 capturing any more packets. Read what remains of the capture file,
311 and stop capture (restore menu items) */
312 gtk_clist_freeze(GTK_CLIST(packet_list));
314 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf);
320 set_menu_sensitivity("/File/Open...", TRUE);
321 set_menu_sensitivity("/File/Close", TRUE);
322 set_menu_sensitivity("/File/Save As...", TRUE);
323 set_menu_sensitivity("/File/Print...", TRUE);
324 set_menu_sensitivity("/File/Reload", TRUE);
326 set_menu_sensitivity("/Capture/Start...", TRUE);
328 set_menu_sensitivity("/Tools/Summary", TRUE);
329 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, " File: <none>");
333 buffer[nread] = '\0';
336 /* look for (possibly multiple) '*' */
344 /* XXX should handle the case of a pipe full (i.e. no star found) */
353 gtk_clist_freeze(GTK_CLIST(packet_list));
354 wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf);
355 gtk_clist_thaw(GTK_CLIST(packet_list));
357 /* restore pipe handler */
358 cap_input_id = gtk_input_add_full (sync_pipe[0],
367 tail_cap_file(char *fname, capture_file *cf) {
371 err = open_cap_file(fname, cf);
372 if ((err == 0) && (cf->cd_t != WTAP_FILE_UNKNOWN)) {
374 set_menu_sensitivity("/File/Open...", FALSE);
375 set_menu_sensitivity("/Display/Options...", TRUE);
377 set_menu_sensitivity("/Capture/Start...", FALSE);
380 for (i = 0; i < cf->cinfo.num_cols; i++) {
381 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
382 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
384 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
385 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
386 cf->cinfo.col_width[i]);
387 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
391 cf->fh = fopen(fname, "r");
393 cap_input_id = gtk_input_add_full (sync_pipe[0],
399 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
400 " <live capture in progress>");
409 /* To do: Add check_col checks to the col_add* routines */
412 col_add_abs_time(frame_data *fd, gint el)
418 tmp = localtime(&then);
419 col_add_fstr(fd, el, "%02d:%02d:%02d.%04ld",
423 (long)fd->abs_usecs/100);
427 col_add_rel_time(frame_data *fd, gint el)
429 col_add_fstr(fd, el, "%d.%06d", fd->rel_secs, fd->rel_usecs);
433 col_add_delta_time(frame_data *fd, gint el)
435 col_add_fstr(fd, el, "%d.%06d", fd->del_secs, fd->del_usecs);
438 /* Add "command-line-specified" time. */
440 col_add_cls_time(frame_data *fd)
442 switch (timestamp_type) {
444 col_add_abs_time(fd, COL_CLS_TIME);
448 col_add_rel_time(fd, COL_CLS_TIME);
452 col_add_delta_time(fd, COL_CLS_TIME);
458 add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf)
461 proto_tree *protocol_tree;
463 /* If we don't have the time stamp of the first packet in the
464 capture, it's because this is the first packet. Save the time
465 stamp of this packet as the time stamp of the first packet. */
466 if (!firstsec && !firstusec) {
467 firstsec = fdata->abs_secs;
468 firstusec = fdata->abs_usecs;
471 /* Get the time elapsed between the first packet and this packet. */
472 cf->esec = fdata->abs_secs - firstsec;
473 if (firstusec <= fdata->abs_usecs) {
474 cf->eusec = fdata->abs_usecs - firstusec;
476 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
480 fdata->cinfo = &cf->cinfo;
481 for (i = 0; i < fdata->cinfo->num_cols; i++) {
482 fdata->cinfo->col_data[i][0] = '\0';
485 /* Apply the display filter */
486 if (DFILTER_CONTAINS_FILTER(cf->dfcode)) {
487 protocol_tree = proto_tree_create_root();
488 dissect_packet(buf, fdata, protocol_tree);
489 fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
490 proto_tree_free(protocol_tree);
493 dissect_packet(buf, fdata, NULL);
494 fdata->passed_dfilter = TRUE;
496 if (fdata->passed_dfilter) {
497 if (check_col(fdata, COL_NUMBER))
498 col_add_fstr(fdata, COL_NUMBER, "%d", cf->count);
500 /* If we don't have the time stamp of the previous displayed packet,
501 it's because this is the first displayed packet. Save the time
502 stamp of this packet as the time stamp of the previous displayed
504 if (!prevsec && !prevusec) {
505 prevsec = fdata->abs_secs;
506 prevusec = fdata->abs_usecs;
509 /* Get the time elapsed between the first packet and this packet. */
510 fdata->rel_secs = cf->esec;
511 fdata->rel_usecs = cf->eusec;
513 /* Get the time elapsed between the previous displayed packet and
515 fdata->del_secs = fdata->abs_secs - prevsec;
516 if (prevusec <= fdata->abs_usecs) {
517 fdata->del_usecs = fdata->abs_usecs - prevusec;
519 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
522 prevsec = fdata->abs_secs;
523 prevusec = fdata->abs_usecs;
525 /* Set any time stamp columns. */
526 if (check_col(fdata, COL_CLS_TIME))
527 col_add_cls_time(fdata);
528 if (check_col(fdata, COL_ABS_TIME))
529 col_add_abs_time(fdata, COL_ABS_TIME);
530 if (check_col(fdata, COL_REL_TIME))
531 col_add_rel_time(fdata, COL_REL_TIME);
532 if (check_col(fdata, COL_DELTA_TIME))
533 col_add_delta_time(fdata, COL_DELTA_TIME);
535 if (check_col(fdata, COL_PACKET_LENGTH))
536 col_add_fstr(fdata, COL_PACKET_LENGTH, "%d", fdata->pkt_len);
538 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
541 /* If this was the selected packet, remember the row it's in, so
542 we can re-select it. ("selected_packet" is 0-origin, as it's
543 a GList index; "count", however, is 1-origin.) */
544 if (cf->selected_packet == cf->count - 1)
545 cf->selected_row = row;
547 fdata->row = -1; /* not in the display */
552 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
555 capture_file *cf = (capture_file *) user;
557 proto_tree *protocol_tree;
558 frame_data *plist_end;
560 while (gtk_events_pending())
561 gtk_main_iteration();
563 /* Allocate the next list entry, and add it to the list. */
564 fdata = (frame_data *) g_malloc(sizeof(frame_data));
567 fdata->pkt_len = phdr->len;
568 fdata->cap_len = phdr->caplen;
569 fdata->file_off = offset;
570 fdata->lnk_t = phdr->pkt_encap;
571 fdata->abs_secs = phdr->ts.tv_sec;
572 fdata->abs_usecs = phdr->ts.tv_usec;
573 fdata->flags = phdr->flags;
578 if (DFILTER_CONTAINS_FILTER(rfcode)) {
579 protocol_tree = proto_tree_create_root();
580 dissect_packet(buf, fdata, protocol_tree);
581 passed = dfilter_apply(rfcode, protocol_tree, cf->pd);
582 proto_tree_free(protocol_tree);
586 plist_end = cf->plist_end;
587 if (plist_end != NULL)
588 plist_end->next = fdata;
591 cf->plist_end = fdata;
594 add_packet_to_packet_list(fdata, cf, buf);
600 filter_packets(capture_file *cf)
605 if (cf->dfilter == NULL) {
606 dfilter_clear_filter(cf->dfcode);
610 * Compile the filter.
612 if (dfilter_compile(cf->dfcode, cf->dfilter) != 0) {
613 simple_dialog(ESD_TYPE_WARN, NULL,
614 "Unable to parse filter string \"%s\".", cf->dfilter);
619 /* Freeze the packet list while we redo it, so we don't get any
620 screen updates while it happens. */
621 gtk_clist_freeze(GTK_CLIST(packet_list));
624 gtk_clist_clear(GTK_CLIST(packet_list));
626 /* If a packet was selected, we don't know yet what row, if any, it'll
628 cf->selected_row = -1;
630 /* Iterate through the list of packets, calling a routine
631 to run the filter on the packet, see if it matches, and
632 put it in the display list if so. */
637 cf->unfiltered_count = cf->count;
640 /* timeout = gtk_timeout_add(250, dfilter_progress_cb, cf);*/
641 for (fd = cf->plist; fd != NULL; fd = fd->next) {
644 fseek(cf->fh, fd->file_off, SEEK_SET);
645 fread(cf->pd, sizeof(guint8), fd->cap_len, cf->fh);
647 add_packet_to_packet_list(fd, cf, cf->pd);
649 if (cf->count % 20 == 0) {
650 dfilter_progress_cb(cf);
653 /* gtk_timeout_remove(timeout);*/
655 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
657 if (cf->selected_row != -1) {
658 /* We had a selected packet and it passed the filter. */
659 gtk_clist_select_row(GTK_CLIST(packet_list), cf->selected_row, -1);
661 /* If we had one, it didn't pass the filter. */
665 /* Unfreeze the packet list. */
666 gtk_clist_thaw(GTK_CLIST(packet_list));
669 /* Update the progress bar */
671 dfilter_progress_cb(gpointer p) {
672 capture_file *cf = (capture_file*)p;
674 /* let's not divide by zero. I should never be started
675 * with unfiltered_count == 0, so let's assert that
677 g_assert(cf->unfiltered_count > 0);
679 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
680 (gfloat) cf->count / cf->unfiltered_count);
682 /* Have GTK+ repaint what is pending */
683 while (gtk_events_pending ()) {
684 gtk_main_iteration();
691 print_packets(capture_file *cf, int to_file, const char *dest)
694 proto_tree *protocol_tree;
696 cf->print_fh = open_print_dest(to_file, dest);
697 if (cf->print_fh == NULL)
698 return FALSE; /* attempt to open destination failed */
700 /* XXX - printing multiple frames in PostScript looks as if it's
701 tricky - you have to deal with page boundaries, I think -
702 and I'll have to spend some time learning enough about
703 PostScript to figure it out, so, for now, we only print
704 multiple frames as text. */
706 print_preamble(cf->print_fh);
709 /* Iterate through the list of packets, printing each of them. */
711 for (fd = cf->plist; fd != NULL; fd = fd->next) {
714 fseek(cf->fh, fd->file_off, SEEK_SET);
715 fread(cf->pd, sizeof(guint8), fd->cap_len, cf->fh);
717 /* create the logical protocol tree */
718 protocol_tree = proto_tree_create_root();
719 dissect_packet(cf->pd, fd, protocol_tree);
721 /* Print the packet */
722 proto_tree_print(cf->count, (GNode *)protocol_tree, cf->pd, fd, cf->print_fh);
724 proto_tree_free(protocol_tree);
728 print_finale(cf->print_fh);
731 close_print_dest(to_file, cf->print_fh);
736 /* Scan through the packet list and change all columns that use the
737 "command-line-specified" time stamp format to use the current
738 value of that format. */
740 change_time_formats(capture_file *cf)
746 /* Freeze the packet list while we redo it, so we don't get any
747 screen updates while it happens. */
750 /* Iterate through the list of packets, checking whether the packet
751 is in a row of the summary list and, if so, whether there are
752 any columns that show the time in the "command-line-specified"
753 format and, if so, update that row. */
754 for (fd = cf->plist; fd != NULL; fd = fd->next) {
756 /* This packet is in the summary list, on row "fd->row". */
758 /* XXX - there really should be a way of checking "cf->cinfo" for this;
759 the answer isn't going to change from packet to packet, so we should
760 simply skip all the "change_time_formats()" work if we're not
761 changing anything. */
762 fd->cinfo = &cf->cinfo;
763 if (check_col(fd, COL_CLS_TIME)) {
764 /* There are columns that show the time in the "command-line-specified"
765 format; update them. */
766 for (i = 0; i < cf->cinfo.num_cols; i++) {
767 cf->cinfo.col_data[i][0] = '\0';
769 col_add_cls_time(fd);
770 for (i = 0; i < cf->cinfo.num_cols; i++) {
771 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
772 /* This is one of the columns that shows the time in
773 "command-line-specified" format; update it. */
774 gtk_clist_set_text(GTK_CLIST(packet_list), fd->row, i,
775 cf->cinfo.col_data[i]);
782 /* Set the column widths of those columns that show the time in
783 "command-line-specified" format. */
784 pl_style = gtk_widget_get_style(packet_list);
785 for (i = 0; i < cf->cinfo.num_cols; i++) {
786 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
787 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
788 get_column_width(COL_CLS_TIME, pl_style->font));
792 /* Unfreeze the packet list. */
797 clear_tree_and_hex_views(void)
799 /* Clear the hex dump. */
800 gtk_text_freeze(GTK_TEXT(byte_view));
801 gtk_text_set_point(GTK_TEXT(byte_view), 0);
802 gtk_text_forward_delete(GTK_TEXT(byte_view),
803 gtk_text_get_length(GTK_TEXT(byte_view)));
804 gtk_text_thaw(GTK_TEXT(byte_view));
806 /* Clear the protocol tree view. */
807 gtk_tree_clear_items(GTK_TREE(tree_view), 0,
808 g_list_length(GTK_TREE(tree_view)->children));
811 /* Select the packet on a given row. */
813 select_packet(capture_file *cf, int row)
818 /* Clear out whatever's currently in the hex dump. */
819 gtk_text_freeze(GTK_TEXT(byte_view));
820 gtk_text_set_point(GTK_TEXT(byte_view), 0);
821 gtk_text_forward_delete(GTK_TEXT(byte_view),
822 gtk_text_get_length(GTK_TEXT(byte_view)));
824 /* Search through the list of frames to see which one is in
826 for (fd = cf->plist, i = 0; fd != NULL; fd = fd->next, i++) {
832 /* Remember the ordinal number of that frame. */
833 cf->selected_packet = i;
835 /* Get the data in that frame. */
836 fseek(cf->fh, cf->fd->file_off, SEEK_SET);
837 fread(cf->pd, sizeof(guint8), cf->fd->cap_len, cf->fh);
839 /* Create the logical protocol tree. */
840 if (cf->protocol_tree)
841 proto_tree_free(cf->protocol_tree);
842 cf->protocol_tree = proto_tree_create_root();
843 dissect_packet(cf->pd, cf->fd, cf->protocol_tree);
845 /* Display the GUI protocol tree and hex dump. */
846 clear_tree_and_hex_views();
847 proto_tree_draw(cf->protocol_tree, tree_view);
848 packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->fd->cap_len, -1, -1);
849 gtk_text_thaw(GTK_TEXT(byte_view));
851 /* A packet is selected, so "File/Print Packet" has something to print. */
852 set_menu_sensitivity("/File/Print Packet", TRUE);
855 /* Unselect the selected packet, if any. */
857 unselect_packet(capture_file *cf)
859 cf->selected_packet = -1; /* nothing there to be selected */
860 cf->selected_row = -1;
862 /* Destroy the protocol tree for that packet. */
863 if (cf->protocol_tree != NULL) {
864 proto_tree_free(cf->protocol_tree);
865 cf->protocol_tree = NULL;
868 /* Clear out the display of that packet. */
869 clear_tree_and_hex_views();
871 /* No packet is selected, so "File/Print Packet" has nothing to print. */
872 set_menu_sensitivity("/File/Print Packet", FALSE);
876 freeze_clist(capture_file *cf)
880 /* Make the column sizes static, so they don't adjust while
881 we're reading the capture file (freezing the clist doesn't
883 for (i = 0; i < cf->cinfo.num_cols; i++)
884 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
885 gtk_clist_freeze(GTK_CLIST(packet_list));
889 thaw_clist(capture_file *cf)
893 for (i = 0; i < cf->cinfo.num_cols; i++) {
894 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
895 /* Set this column's width to the appropriate value. */
896 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
897 cf->cinfo.col_width[i]);
899 /* Make this column's size dynamic, so that it adjusts to the
901 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
904 gtk_clist_thaw(GTK_CLIST(packet_list));
906 /* Hopefully, the columns have now gotten their appropriate sizes;
907 make them resizeable - a column that auto-resizes cannot be
908 resized by the user, and *vice versa*. */
909 for (i = 0; i < cf->cinfo.num_cols; i++)
910 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
913 /* Tries to mv a file. If unsuccessful, tries to cp the file.
914 * Returns 0 on failure to do either, 1 on success of either
917 file_mv(char *from, char *to)
920 #define COPY_BUFFER_SIZE 8192
925 /* try a hard link */
926 retval = link(from, to);
931 retval = file_cp(from, to);
944 * Returns 0 on failure to do either, 1 on success of either
947 file_cp(char *from, char *to)
950 #define COPY_BUFFER_SIZE 8192
952 int from_fd, to_fd, nread, nwritten;
955 buffer = g_malloc(COPY_BUFFER_SIZE);
957 from_fd = open(from, O_RDONLY);
959 simple_dialog(ESD_TYPE_WARN, NULL,
960 file_open_error_message(errno, TRUE), from);
964 to_fd = creat(to, 0644);
966 simple_dialog(ESD_TYPE_WARN, NULL,
967 file_open_error_message(errno, TRUE), to);
972 while( (nread = read(from_fd, buffer, COPY_BUFFER_SIZE)) > 0) {
973 nwritten = write(to_fd, buffer, nread);
974 if (nwritten < nread) {
976 simple_dialog(ESD_TYPE_WARN, NULL,
977 file_write_error_message(errno), to);
979 simple_dialog(ESD_TYPE_WARN, NULL,
980 "The file \"%s\" could not be saved: tried writing %d, wrote %d.\n",
981 to, nread, nwritten);
989 simple_dialog(ESD_TYPE_WARN, NULL,
990 file_read_error_message(errno), from);
1002 file_open_error_message(int err, int for_writing)
1005 static char errmsg_errno[1024+1];
1009 case OPEN_CAP_FILE_NOT_REGULAR:
1010 errmsg = "The file \"%s\" is invalid.";
1013 case OPEN_CAP_FILE_UNKNOWN_FORMAT:
1014 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1019 errmsg = "The path to the file \"%s\" does not exist.";
1021 errmsg = "The file \"%s\" does not exist.";
1026 errmsg = "You do not have permission to create or write to the file \"%s\".";
1028 errmsg = "You do not have permission to open the file \"%s\".";
1032 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.", strerror(err));
1033 errmsg = errmsg_errno;
1040 file_read_error_message(int err)
1042 static char errmsg_errno[1024+1];
1044 sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.", strerror(err));
1045 return errmsg_errno;
1049 file_write_error_message(int err)
1052 static char errmsg_errno[1024+1];
1057 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1062 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1067 sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.", strerror(err));
1068 errmsg = errmsg_errno;