Ethereal-dev: [Ethereal-dev] [PATCH] export data as CSV for iostat
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: francesco fondelli <fondelli.francesco@xxxxxxxxxx>
Date: Fri, 29 Oct 2004 11:47:39 +0200
Hi all, I needed a way to plot rate graph nicer than IO-Stat does, so I wrote a patch that exports data in a CSV formatted file. So we can now plot an io graph using gnuplot, Excel... I tested the patch against the svn version of ethereal, compiled for GNU/Linux with gtk2. Hope this is useful for someone else. I tried to follow Ronnie Sahlberg's coding style for names and indentation. Please find attached the "svn-diffed" patch. Ciao FF
Index: AUTHORS =================================================================== --- AUTHORS (revision 12430) +++ AUTHORS (working copy) @@ -2226,6 +2226,7 @@ Francesco Fondelli <fondelli.francesco [AT] tiscali.it> { ICE protocol support + IO-Stat: added support for data export as csv } Index: gtk/io_stat.c =================================================================== --- gtk/io_stat.c (revision 12430) +++ gtk/io_stat.c (working copy) @@ -1,6 +1,8 @@ /* io_stat.c * io_stat 2002 Ronnie Sahlberg * + * Francesco Fondelli (_FF_), 28-Oct-2004, added support for data export as csv. + * * $Id$ * * Ethereal - Network traffic analyzer @@ -149,6 +151,7 @@ GdkPixmap *pixmap; GtkAdjustment *scrollbar_adjustment; GtkWidget *scrollbar; + GtkWidget *save_as_w; int pixmap_width; int pixmap_height; int pixels_per_tick; @@ -1064,6 +1067,7 @@ io->pixmap=NULL; io->scrollbar=NULL; io->scrollbar_adjustment=NULL; + io->save_as_w=NULL; io->pixmap_width=500; io->pixmap_height=200; io->pixels_per_tick=pixels_per_tick[DEFAULT_PIXELS_PER_TICK]; @@ -1864,13 +1868,170 @@ return; } +/* based on file_dlg.c code */ +static void +iostat_save_as_ok_cb(GtkWidget *bt _U_, gpointer data _U_) +{ + io_stat_t *io = (io_stat_t *)data; + gchar *csvf_name; + FILE *fp; + gint32 i, j; + gint32 lastgraph = -1; + gchar *filter; + gchar *field; + +#if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2 + csvf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(io->save_as_w))); +#else + csvf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(io->save_as_w))); +#endif + + /* check whether the user specified a directory instead of a file */ + if (test_for_directory(csvf_name) == EISDIR) { + /* It's a directory - set the file selection box to display that + directory, and leave the selection box displayed. */ + set_last_open_dir(csvf_name); + g_free(csvf_name); + file_selection_set_current_folder(io->save_as_w, get_last_open_dir()); + return; + } + + /* it was a file, open it */ + if ((fp = fopen(csvf_name, "w+")) == NULL) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + "Could not open\n%s\nfor writing: %s.", + csvf_name, strerror(errno)); + g_free(csvf_name); + return; + } + + /* print file header */ + + fprintf(fp, "################################################################################\n"); + fprintf(fp, "# CSV file exported by Ethereal->Statistics->IO Graphs\n"); + /* XXX to do: add Start/End time lines, i.e. the abs arrival time of the first and last pkt + to let the user easily remember when the measure has been taken. + And maybe a line telling which interface the traffic has been sniffed from. + */ + fprintf(fp, "# Y Unit: %s\n", count_type_names[io->count_type]); + fprintf(fp, "# X Tick Interval: %dms\n", io->interval); + for( i = 0; i < MAX_GRAPHS; i++ ) + if(io->graphs[i].display) { + + filter = (char *)gtk_entry_get_text(GTK_ENTRY(io->graphs[i].filter_field)); + fprintf(fp, "# Graph%d: %s", i + 1, + ((filter==NULL) || (filter[0]==0)) ? "all" : filter); + + if ( io->count_type == COUNT_TYPE_ADVANCED ) { + field = (char *)gtk_entry_get_text(GTK_ENTRY(io->graphs[i].calc_field)); + fprintf(fp, ", %s on %s\n", calc_type_names[io->graphs[i].calc_type], field); + } else + fprintf(fp, "\n"); + } + fprintf(fp, "################################################################################\n"); + + /* find the last graph displayed */ + + for( i = (MAX_GRAPHS - 1); i >= 0 ; i-- ) + if(io->graphs[i].display) { + lastgraph = i; + break; + } + + /* save graphs data */ + + for( j = 0; j < (io->num_items - 1); j++ ) { + + for( i = 0; i < MAX_GRAPHS; i++ ) { + + /* save only displayed graphs */ + + if(!io->graphs[i].display) + continue; + + /* save the point in the form it is displayed */ + + if ( i != lastgraph ) + fprintf(fp, "%d,", get_it_value(io, i, j)); + else + fprintf(fp, "%d\n", get_it_value(io, i, j)); + } + } + + fclose(fp); + g_free(csvf_name); + window_destroy(GTK_WIDGET(io->save_as_w)); +} static void +iostat_save_as_destroy_cb(GtkWidget *win _U_, gpointer data _U_) +{ + io_stat_t *io = (io_stat_t *)data; + io->save_as_w = NULL; +} + +/* based on file_dlg.c code */ +static void +iostat_dlg_save_as_cb(GtkWidget *bt_save _U_, gpointer data _U_) +{ + io_stat_t *io = (io_stat_t *)data; + gboolean sth_to_save = FALSE; + gint32 i; + + /* check for something to save */ + + for( i = 0; i < MAX_GRAPHS; i++ ) + if(io->graphs[i].display) + sth_to_save = TRUE; + + if ( (!sth_to_save) || (io->num_items == 0) ) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "There is no data to save."); + return; + } + + if (io->save_as_w != NULL) { + /* there is already a Save dialog box; reactivate it. */ + reactivate_window(io->save_as_w); + return; + } + + /* file selection from dlg_util */ + io->save_as_w = file_selection_new("Ethereal: Save Graphs Data as CSV", FILE_SELECTION_SAVE); + + SIGNAL_CONNECT(io->save_as_w, "destroy", iostat_save_as_destroy_cb, io); + +#if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2 + if (gtk_dialog_run(GTK_DIALOG(io->save_as_w)) == GTK_RESPONSE_ACCEPT) { + iostat_save_as_ok_cb(io->save_as_w, io); + } else { + window_destroy(io->save_as_w); + } +#else + /* Connect the ok_button to iostat_save_as_ok_cb function and pass along a pointer to io */ + SIGNAL_CONNECT(GTK_FILE_SELECTION(io->save_as_w)->ok_button, "clicked", + iostat_save_as_ok_cb, io); + + window_set_cancel_button(io->save_as_w, + GTK_FILE_SELECTION(io->save_as_w)->cancel_button, + window_cancel_button_cb); + + SIGNAL_CONNECT(io->save_as_w, "delete_event", window_delete_event_cb, NULL); + + gtk_file_selection_set_filename(GTK_FILE_SELECTION(io->save_as_w), ""); + + gtk_widget_show(io->save_as_w); + window_present(io->save_as_w); +#endif +} + + +static void init_io_stat_window(io_stat_t *io) { GtkWidget *vbox; GtkWidget *hbox; - GtkWidget *bt_close; + GtkWidget *bt_close; + GtkWidget *bt_save; /* create the main window */ io->window=window_new(GTK_WINDOW_TOPLEVEL, "I/O Graphs"); @@ -1883,7 +2044,7 @@ hbox=gtk_hbox_new(FALSE, 3); gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); - gtk_container_border_width(GTK_CONTAINER(hbox), 3); + gtk_container_border_width(GTK_CONTAINER(hbox), 3); gtk_box_set_child_packing(GTK_BOX(vbox), hbox, FALSE, FALSE, 0, GTK_PACK_START); gtk_widget_show(hbox); @@ -1892,17 +2053,20 @@ io_stat_set_title(io); - hbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL); + hbox = dlg_button_row_new(GTK_STOCK_SAVE, GTK_STOCK_CLOSE, NULL); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); - gtk_widget_show(hbox); + gtk_widget_show(hbox); + + bt_close = OBJECT_GET_DATA(hbox, GTK_STOCK_CLOSE); + window_set_cancel_button(io->window, bt_close, window_cancel_button_cb); + + bt_save = OBJECT_GET_DATA(hbox, GTK_STOCK_SAVE); + SIGNAL_CONNECT(bt_save, "clicked", iostat_dlg_save_as_cb, io); - bt_close = OBJECT_GET_DATA(hbox, GTK_STOCK_CLOSE); - window_set_cancel_button(io->window, bt_close, window_cancel_button_cb); - - SIGNAL_CONNECT(io->window, "delete_event", window_delete_event_cb, NULL); - - gtk_widget_show(io->window); - window_present(io->window); + SIGNAL_CONNECT(io->window, "delete_event", window_delete_event_cb, NULL); + + gtk_widget_show(io->window); + window_present(io->window); }
- Follow-Ups:
- Re: [Ethereal-dev] [PATCH] export data as CSV for iostat
- From: ronnie sahlberg
- Re: [Ethereal-dev] [PATCH] export data as CSV for iostat
- Prev by Date: Re: [Ethereal-dev] Patch to packet-http.c - Authentication 'Negotiate' can also be GSSAPI, not just NTLMSSP
- Next by Date: Re: [Ethereal-dev] [PATCH] export data as CSV for iostat
- Previous by thread: Re: [Ethereal-dev] Reassembling out of order packets
- Next by thread: Re: [Ethereal-dev] [PATCH] export data as CSV for iostat
- Index(es):