From bc8e5204396969ed21d9c5c518e25ea8b218daf5 Mon Sep 17 00:00:00 2001 From: Chris Maynard Date: Wed, 24 Oct 2012 17:46:16 +0000 Subject: Allow to be successfully sscanf'd no matter the locale for the decimal symbol. Fixes https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=2880 (again). #BACKPORT(1.8) svn path=/trunk/; revision=45770 --- ui/cli/tap-iostat.c | 247 +++++++++++++++++++++++++++------------------------- 1 file changed, 129 insertions(+), 118 deletions(-) (limited to 'ui/cli') diff --git a/ui/cli/tap-iostat.c b/ui/cli/tap-iostat.c index b0bc46391f..65d7cb7522 100644 --- a/ui/cli/tap-iostat.c +++ b/ui/cli/tap-iostat.c @@ -36,14 +36,14 @@ #include "globals.h" #define CALC_TYPE_FRAMES 0 -#define CALC_TYPE_BYTES 1 -#define CALC_TYPE_FRAMES_AND_BYTES 2 -#define CALC_TYPE_COUNT 3 -#define CALC_TYPE_SUM 4 -#define CALC_TYPE_MIN 5 -#define CALC_TYPE_MAX 6 -#define CALC_TYPE_AVG 7 -#define CALC_TYPE_LOAD 8 +#define CALC_TYPE_BYTES 1 +#define CALC_TYPE_FRAMES_AND_BYTES 2 +#define CALC_TYPE_COUNT 3 +#define CALC_TYPE_SUM 4 +#define CALC_TYPE_MIN 5 +#define CALC_TYPE_MAX 6 +#define CALC_TYPE_AVG 7 +#define CALC_TYPE_LOAD 8 typedef struct { const char *func_name; @@ -102,7 +102,7 @@ iostat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt, const void *du GPtrArray *gp; guint i; int ftype; - + mit = (io_stat_item_t *) arg; parent = mit->parent; relative_time = (guint64)((pinfo->fd->rel_ts.secs*1000000) + ((pinfo->fd->rel_ts.nsecs+500)/1000)); @@ -120,7 +120,7 @@ iostat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt, const void *du } /* If we have moved into a new interval (row), create a new io_stat_item_t struct for every interval - * between the last struct and this one. If an item was not found in a previous interval, an empty + * between the last struct and this one. If an item was not found in a previous interval, an empty * struct will be created for it. */ rt = relative_time; while (rt >= it->time + parent->interval) { @@ -182,7 +182,7 @@ iostat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt, const void *du it->counter += (gint64)fvalue_get_integer64(&((field_info *)gp->pdata[i])->value); break; case FT_FLOAT: - it->float_counter += + it->float_counter += (gfloat)fvalue_get_floating(&((field_info *)gp->pdata[i])->value); break; case FT_DOUBLE: @@ -242,7 +242,7 @@ iostat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt, const void *du val = fvalue_get_integer64(&((field_info *)gp->pdata[i])->value); if((it->frames==1 && i==0) || ((gint64)val < (gint64)it->counter)) { it->counter=val; - } + } break; case FT_FLOAT: float_val=(gfloat)fvalue_get_floating(&((field_info *)gp->pdata[i])->value); @@ -254,7 +254,7 @@ iostat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt, const void *du double_val=fvalue_get_floating(&((field_info *)gp->pdata[i])->value); if((it->frames==1 && i==0) || (double_val < it->double_counter)) { it->double_counter=double_val; - } + } break; case FT_RELATIVE_TIME: new_time = (nstime_t *)fvalue_get(&((field_info *)gp->pdata[i])->value); @@ -294,7 +294,7 @@ iostat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt, const void *du break; case FT_UINT64: val = fvalue_get_integer64(&((field_info *)gp->pdata[i])->value); - if(val > it->counter) + if(val > it->counter) it->counter=val; break; case FT_INT8: @@ -302,12 +302,12 @@ iostat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt, const void *du case FT_INT24: case FT_INT32: val = fvalue_get_sinteger(&((field_info *)gp->pdata[i])->value); - if((gint32)val > (gint32)it->counter) + if((gint32)val > (gint32)it->counter) it->counter=val; break; case FT_INT64: val = fvalue_get_integer64(&((field_info *)gp->pdata[i])->value); - if ((gint64)val > (gint64)it->counter) + if ((gint64)val > (gint64)it->counter) it->counter=val; break; case FT_FLOAT: @@ -341,7 +341,7 @@ iostat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt, const void *du gp=proto_get_finfo_ptr_array(edt->tree, it->hf_index); if(gp){ guint64 val; - + ftype=proto_registrar_get_ftype(it->hf_index); for(i=0;ilen;i++){ it->num++; @@ -420,21 +420,21 @@ iostat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt, const void *du } break; } - /* Store the highest value for this item in order to determine the width of each stat column. + /* Store the highest value for this item in order to determine the width of each stat column. * For real numbers we only need to know its magnitude (the value to the left of the decimal point * so round it up before storing it as an integer in max_vals. For AVG of RELATIVE_TIME fields, * calc the average, round it to the next second and store the seconds. For all other calc types - * of RELATIVE_TIME fields, store the counters without modification. + * of RELATIVE_TIME fields, store the counters without modification. * fields. */ switch(it->calc_type) { case CALC_TYPE_FRAMES: case CALC_TYPE_FRAMES_AND_BYTES: - parent->max_frame[it->colnum] = + parent->max_frame[it->colnum] = MAX(parent->max_frame[it->colnum], it->frames); if (it->calc_type==CALC_TYPE_FRAMES_AND_BYTES) - parent->max_vals[it->colnum] = + parent->max_vals[it->colnum] = MAX(parent->max_vals[it->colnum], it->counter); - + case CALC_TYPE_BYTES: case CALC_TYPE_COUNT: case CALC_TYPE_LOAD: @@ -446,20 +446,20 @@ iostat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt, const void *du ftype=proto_registrar_get_ftype(it->hf_index); switch(ftype) { case FT_FLOAT: - parent->max_vals[it->colnum] = + parent->max_vals[it->colnum] = MAX(parent->max_vals[it->colnum], (guint64)(it->float_counter+0.5)); break; case FT_DOUBLE: - parent->max_vals[it->colnum] = + parent->max_vals[it->colnum] = MAX(parent->max_vals[it->colnum],(guint64)(it->double_counter+0.5)); break; case FT_RELATIVE_TIME: - parent->max_vals[it->colnum] = - MAX(parent->max_vals[it->colnum], it->counter); - break; + parent->max_vals[it->colnum] = + MAX(parent->max_vals[it->colnum], it->counter); + break; default: /* UINT16-64 and INT8-64 */ - parent->max_vals[it->colnum] = + parent->max_vals[it->colnum] = MAX(parent->max_vals[it->colnum], it->counter); break; } @@ -470,20 +470,20 @@ iostat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt, const void *du ftype=proto_registrar_get_ftype(it->hf_index); switch(ftype) { case FT_FLOAT: - parent->max_vals[it->colnum] = + parent->max_vals[it->colnum] = MAX(parent->max_vals[it->colnum], (guint64)it->float_counter/it->num); break; case FT_DOUBLE: - parent->max_vals[it->colnum] = + parent->max_vals[it->colnum] = MAX(parent->max_vals[it->colnum],(guint64)it->double_counter/it->num); break; case FT_RELATIVE_TIME: - parent->max_vals[it->colnum] = - MAX(parent->max_vals[it->colnum], ((it->counter/it->num) + 500000000) / NANOSECS_PER_SEC); + parent->max_vals[it->colnum] = + MAX(parent->max_vals[it->colnum], ((it->counter/it->num) + 500000000) / NANOSECS_PER_SEC); break; default: /* UINT16-64 and INT8-64 */ - parent->max_vals[it->colnum] = + parent->max_vals[it->colnum] = MAX(parent->max_vals[it->colnum], it->counter/it->num); break; } @@ -491,21 +491,21 @@ iostat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt, const void *du return TRUE; } -static int +static int magnitude (guint64 val, int max_w) { int i, mag=0; for (i=0; i 0 && len < 6) { - spaces_ptr = &spaces[len]; + spaces_ptr = &spaces[len]; if ((lenval-lenlab)%2==0) { printf("%s%s%s|", spaces_ptr, label, spaces_ptr); } else { - printf("%s%s%s|", spaces_ptr-1, label, spaces_ptr); + printf("%s%s%s|", spaces_ptr-1, label, spaces_ptr); } } else if (len > 0 && len <= 15) { printf("%s|", label); @@ -546,7 +546,7 @@ iostat_draw(void *arg) io_stat_item_t *mit, **stat_cols, *item, **item_in_column; gboolean last_row=FALSE; io_stat_t *iot; - column_width *col_w; + column_width *col_w; struct tm * tm_time; time_t the_time; @@ -574,19 +574,19 @@ iostat_draw(void *arg) /* Calc the capture duration's magnitude (dur_mag) */ dur_secs = (int)duration/1000000; dur_mag = magnitude((guint64)dur_secs, 5); - g_snprintf(dur_mag_s, 3, "%u", dur_mag); + g_snprintf(dur_mag_s, 3, "%u", dur_mag); /* Calc the interval's magnitude */ - invl_mag = magnitude((guint64)interval/1000000, 5); + invl_mag = magnitude((guint64)interval/1000000, 5); /* Set or get the interval precision */ if (interval==duration) { - /* + /* * An interval arg of 0 or an interval size exceeding the capture duration was specified. * Set the decimal precision of duration based on its magnitude. */ if (dur_mag >= 2) invl_prec = 1; - else if (dur_mag==1) + else if (dur_mag==1) invl_prec = 3; else invl_prec = 6; @@ -602,7 +602,7 @@ iostat_draw(void *arg) for (i=0; iinterval==G_MAXINT32) + if (iot->interval==G_MAXINT32) interval = duration; /* Recalc the dur_mag in case rounding has increased its magnitude */ @@ -610,18 +610,18 @@ iostat_draw(void *arg) dur_mag = magnitude((guint64)dur_secs, 5); /* Calc the width of the time interval column (incl borders and padding). */ - if (invl_prec==0) + if (invl_prec==0) invl_col_w = (2*dur_mag) + 8; else invl_col_w = (2*dur_mag) + (2*invl_prec) + 10; - /* Update the width of the time interval column for "-t ad" */ - if (timestamp_get_type()==TS_ABSOLUTE_WITH_DATE) + /* Update the width of the time interval column for "-t ad" */ + if (timestamp_get_type()==TS_ABSOLUTE_WITH_DATE) invl_col_w = MAX(invl_col_w, 23); - else - invl_col_w = MAX(invl_col_w, 12); + else + invl_col_w = MAX(invl_col_w, 12); - borderlen = MAX(borderlen, invl_col_w); + borderlen = MAX(borderlen, invl_col_w); /* Calc the total width of each row in the stats table and build the printf format string for each * column based on its field type, width, and name length. @@ -645,9 +645,9 @@ iostat_draw(void *arg) g_snprintf(fr_mag_s, 3, "%u", fr_mag); if (type==CALC_TYPE_FRAMES) { - fmt = g_strconcat(" %", fr_mag_s, "u |", NULL); - } else { - /* CALC_TYPE_FRAMES_AND_BYTES + fmt = g_strconcat(" %", fr_mag_s, "u |", NULL); + } else { + /* CALC_TYPE_FRAMES_AND_BYTES */ val_mag = magnitude(iot->max_vals[j], 15); val_mag = MAX(5, val_mag); @@ -670,10 +670,10 @@ iostat_draw(void *arg) g_snprintf(val_mag_s, 3, "%u", val_mag); fmt = g_strconcat(" %", val_mag_s, G_GINT64_MODIFIER, "u |", NULL); break; - + default: ftype = proto_registrar_get_ftype(stat_cols[j]->hf_index); - switch (ftype) { + switch (ftype) { case FT_FLOAT: case FT_DOUBLE: val_mag = magnitude(iot->max_vals[j], 15); @@ -682,7 +682,7 @@ iostat_draw(void *arg) col_w[j].val = val_mag + 7; break; case FT_RELATIVE_TIME: - /* Convert FT_RELATIVE_TIME field to seconds + /* Convert FT_RELATIVE_TIME field to seconds * CALC_TYPE_LOAD was already converted in iostat_packet() ) */ if (type==CALC_TYPE_LOAD) { iot->max_vals[j] /= interval; @@ -693,14 +693,14 @@ iostat_draw(void *arg) g_snprintf(val_mag_s, 3, "%u", val_mag); fmt = g_strconcat(" %", val_mag_s, "u.%06u |", NULL); col_w[j].val = val_mag + 7; - break; - + break; + default: val_mag = magnitude(iot->max_vals[j], 15); val_mag = MAX(namelen, val_mag); col_w[j].val = val_mag; g_snprintf(val_mag_s, 3, "%u", val_mag); - + switch (ftype) { case FT_UINT8: case FT_UINT16: @@ -708,7 +708,7 @@ iostat_draw(void *arg) case FT_UINT32: case FT_UINT64: fmt = g_strconcat(" %", val_mag_s, G_GINT64_MODIFIER, "u |", NULL); - break; + break; case FT_INT8: case FT_INT16: case FT_INT24: @@ -720,11 +720,11 @@ iostat_draw(void *arg) } /* End of ftype switch */ } /* End of calc_type switch */ tabrow_w += col_w[j].val + 3; - if (fmt) + if (fmt) fmts[j] = fmt; } /* End of for loop (columns) */ - borderlen = MAX(borderlen, tabrow_w); + borderlen = MAX(borderlen, tabrow_w); /* Calc the max width of the list of filters. */ maxfltr_w = 0; @@ -739,7 +739,7 @@ iostat_draw(void *arg) /* The stat table is not wrapped (by tshark) but filter is wrapped at the width of the stats table * (which currently = borderlen); however, if the filter width exceeds the table width and the * table width is less than 102 bytes, set borderlen to the lesser of the max filter width and 102. - * The filters will wrap at the lesser of borderlen-2 and the last space in the filter. + * The filters will wrap at the lesser of borderlen-2 and the last space in the filter. * NOTE: 102 is the typical size of a user window when the font is fixed width (e.g., COURIER 10). * XXX: A pref could be added to change the max width from the default size of 102. */ if (maxfltr_w > borderlen && borderlen < 102) @@ -747,27 +747,27 @@ iostat_draw(void *arg) /* Prevent double right border by adding a space */ if (borderlen-tabrow_w==1) - borderlen++; + borderlen++; /* Display the top border */ printf("\n"); for (i=0; i 0) { - g_snprintf(invl_prec_s, 3, "%u", invl_prec); - invl_fmt = g_strconcat("%", invl_mag_s, "u.%0", invl_prec_s, "u", NULL); + g_snprintf(invl_prec_s, 3, "%u", invl_prec); + invl_fmt = g_strconcat("%", invl_mag_s, "u.%0", invl_prec_s, "u", NULL); if (interval==duration) { full_fmt = g_strconcat("| Interval size: ", invl_fmt, " secs (dur)%s", NULL); spaces_s = &spaces[30+invl_mag+invl_prec]; @@ -786,24 +786,24 @@ iostat_draw(void *arg) g_free(invl_fmt); g_free(full_fmt); - if (invl_prec > 0) + if (invl_prec > 0) invl_fmt = g_strconcat("%", dur_mag_s, "u.%0", invl_prec_s, "u", NULL); - else + else invl_fmt = g_strconcat("%", dur_mag_s, "u", NULL); - + /* Display the list of filters and their column numbers vertically */ printf("|\n| Col"); for(j=0; jfilters[j] || (iot->filters[j]==0)) { - /* + if (!iot->filters[j] || (iot->filters[j]==0)) { + /* * An empty (no filter) comma field was specified */ spaces_s = &spaces[16 + 10]; printf("Frames and bytes%s|\n", spaces_s); } else { filter = iot->filters[j]; len_filt = (int) strlen(filter); - + /* If the width of the widest filter exceeds the width of the stat table, borderlen has * been set to 102 bytes above and filters wider than 102 will wrap at 91 bytes. */ if (len_filt+11 <= borderlen) { @@ -818,11 +818,11 @@ iostat_draw(void *arg) const gchar *pos; gsize len; int next_start, max_w=borderlen-11; - + do { if (len_filt > max_w) { sfilter1 = g_strndup( (gchar *) filter, (gsize) max_w); - /* + /* * Find the pos of the last space in sfilter1. If a space is found, set * sfilter2 to the string prior to that space and print it; otherwise, wrap * the filter at max_w. */ @@ -846,7 +846,7 @@ iostat_draw(void *arg) printf("%s%s|\n", filter, &spaces[((int)strlen(filter))+10]); break; } - } while (1); + } while (1); } } } @@ -865,11 +865,11 @@ iostat_draw(void *arg) for(j=0; jcalc_type==CALC_TYPE_FRAMES_AND_BYTES) - spaces_s = &spaces[borderlen - (col_w[j].fr + col_w[j].val)] - 3; + spaces_s = &spaces[borderlen - (col_w[j].fr + col_w[j].val)] - 3; else if (item->calc_type==CALC_TYPE_FRAMES) - spaces_s = &spaces[borderlen - col_w[j].fr]; + spaces_s = &spaces[borderlen - col_w[j].fr]; else - spaces_s = &spaces[borderlen - col_w[j].val]; + spaces_s = &spaces[borderlen - col_w[j].val]; printf("%-2u%s|", j+1, spaces_s); } @@ -877,15 +877,15 @@ iostat_draw(void *arg) filler_s = &spaces[tabrow_w+1]; printf("%s|", filler_s); } - - k = 11; + + k = 11; switch (timestamp_get_type()) { case TS_ABSOLUTE: printf("\n| Time "); break; case TS_ABSOLUTE_WITH_DATE: printf("\n| Date and time"); - k = 16; + k = 16; break; case TS_RELATIVE: case TS_NOT_SET: @@ -895,7 +895,7 @@ iostat_draw(void *arg) break; } - spaces_s = &spaces[borderlen-(invl_col_w-k)]; + spaces_s = &spaces[borderlen-(invl_col_w-k)]; printf("%s|", spaces_s); /* Display the stat label in each column */ @@ -932,7 +932,7 @@ iostat_draw(void *arg) item_in_column[j] = stat_cols[j]; } - /* Display the table values + /* Display the table values * * The outer loop is for time interval rows and the inner loop is for stat column items.*/ for (i=0; itm_hour, tm_time->tm_min, tm_time->tm_sec); break; - + case TS_ABSOLUTE_WITH_DATE: printf("| %04d-%02d-%02d %02d:%02d:%02d |", tm_time->tm_year + 1900, @@ -969,7 +969,7 @@ iostat_draw(void *arg) tm_time->tm_min, tm_time->tm_sec); break; - + case TS_RELATIVE: case TS_NOT_SET: @@ -996,7 +996,7 @@ iostat_draw(void *arg) /* Display stat values in each column for this row */ for (j=0; jcalc_type) { @@ -1061,8 +1061,8 @@ iostat_draw(void *arg) case FT_RELATIVE_TIME: if (!last_row) { printf(fmt, - (int) (item->counter/interval), - (int)((item->counter%interval)*1000000 / interval)); + (int) (item->counter/interval), + (int)((item->counter%interval)*1000000 / interval)); } else { printf(fmt, (int) (item->counter/(invl_end-t)), @@ -1077,7 +1077,7 @@ iostat_draw(void *arg) if (fmt) g_free(fmt); } else { - item_in_column[j] = item_in_column[j]->next; + item_in_column[j] = item_in_column[j]->next; } } else { printf(fmt, (guint64)0); @@ -1087,7 +1087,7 @@ iostat_draw(void *arg) printf("%s|", filler_s); printf("\n"); t += interval; - + } for(i=0;iitems[i].calc_type==CALC_TYPE_FRAMES || io->items[i].calc_type==CALC_TYPE_BYTES){ if(parenp!=p) { - fprintf(stderr, + fprintf(stderr, "\ntshark: %s does not require or allow a field name within the parens.\n", calc_type_table[j].func_name); exit(10); @@ -1274,13 +1274,29 @@ iostat_init(const char *optarg, void* userdata _U_) gdouble interval_float; guint32 idx=0, i; io_stat_t *io; - const gchar *filters=NULL, *str, *pos; + const gchar *filters, *str, *pos; - if (sscanf(optarg, "io,stat,%lf,%n", &interval_float, (int *)&idx)==0) { - fprintf(stderr, "\ntshark: invalid \"-z io,stat,[,]\" argument\n"); + if ((*(optarg+(strlen(optarg)-1)) == ',') || + (sscanf(optarg, "io,stat,%lf%n", &interval_float, (int *)&idx) != 1) || + (idx < 8)) { + fprintf(stderr, "\ntshark: invalid \"-z io,stat,[,][,]...\" argument\n"); exit(1); } + filters=optarg+idx; + if (*filters) { + if (*filters != ',') { + /* For locale's that use ',' instead of '.', the comma might + * have been consumed during the floating point conversion. */ + --filters; + if (*filters != ',') { + fprintf(stderr, "\ntshark: invalid \"-z io,stat,[,][,]...\" argument\n"); + exit(1); + } + } + } else + filters=NULL; + switch (timestamp_get_type()) { case TS_DELTA: case TS_DELTA_DIS: @@ -1289,11 +1305,11 @@ iostat_init(const char *optarg, void* userdata _U_) case TS_UTC_WITH_DATE: fprintf(stderr, "\ntshark: invalid -t operand. io,stat only supports -t \n"); exit(1); - default: - break; + default: + break; } - - io = (io_stat_t *) g_malloc(sizeof(io_stat_t)); + + io = (io_stat_t *) g_malloc(sizeof(io_stat_t)); /* If interval is 0, calculate statistics over the whole file by setting the interval to * G_MAXINT32 */ @@ -1306,7 +1322,7 @@ iostat_init(const char *optarg, void* userdata _U_) /* * Determine what interval precision the user has specified */ io->invl_prec = 6; - for (i=10; i<10000000; i*=10) { + for (i=10; i<10000000; i*=10) { if (io->interval%i > 0) break; io->invl_prec--; @@ -1322,17 +1338,12 @@ iostat_init(const char *optarg, void* userdata _U_) io->num_cols = 1; io->start_time=0; - if (idx) { - filters = optarg + idx; - if (strlen(filters) > 0 ) { - str = filters; - while((str = strchr(str, ','))) { - io->num_cols++; - str++; - } + if (filters && (*filters != '\0')) { + str = filters; + while((str = strchr(str, ','))) { + io->num_cols++; + str++; } - } else { - filters=NULL; } io->items = (io_stat_item_t *) g_malloc(sizeof(io_stat_item_t) * io->num_cols); @@ -1343,7 +1354,7 @@ iostat_init(const char *optarg, void* userdata _U_) for (i=0; inum_cols; i++) { io->max_vals[i] = 0; io->max_frame[i] = 0; - } + } /* Register a tap listener for each filter */ if((!filters) || (filters[0]==0)) { -- cgit v1.2.3