Bug Summary

File:builds/wireshark/wireshark/ui/cli/tap-iostat.c
Warning:line 1649, column 23
Potential leak of memory pointed to by 'filter'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name tap-iostat.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-18/lib/clang/18 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -dwarf-debug-flags /usr/lib/llvm-18/bin/clang -### --analyze -x c -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -fvisibility=hidden -fexcess-precision=fast -fstrict-flex-arrays=3 -fstack-clash-protection -fcf-protection=full -D _GLIBCXX_ASSERTIONS -fstack-protector-strong -fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -fexceptions -Wno-format-truncation -Wno-format-nonliteral -fdiagnostics-color=always -Wno-pointer-sign -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -std=gnu11 -fPIE /builds/wireshark/wireshark/ui/cli/tap-iostat.c -o /builds/wireshark/wireshark/sbout/2025-05-05-100256-3825-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-05-05-100256-3825-1 -x c /builds/wireshark/wireshark/ui/cli/tap-iostat.c
1/* tap-iostat.c
2 * iostat 2002 Ronnie Sahlberg
3 *
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11#include "config.h"
12
13#include <stdlib.h>
14#include <string.h>
15#include <locale.h>
16
17#include <epan/epan_dissect.h>
18#include <epan/tap.h>
19#include <epan/stat_tap_ui.h>
20#include "globals.h"
21#include <wsutil/ws_assert.h>
22#include <wsutil/time_util.h>
23#include <wsutil/to_str.h>
24#include <wsutil/cmdarg_err.h>
25
26#define CALC_TYPE_FRAMES0 0
27#define CALC_TYPE_BYTES1 1
28#define CALC_TYPE_FRAMES_AND_BYTES2 2
29#define CALC_TYPE_COUNT3 3
30#define CALC_TYPE_SUM4 4
31#define CALC_TYPE_MIN5 5
32#define CALC_TYPE_MAX6 6
33#define CALC_TYPE_AVG7 7
34#define CALC_TYPE_LOAD8 8
35
36void register_tap_listener_iostat(void);
37
38typedef struct {
39 const char *func_name;
40 int calc_type;
41} calc_type_ent_t;
42
43static calc_type_ent_t calc_type_table[] = {
44 { "FRAMES", CALC_TYPE_FRAMES0 },
45 { "BYTES", CALC_TYPE_BYTES1 },
46 { "FRAMES BYTES", CALC_TYPE_FRAMES_AND_BYTES2 },
47 { "COUNT", CALC_TYPE_COUNT3 },
48 { "SUM", CALC_TYPE_SUM4 },
49 { "MIN", CALC_TYPE_MIN5 },
50 { "MAX", CALC_TYPE_MAX6 },
51 { "AVG", CALC_TYPE_AVG7 },
52 { "LOAD", CALC_TYPE_LOAD8 },
53 { NULL((void*)0), 0 }
54};
55
56typedef struct _io_stat_t {
57 uint64_t interval; /* The user-specified time interval (us) */
58 unsigned invl_prec; /* Decimal precision of the time interval (1=10s, 2=100s etc) */
59 unsigned int num_cols; /* The number of columns of stats in the table */
60 struct _io_stat_item_t *items; /* Each item is a single cell in the table */
61 nstime_t start_time; /* Time of first frame matching the filter */
62 /* The following are all per-column fixed information arrays */
63 const char **filters; /* 'io,stat' cmd strings (e.g., "AVG(smb.time)smb.time") */
64 uint64_t *max_vals; /* The max value sans the decimal or nsecs portion in each stat column */
65 uint32_t *max_frame; /* The max frame number displayed in each stat column */
66 int *hf_indexes;
67 int *calc_type; /* The statistic type */
68} io_stat_t;
69
70typedef struct _io_stat_item_t {
71 io_stat_t *parent;
72 struct _io_stat_item_t *next;
73 struct _io_stat_item_t *prev;
74 uint64_t start_time; /* Time since start of capture (us)*/
75 int colnum; /* Column number of this stat (0 to n) */
76 uint32_t frames;
77 uint32_t num; /* The sample size of a given statistic (only needed for AVG) */
78 union { /* The accumulated data for the calculation of that statistic */
79 uint64_t counter;
80 float float_counter;
81 double double_counter;
82 };
83} io_stat_item_t;
84
85static char *io_decimal_point;
86
87#define NANOSECS_PER_SEC1000000000UL UINT64_C(1000000000)1000000000UL
88
89static uint64_t last_relative_time;
90
91static tap_packet_status
92iostat_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt, const void *dummy _U___attribute__((unused)), tap_flags_t flags _U___attribute__((unused)))
93{
94 io_stat_t *parent;
95 io_stat_item_t *mit;
96 io_stat_item_t *it;
97 uint64_t relative_time, rt;
98 const nstime_t *new_time;
99 GPtrArray *gp;
100 unsigned i;
101 int ftype;
102
103 mit = (io_stat_item_t *) arg;
104 parent = mit->parent;
105
106 /* If this frame's relative time is negative, set its relative time to last_relative_time
107 rather than disincluding it from the calculations. */
108 if ((pinfo->rel_ts.secs >= 0) && (pinfo->rel_ts.nsecs >= 0)) {
109 relative_time = ((uint64_t)pinfo->rel_ts.secs * UINT64_C(1000000)1000000UL) +
110 ((uint64_t)((pinfo->rel_ts.nsecs+500)/1000));
111 last_relative_time = relative_time;
112 } else {
113 relative_time = last_relative_time;
114 }
115
116 if (nstime_is_unset(&mit->parent->start_time)) {
117 nstime_delta(&mit->parent->start_time, &pinfo->abs_ts, &pinfo->rel_ts);
118 }
119
120 /* The prev item is always the last interval in which we saw packets. */
121 it = mit->prev;
122
123 /* If we have moved into a new interval (row), create a new io_stat_item_t struct for every interval
124 * between the last struct and this one. If an item was not found in a previous interval, an empty
125 * struct will be created for it. */
126 rt = relative_time;
127 while (rt >= it->start_time + parent->interval) {
128 it->next = g_new(io_stat_item_t, 1)((io_stat_item_t *) g_malloc_n ((1), sizeof (io_stat_item_t))
)
;
129 it->next->prev = it;
130 it->next->next = NULL((void*)0);
131 it = it->next;
132 mit->prev = it;
133
134 it->start_time = it->prev->start_time + parent->interval;
135 it->frames = 0;
136 it->counter = 0; /* 64-bit, type-punning with double is fine */
137 it->num = 0;
138 it->colnum = it->prev->colnum;
139 }
140
141 /* Store info in the current structure */
142 it->frames++;
143
144 switch (parent->calc_type[it->colnum]) {
145 case CALC_TYPE_FRAMES0:
146 case CALC_TYPE_BYTES1:
147 case CALC_TYPE_FRAMES_AND_BYTES2:
148 it->counter += pinfo->fd->pkt_len;
149 break;
150 case CALC_TYPE_COUNT3:
151 gp = proto_get_finfo_ptr_array(edt->tree, parent->hf_indexes[it->colnum]);
152 if (gp) {
153 it->counter += gp->len;
154 }
155 break;
156 case CALC_TYPE_SUM4:
157 gp = proto_get_finfo_ptr_array(edt->tree, parent->hf_indexes[it->colnum]);
158 if (gp) {
159 uint64_t val;
160
161 for (i=0; i<gp->len; i++) {
162 switch (proto_registrar_get_ftype(parent->hf_indexes[it->colnum])) {
163 case FT_UINT8:
164 case FT_UINT16:
165 case FT_UINT24:
166 case FT_UINT32:
167 it->counter += fvalue_get_uinteger(((field_info *)gp->pdata[i])->value);
168 break;
169 case FT_UINT40:
170 case FT_UINT48:
171 case FT_UINT56:
172 case FT_UINT64:
173 it->counter += fvalue_get_uinteger64(((field_info *)gp->pdata[i])->value);
174 break;
175 case FT_INT8:
176 case FT_INT16:
177 case FT_INT24:
178 case FT_INT32:
179 it->counter += fvalue_get_sinteger(((field_info *)gp->pdata[i])->value);
180 break;
181 case FT_INT40:
182 case FT_INT48:
183 case FT_INT56:
184 case FT_INT64:
185 it->counter += (int64_t)fvalue_get_sinteger64(((field_info *)gp->pdata[i])->value);
186 break;
187 case FT_FLOAT:
188 it->float_counter +=
189 (float)fvalue_get_floating(((field_info *)gp->pdata[i])->value);
190 break;
191 case FT_DOUBLE:
192 it->double_counter += fvalue_get_floating(((field_info *)gp->pdata[i])->value);
193 break;
194 case FT_RELATIVE_TIME:
195 new_time = fvalue_get_time(((field_info *)gp->pdata[i])->value);
196 val = ((uint64_t)new_time->secs * NANOSECS_PER_SEC1000000000UL) + (uint64_t)new_time->nsecs;
197 it->counter += val;
198 break;
199 default:
200 /*
201 * "Can't happen"; see the checks
202 * in register_io_tap().
203 */
204 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "ui/cli/tap-iostat.c",
204, __func__, "assertion \"not reached\" failed")
;
205 break;
206 }
207 }
208 }
209 break;
210 case CALC_TYPE_MIN5:
211 gp = proto_get_finfo_ptr_array(edt->tree, parent->hf_indexes[it->colnum]);
212 if (gp) {
213 uint64_t val;
214 float float_val;
215 double double_val;
216
217 ftype = proto_registrar_get_ftype(parent->hf_indexes[it->colnum]);
218 for (i=0; i<gp->len; i++) {
219 switch (ftype) {
220 case FT_UINT8:
221 case FT_UINT16:
222 case FT_UINT24:
223 case FT_UINT32:
224 val = fvalue_get_uinteger(((field_info *)gp->pdata[i])->value);
225 if ((it->frames == 1 && i == 0) || (val < it->counter)) {
226 it->counter = val;
227 }
228 break;
229 case FT_UINT40:
230 case FT_UINT48:
231 case FT_UINT56:
232 case FT_UINT64:
233 val = fvalue_get_uinteger64(((field_info *)gp->pdata[i])->value);
234 if ((it->frames == 1 && i == 0) || (val < it->counter)) {
235 it->counter = val;
236 }
237 break;
238 case FT_INT8:
239 case FT_INT16:
240 case FT_INT24:
241 case FT_INT32:
242 val = fvalue_get_sinteger(((field_info *)gp->pdata[i])->value);
243 if ((it->frames == 1 && i == 0) || ((int32_t)val < (int32_t)it->counter)) {
244 it->counter = val;
245 }
246 break;
247 case FT_INT40:
248 case FT_INT48:
249 case FT_INT56:
250 case FT_INT64:
251 val = fvalue_get_sinteger64(((field_info *)gp->pdata[i])->value);
252 if ((it->frames == 1 && i == 0) || ((int64_t)val < (int64_t)it->counter)) {
253 it->counter = val;
254 }
255 break;
256 case FT_FLOAT:
257 float_val = (float)fvalue_get_floating(((field_info *)gp->pdata[i])->value);
258 if ((it->frames == 1 && i == 0) || (float_val < it->float_counter)) {
259 it->float_counter = float_val;
260 }
261 break;
262 case FT_DOUBLE:
263 double_val = fvalue_get_floating(((field_info *)gp->pdata[i])->value);
264 if ((it->frames == 1 && i == 0) || (double_val < it->double_counter)) {
265 it->double_counter = double_val;
266 }
267 break;
268 case FT_RELATIVE_TIME:
269 new_time = fvalue_get_time(((field_info *)gp->pdata[i])->value);
270 val = ((uint64_t)new_time->secs * NANOSECS_PER_SEC1000000000UL) + (uint64_t)new_time->nsecs;
271 if ((it->frames == 1 && i == 0) || (val < it->counter)) {
272 it->counter = val;
273 }
274 break;
275 default:
276 /*
277 * "Can't happen"; see the checks
278 * in register_io_tap().
279 */
280 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "ui/cli/tap-iostat.c",
280, __func__, "assertion \"not reached\" failed")
;
281 break;
282 }
283 }
284 }
285 break;
286 case CALC_TYPE_MAX6:
287 gp = proto_get_finfo_ptr_array(edt->tree, parent->hf_indexes[it->colnum]);
288 if (gp) {
289 uint64_t val;
290 float float_val;
291 double double_val;
292
293 ftype = proto_registrar_get_ftype(parent->hf_indexes[it->colnum]);
294 for (i=0; i<gp->len; i++) {
295 switch (ftype) {
296 case FT_UINT8:
297 case FT_UINT16:
298 case FT_UINT24:
299 case FT_UINT32:
300 val = fvalue_get_uinteger(((field_info *)gp->pdata[i])->value);
301 if (val > it->counter)
302 it->counter = val;
303 break;
304 case FT_UINT40:
305 case FT_UINT48:
306 case FT_UINT56:
307 case FT_UINT64:
308 val = fvalue_get_uinteger64(((field_info *)gp->pdata[i])->value);
309 if (val > it->counter)
310 it->counter = val;
311 break;
312 case FT_INT8:
313 case FT_INT16:
314 case FT_INT24:
315 case FT_INT32:
316 val = fvalue_get_sinteger(((field_info *)gp->pdata[i])->value);
317 if ((int32_t)val > (int32_t)it->counter)
318 it->counter = val;
319 break;
320 case FT_INT40:
321 case FT_INT48:
322 case FT_INT56:
323 case FT_INT64:
324 val = fvalue_get_sinteger64(((field_info *)gp->pdata[i])->value);
325 if ((int64_t)val > (int64_t)it->counter)
326 it->counter = val;
327 break;
328 case FT_FLOAT:
329 float_val = (float)fvalue_get_floating(((field_info *)gp->pdata[i])->value);
330 if (float_val > it->float_counter)
331 it->float_counter = float_val;
332 break;
333 case FT_DOUBLE:
334 double_val = fvalue_get_floating(((field_info *)gp->pdata[i])->value);
335 if (double_val > it->double_counter)
336 it->double_counter = double_val;
337 break;
338 case FT_RELATIVE_TIME:
339 new_time = fvalue_get_time(((field_info *)gp->pdata[i])->value);
340 val = ((uint64_t)new_time->secs * NANOSECS_PER_SEC1000000000UL) + (uint64_t)new_time->nsecs;
341 if (val > it->counter)
342 it->counter = val;
343 break;
344 default:
345 /*
346 * "Can't happen"; see the checks
347 * in register_io_tap().
348 */
349 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "ui/cli/tap-iostat.c",
349, __func__, "assertion \"not reached\" failed")
;
350 break;
351 }
352 }
353 }
354 break;
355 case CALC_TYPE_AVG7:
356 gp = proto_get_finfo_ptr_array(edt->tree, parent->hf_indexes[it->colnum]);
357 if (gp) {
358 uint64_t val;
359
360 ftype = proto_registrar_get_ftype(parent->hf_indexes[it->colnum]);
361 for (i=0; i<gp->len; i++) {
362 it->num++;
363 switch (ftype) {
364 case FT_UINT8:
365 case FT_UINT16:
366 case FT_UINT24:
367 case FT_UINT32:
368 val = fvalue_get_uinteger(((field_info *)gp->pdata[i])->value);
369 it->counter += val;
370 break;
371 case FT_UINT40:
372 case FT_UINT48:
373 case FT_UINT56:
374 case FT_UINT64:
375 val = fvalue_get_uinteger64(((field_info *)gp->pdata[i])->value);
376 it->counter += val;
377 break;
378 case FT_INT8:
379 case FT_INT16:
380 case FT_INT24:
381 case FT_INT32:
382 val = fvalue_get_sinteger(((field_info *)gp->pdata[i])->value);
383 it->counter += val;
384 break;
385 case FT_INT40:
386 case FT_INT48:
387 case FT_INT56:
388 case FT_INT64:
389 val = fvalue_get_sinteger64(((field_info *)gp->pdata[i])->value);
390 it->counter += val;
391 break;
392 case FT_FLOAT:
393 it->float_counter += (float)fvalue_get_floating(((field_info *)gp->pdata[i])->value);
394 break;
395 case FT_DOUBLE:
396 it->double_counter += fvalue_get_floating(((field_info *)gp->pdata[i])->value);
397 break;
398 case FT_RELATIVE_TIME:
399 new_time = fvalue_get_time(((field_info *)gp->pdata[i])->value);
400 val = ((uint64_t)new_time->secs * NANOSECS_PER_SEC1000000000UL) + (uint64_t)new_time->nsecs;
401 it->counter += val;
402 break;
403 default:
404 /*
405 * "Can't happen"; see the checks
406 * in register_io_tap().
407 */
408 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "ui/cli/tap-iostat.c",
408, __func__, "assertion \"not reached\" failed")
;
409 break;
410 }
411 }
412 }
413 break;
414 case CALC_TYPE_LOAD8:
415 gp = proto_get_finfo_ptr_array(edt->tree, parent->hf_indexes[it->colnum]);
416 if (gp) {
417 ftype = proto_registrar_get_ftype(parent->hf_indexes[it->colnum]);
418 if (ftype != FT_RELATIVE_TIME) {
419 cmdarg_err("\ntshark: LOAD() is only supported for relative-time fields such as smb.time\n");
420 return TAP_PACKET_FAILED;
421 }
422 for (i=0; i<gp->len; i++) {
423 uint64_t val;
424 int tival;
425 io_stat_item_t *pit;
426
427 new_time = fvalue_get_time(((field_info *)gp->pdata[i])->value);
428 val = ((uint64_t)new_time->secs*UINT64_C(1000000)1000000UL) + (uint64_t)(new_time->nsecs/1000);
429 tival = (int)(val % parent->interval);
430 it->counter += tival;
431 val -= tival;
432 pit = it->prev;
433 while (val > 0) {
434 if (val < (uint64_t)parent->interval) {
435 pit->counter += val;
436 break;
437 }
438 pit->counter += parent->interval;
439 val -= parent->interval;
440 pit = pit->prev;
441 }
442 }
443 }
444 break;
445 }
446 /* Store the highest value for this item in order to determine the width of each stat column.
447 * For real numbers we only need to know its magnitude (the value to the left of the decimal point
448 * so round it up before storing it as an integer in max_vals. For AVG of RELATIVE_TIME fields,
449 * calc the average, round it to the next second and store the seconds. For all other calc types
450 * of RELATIVE_TIME fields, store the counters without modification.
451 * fields. */
452 switch (parent->calc_type[it->colnum]) {
453 case CALC_TYPE_FRAMES0:
454 case CALC_TYPE_FRAMES_AND_BYTES2:
455 parent->max_frame[it->colnum] =
456 MAX(parent->max_frame[it->colnum], it->frames)(((parent->max_frame[it->colnum]) > (it->frames))
? (parent->max_frame[it->colnum]) : (it->frames))
;
457 if (parent->calc_type[it->colnum] == CALC_TYPE_FRAMES_AND_BYTES2)
458 parent->max_vals[it->colnum] =
459 MAX(parent->max_vals[it->colnum], it->counter)(((parent->max_vals[it->colnum]) > (it->counter))
? (parent->max_vals[it->colnum]) : (it->counter))
;
460 break;
461 case CALC_TYPE_BYTES1:
462 case CALC_TYPE_COUNT3:
463 case CALC_TYPE_LOAD8:
464 parent->max_vals[it->colnum] = MAX(parent->max_vals[it->colnum], it->counter)(((parent->max_vals[it->colnum]) > (it->counter))
? (parent->max_vals[it->colnum]) : (it->counter))
;
465 break;
466 case CALC_TYPE_SUM4:
467 case CALC_TYPE_MIN5:
468 case CALC_TYPE_MAX6:
469 ftype = proto_registrar_get_ftype(parent->hf_indexes[it->colnum]);
470 switch (ftype) {
471 case FT_FLOAT:
472 parent->max_vals[it->colnum] =
473 MAX(parent->max_vals[it->colnum], (uint64_t)(it->float_counter+0.5))(((parent->max_vals[it->colnum]) > ((uint64_t)(it->
float_counter+0.5))) ? (parent->max_vals[it->colnum]) :
((uint64_t)(it->float_counter+0.5)))
;
474 break;
475 case FT_DOUBLE:
476 parent->max_vals[it->colnum] =
477 MAX(parent->max_vals[it->colnum], (uint64_t)(it->double_counter+0.5))(((parent->max_vals[it->colnum]) > ((uint64_t)(it->
double_counter+0.5))) ? (parent->max_vals[it->colnum]) :
((uint64_t)(it->double_counter+0.5)))
;
478 break;
479 case FT_RELATIVE_TIME:
480 parent->max_vals[it->colnum] =
481 MAX(parent->max_vals[it->colnum], it->counter)(((parent->max_vals[it->colnum]) > (it->counter))
? (parent->max_vals[it->colnum]) : (it->counter))
;
482 break;
483 default:
484 /* UINT16-64 and INT8-64 */
485 parent->max_vals[it->colnum] =
486 MAX(parent->max_vals[it->colnum], it->counter)(((parent->max_vals[it->colnum]) > (it->counter))
? (parent->max_vals[it->colnum]) : (it->counter))
;
487 break;
488 }
489 break;
490 case CALC_TYPE_AVG7:
491 if (it->num == 0) /* avoid division by zero */
492 break;
493 ftype = proto_registrar_get_ftype(parent->hf_indexes[it->colnum]);
494 switch (ftype) {
495 case FT_FLOAT:
496 parent->max_vals[it->colnum] =
497 MAX(parent->max_vals[it->colnum], (uint64_t)it->float_counter/it->num)(((parent->max_vals[it->colnum]) > ((uint64_t)it->
float_counter/it->num)) ? (parent->max_vals[it->colnum
]) : ((uint64_t)it->float_counter/it->num))
;
498 break;
499 case FT_DOUBLE:
500 parent->max_vals[it->colnum] =
501 MAX(parent->max_vals[it->colnum], (uint64_t)it->double_counter/it->num)(((parent->max_vals[it->colnum]) > ((uint64_t)it->
double_counter/it->num)) ? (parent->max_vals[it->colnum
]) : ((uint64_t)it->double_counter/it->num))
;
502 break;
503 case FT_RELATIVE_TIME:
504 parent->max_vals[it->colnum] =
505 MAX(parent->max_vals[it->colnum], ((it->counter/(uint64_t)it->num) + UINT64_C(500000000)) / NANOSECS_PER_SEC)(((parent->max_vals[it->colnum]) > (((it->counter
/(uint64_t)it->num) + 500000000UL) / 1000000000UL)) ? (parent
->max_vals[it->colnum]) : (((it->counter/(uint64_t)it
->num) + 500000000UL) / 1000000000UL))
;
506 break;
507 default:
508 /* UINT16-64 and INT8-64 */
509 parent->max_vals[it->colnum] =
510 MAX(parent->max_vals[it->colnum], it->counter/it->num)(((parent->max_vals[it->colnum]) > (it->counter/it
->num)) ? (parent->max_vals[it->colnum]) : (it->counter
/it->num))
;
511 break;
512 }
513 }
514 return TAP_PACKET_REDRAW;
515}
516
517static unsigned int
518magnitude (uint64_t val, unsigned int max_w)
519{
520 unsigned int i, mag = 0;
521
522 for (i=0; i<max_w; i++) {
523 mag++;
524 if ((val /= 10) == 0)
525 break;
526 }
527 return(mag);
528}
529
530/*
531* Print the calc_type_table[] function label centered in the column header.
532*/
533static void
534printcenter (const char *label, int lenval, int numpad)
535{
536 int lenlab = (int) strlen(label), len;
537 const char spaces[] = " ", *spaces_ptr;
538
539 len = (int) (strlen(spaces)) - (((lenval-lenlab) / 2) + numpad);
540 if (len > 0 && len < 6) {
541 spaces_ptr = &spaces[len];
542 if ((lenval-lenlab)%2 == 0) {
543 printf("%s%s%s|", spaces_ptr, label, spaces_ptr);
544 } else {
545 printf("%s%s%s|", spaces_ptr-1, label, spaces_ptr);
546 }
547 } else if (len > 0 && len <= 15) {
548 printf("%s|", label);
549 }
550}
551
552typedef struct {
553 int fr; /* Width of this FRAMES column sans padding and border chars */
554 int val; /* Width of this non-FRAMES column sans padding and border chars */
555} column_width;
556
557static void
558fill_abs_time(const nstime_t* the_time, char *time_buf, char *decimal_point, unsigned invl_prec, bool_Bool local)
559{
560 struct tm tm, *tmp;
561 char *ptr;
562 size_t remaining = NSTIME_ISO8601_BUFSIZEsizeof("YYYY-MM-DDTHH:MM:SS.123456789Z");
563 int num_bytes;
564
565 if (local) {
566 tmp = ws_localtime_r(&the_time->secs, &tm);
567 } else {
568 tmp = ws_gmtime_r(&the_time->secs, &tm);
569 }
570
571 if (tmp == NULL((void*)0)) {
572 snprintf(time_buf, remaining, "XX:XX:XX");
573 return;
574 }
575
576 ptr = time_buf;
577 num_bytes = snprintf(time_buf, NSTIME_ISO8601_BUFSIZEsizeof("YYYY-MM-DDTHH:MM:SS.123456789Z"),
578 "%02d:%02d:%02d",
579 tmp->tm_hour,
580 tmp->tm_min,
581 tmp->tm_sec);
582 if (num_bytes < 0) {
583 // snprintf failed
584 snprintf(time_buf, remaining, "XX:XX:XX");
585 return;
586 }
587 ptr += num_bytes;
588 remaining -= num_bytes;
589 if (invl_prec != 0) {
590 num_bytes = format_fractional_part_nsecs(ptr, remaining,
591 (uint32_t)the_time->nsecs, decimal_point, invl_prec);
592 ptr += num_bytes;
593 remaining -= num_bytes;
594 }
595
596 if (!local) {
597 if (remaining == 1 && num_bytes > 0) {
598 /*
599 * If we copied a fractional part but there's only room
600 * for the terminating '\0', replace the last digit of
601 * the fractional part with the "Z". (Remaining is at
602 * least 1, otherwise we would have returned above.)
603 */
604 ptr--;
605 remaining++;
606 }
607 (void)g_strlcpy(ptr, "Z", remaining);
608 }
609 return;
610}
611
612static void
613fill_abs_ydoy_time(const nstime_t* the_time, char *time_buf, char *decimal_point, unsigned invl_prec, bool_Bool local)
614{
615 struct tm tm, *tmp;
616 char *ptr;
617 size_t remaining = NSTIME_ISO8601_BUFSIZEsizeof("YYYY-MM-DDTHH:MM:SS.123456789Z");
618 int num_bytes;
619
620 if (local) {
621 tmp = ws_localtime_r(&the_time->secs, &tm);
622 } else {
623 tmp = ws_gmtime_r(&the_time->secs, &tm);
624 }
625
626 if (tmp == NULL((void*)0)) {
627 snprintf(time_buf, remaining, "XXXX/XXX XX:XX:XX");
628 return;
629 }
630
631 ptr = time_buf;
632 num_bytes = snprintf(time_buf, NSTIME_ISO8601_BUFSIZEsizeof("YYYY-MM-DDTHH:MM:SS.123456789Z"),
633 "%04d/%03d %02d:%02d:%02d",
634 tmp->tm_year + 1900,
635 tmp->tm_yday + 1,
636 tmp->tm_hour,
637 tmp->tm_min,
638 tmp->tm_sec);
639 if (num_bytes < 0) {
640 // snprintf failed
641 snprintf(time_buf, remaining, "XXXX/XXX XX:XX:XX");
642 return;
643 }
644 ptr += num_bytes;
645 remaining -= num_bytes;
646 if (invl_prec != 0) {
647 num_bytes = format_fractional_part_nsecs(ptr, remaining,
648 (uint32_t)the_time->nsecs, decimal_point, invl_prec);
649 ptr += num_bytes;
650 remaining -= num_bytes;
651 }
652
653 if (!local) {
654 if (remaining == 1 && num_bytes > 0) {
655 /*
656 * If we copied a fractional part but there's only room
657 * for the terminating '\0', replace the last digit of
658 * the fractional part with the "Z". (Remaining is at
659 * least 1, otherwise we would have returned above.)
660 */
661 ptr--;
662 remaining++;
663 }
664 (void)g_strlcpy(ptr, "Z", remaining);
665 }
666 return;
667}
668
669/* Calc the total width of each row in the stats table and build the printf format string for each
670* column based on its field type, width, and name length.
671* NOTE: The magnitude of all types including float and double are stored in iot->max_vals which
672* is an *integer*. */
673static unsigned
674iostat_calc_cols_width_and_fmt(io_stat_t *iot, uint64_t interval, column_width* col_w, char**fmts)
675{
676 unsigned tabrow_w, type, ftype, namelen;
677 unsigned fr_mag; /* The magnitude of the max frame number in this column */
678 unsigned val_mag; /* The magnitude of the max value in this column */
679 char *fmt = NULL((void*)0);
680
681 tabrow_w = 0;
682 for (unsigned j=0; j < iot->num_cols; j++) {
683 type = iot->calc_type[j];
684 if (type == CALC_TYPE_FRAMES_AND_BYTES2) {
685 namelen = 5;
686 } else {
687 namelen = (unsigned int)strlen(calc_type_table[type].func_name);
688 }
689 if (type == CALC_TYPE_FRAMES0
690 || type == CALC_TYPE_FRAMES_AND_BYTES2) {
691
692 fr_mag = magnitude(iot->max_frame[j], 15);
693 fr_mag = MAX(6, fr_mag)(((6) > (fr_mag)) ? (6) : (fr_mag));
694 col_w[j].fr = fr_mag;
695 tabrow_w += col_w[j].fr + 3;
696
697 if (type == CALC_TYPE_FRAMES0) {
698 fmt = g_strdup_printf(" %%%uu |", fr_mag);
699 } else {
700 /* CALC_TYPE_FRAMES_AND_BYTES
701 */
702 val_mag = magnitude(iot->max_vals[j], 15);
703 val_mag = MAX(5, val_mag)(((5) > (val_mag)) ? (5) : (val_mag));
704 col_w[j].val = val_mag;
705 tabrow_w += (col_w[j].val + 3);
706 fmt = g_strdup_printf(" %%%uu | %%%u"PRIu64"l" "u" " |", fr_mag, val_mag);
707 }
708 if (fmt)
709 fmts[j] = fmt;
710 continue;
711 }
712 switch (type) {
713 case CALC_TYPE_BYTES1:
714 case CALC_TYPE_COUNT3:
715
716 val_mag = magnitude(iot->max_vals[j], 15);
717 val_mag = MAX(5, val_mag)(((5) > (val_mag)) ? (5) : (val_mag));
718 col_w[j].val = val_mag;
719 fmt = g_strdup_printf(" %%%u"PRIu64"l" "u"" |", val_mag);
720 break;
721
722 default:
723 ftype = proto_registrar_get_ftype(iot->hf_indexes[j]);
724 switch (ftype) {
725 case FT_FLOAT:
726 case FT_DOUBLE:
727 val_mag = magnitude(iot->max_vals[j], 15);
728 fmt = g_strdup_printf(" %%%u.6f |", val_mag);
729 col_w[j].val = val_mag + 7;
730 break;
731 case FT_RELATIVE_TIME:
732 /* Convert FT_RELATIVE_TIME field to seconds
733 * CALC_TYPE_LOAD was already converted in iostat_packet() ) */
734 if (type == CALC_TYPE_LOAD8) {
735 iot->max_vals[j] /= interval;
736 } else if (type != CALC_TYPE_AVG7) {
737 iot->max_vals[j] = (iot->max_vals[j] + UINT64_C(500000000)500000000UL) / NANOSECS_PER_SEC1000000000UL;
738 }
739 val_mag = magnitude(iot->max_vals[j], 15);
740 fmt = g_strdup_printf(" %%%uu.%%06u |", val_mag);
741 col_w[j].val = val_mag + 7;
742 break;
743
744 default:
745 val_mag = magnitude(iot->max_vals[j], 15);
746 val_mag = MAX(namelen, val_mag)(((namelen) > (val_mag)) ? (namelen) : (val_mag));
747 col_w[j].val = val_mag;
748
749 switch (ftype) {
750 case FT_UINT8:
751 case FT_UINT16:
752 case FT_UINT24:
753 case FT_UINT32:
754 case FT_UINT64:
755 fmt = g_strdup_printf(" %%%u"PRIu64"l" "u" " |", val_mag);
756 break;
757 case FT_INT8:
758 case FT_INT16:
759 case FT_INT24:
760 case FT_INT32:
761 case FT_INT64:
762 fmt = g_strdup_printf(" %%%u"PRId64"l" "d" " |", val_mag);
763 break;
764 }
765 } /* End of ftype switch */
766 } /* End of calc_type switch */
767 tabrow_w += col_w[j].val + 3;
768 if (fmt)
769 fmts[j] = fmt;
770 } /* End of for loop (columns) */
771
772 return tabrow_w;
773}
774
775static void
776iostat_draw_filters(unsigned borderlen, const io_stat_t *iot)
777{
778 const char *filter;
779 size_t len_filt;
780 GString *filt_str;
781
782 /* Display the list of filters and their column numbers vertically */
783 for (unsigned j=0; j<iot->num_cols; j++) {
784 if (j == 0) {
785 filt_str = g_string_new("| Col ");
786 } else {
787 filt_str = g_string_new("| ");
788 };
789 g_string_append_printf(filt_str, "%2u: ", j + 1);
790 if (!iot->filters[j]) {
791 /* An empty (no filter) comma field was specified */
792 g_string_append(filt_str, "Frames and bytes")(__builtin_constant_p ("Frames and bytes") ? __extension__ ({
const char * const __val = ("Frames and bytes"); g_string_append_len_inline
(filt_str, __val, (__val != ((void*)0)) ? (gssize) strlen ((
(__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(filt_str, "Frames and bytes", (gssize) -1))
;
793 } else {
794 filter = iot->filters[j];
795 len_filt = strlen(filter);
796 /* borderlen has been adjusted to try to accommodate the widest
797 * filter, but only up to a limit (currently 102 bytes), and so
798 * filters wider than that must still wrap. */
799 /* 11 is the length of "| Col XX: " plus the trailing "|" */
800 size_t max_w = borderlen - 11;
801
802 while (len_filt > max_w) {
803 const char *pos;
804 size_t len;
805 unsigned int next_start;
806
807 /* Find the pos of the last space in filter up to max_w. If a
808 * space is found, copy up to that space; otherwise, wrap the
809 * filter at max_w. */
810 pos = g_strrstr_len(filter, max_w, " ");
811 if (pos) {
812 len = (size_t)(pos-filter);
813 /* Skip the space when wrapping. */
814 next_start = (unsigned int) len+1;
815 } else {
816 len = max_w;
817 next_start = (unsigned int)len;
818 }
819 g_string_append_len(filt_str, filter, len)g_string_append_len_inline (filt_str, filter, len);
820 g_string_append_printf(filt_str, "%*s", (int)(borderlen - filt_str->len), "|");
821
822 puts(filt_str->str);
823 g_string_free(filt_str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(filt_str), ((!(0)))) : g_string_free_and_steal (filt_str)) :
(g_string_free) ((filt_str), ((!(0)))))
;
824
825 filt_str = g_string_new("| ");
826 filter = &filter[next_start];
827 len_filt = strlen(filter);
828 }
829
830 g_string_append(filt_str, filter)(__builtin_constant_p (filter) ? __extension__ ({ const char *
const __val = (filter); g_string_append_len_inline (filt_str
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (filt_str
, filter, (gssize) -1))
;
831 }
832 g_string_append_printf(filt_str, "%*s", (int)(borderlen - filt_str->len), "|");
833 puts(filt_str->str);
834 g_string_free(filt_str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(filt_str), ((!(0)))) : g_string_free_and_steal (filt_str)) :
(g_string_free) ((filt_str), ((!(0)))))
;
835 }
836}
837
838static void
839iostat_draw_header(unsigned borderlen, const io_stat_t *iot, const nstime_t *duration, const nstime_t *interval, ws_tsprec_e invl_prec)
840{
841 unsigned i;
842 char time_buf[NSTIME_ISO8601_BUFSIZEsizeof("YYYY-MM-DDTHH:MM:SS.123456789Z")];
843
844 /* Display the top border */
845 printf("\n");
846 for (i=0; i<borderlen; i++)
847 printf("=");
848
849 printf("\n|%-*s|\n", borderlen - 2, " IO Statistics");
850 printf("|%-*s|\n", borderlen - 2, "");
851
852 /* For some reason, we print the total duration in microsecond precision
853 * here if the interval is in seconds precision, and use the interval
854 * precision otherwise.
855 */
856 ws_tsprec_e dur_prec = (invl_prec == WS_TSPREC_SEC) ? WS_TSPREC_USEC : invl_prec;
857 nstime_t dur_rounded;
858 nstime_rounded(&dur_rounded, duration, dur_prec);
859 int dur_mag = magnitude(duration->secs, 5);
860 int dur_w = dur_mag + (invl_prec == 0 ? 0 : invl_prec+1);
861
862 GString *dur_str = g_string_new("| Duration: ");
863 display_signed_time(time_buf, NSTIME_ISO8601_BUFSIZEsizeof("YYYY-MM-DDTHH:MM:SS.123456789Z"), &dur_rounded, dur_prec);
864 g_string_append_printf(dur_str, "%*s secs", dur_w, time_buf);
865 g_string_append_printf(dur_str, "%*s", (int)(borderlen - dur_str->len), "|");
866 puts(dur_str->str);
867 g_string_free(dur_str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(dur_str), ((!(0)))) : g_string_free_and_steal (dur_str)) : (
g_string_free) ((dur_str), ((!(0)))))
;
868
869 GString *invl_str = g_string_new("| Interval: ");
870 display_signed_time(time_buf, NSTIME_ISO8601_BUFSIZEsizeof("YYYY-MM-DDTHH:MM:SS.123456789Z"), interval, invl_prec);
871 g_string_append_printf(invl_str, "%*s secs", dur_w, time_buf);
872 g_string_append_printf(invl_str, "%*s", (int)(borderlen - invl_str->len), "|");
873 puts(invl_str->str);
874 g_string_free(invl_str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(invl_str), ((!(0)))) : g_string_free_and_steal (invl_str)) :
(g_string_free) ((invl_str), ((!(0)))))
;
875
876 printf("|%-*s|\n", borderlen - 2, "");
877
878 iostat_draw_filters(borderlen, iot);
879
880 printf("|-");
881 for (i=0; i<borderlen-3; i++) {
882 printf("-");
883 }
884 printf("|\n");
885}
886
887static void
888iostat_draw_header_row(unsigned borderlen, const io_stat_t *iot, const column_width *col_w, unsigned invl_col_w, unsigned tabrow_w)
889{
890 unsigned j, type, numpad = 1;
891 char *filler_s = NULL((void*)0);
892
893 /* Display spaces above "Interval (s)" label */
894 printf("|%*s", invl_col_w - 1, "|");
895
896 /* Display column number headers */
897 for (j=0; j < iot->num_cols; j++) {
898 int padding;
899 if (iot->calc_type[j] == CALC_TYPE_FRAMES_AND_BYTES2)
900 padding = col_w[j].fr + col_w[j].val + 3;
901 else if (iot->calc_type[j] == CALC_TYPE_FRAMES0)
902 padding = col_w[j].fr;
903 else
904 padding = col_w[j].val;
905
906 printf("%-2d%*s|", j+1, padding, "");
907 }
908 if (tabrow_w < borderlen) {
909 filler_s = g_strdup_printf("%*s", borderlen - tabrow_w, "|");
910 printf("%s", filler_s);
911 }
912 printf("\n");
913
914 GString *timestamp_str;
915 switch (timestamp_get_type()) {
916 case TS_ABSOLUTE:
917 case TS_UTC:
918 timestamp_str = g_string_new("| Time ");
919 break;
920 case TS_ABSOLUTE_WITH_YMD:
921 case TS_ABSOLUTE_WITH_YDOY:
922 case TS_UTC_WITH_YMD:
923 case TS_UTC_WITH_YDOY:
924 timestamp_str = g_string_new("| Date and time");
925 break;
926 case TS_RELATIVE:
927 case TS_NOT_SET:
928 timestamp_str = g_string_new("| Interval");
929 break;
930 default:
931 timestamp_str = g_string_new(NULL((void*)0));
932 break;
933 }
934
935 printf("%s%*s", timestamp_str->str, (int)(invl_col_w - timestamp_str->len), "|");
936 g_string_free(timestamp_str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(timestamp_str), ((!(0)))) : g_string_free_and_steal (timestamp_str
)) : (g_string_free) ((timestamp_str), ((!(0)))))
;
937
938 /* Display the stat label in each column */
939 for (j=0; j < iot->num_cols; j++) {
940 type = iot->calc_type[j];
941 if (type == CALC_TYPE_FRAMES0) {
942 printcenter (calc_type_table[type].func_name, col_w[j].fr, numpad);
943 } else if (type == CALC_TYPE_FRAMES_AND_BYTES2) {
944 printcenter ("Frames", col_w[j].fr, numpad);
945 printcenter ("Bytes", col_w[j].val, numpad);
946 } else {
947 printcenter (calc_type_table[type].func_name, col_w[j].val, numpad);
948 }
949 }
950 if (filler_s) {
951 printf("%s", filler_s);
952 }
953 printf("\n|-");
954
955 for (j=0; j<tabrow_w-3; j++)
956 printf("-");
957 printf("|");
958
959 if (filler_s) {
960 printf("%s", filler_s);
961 g_free(filler_s);
962 }
963
964 printf("\n");
965}
966
967static void
968iostat_draw(void *arg)
969{
970 uint32_t num;
971 uint64_t interval, duration, t, invl_end, dv;
972 unsigned int i, j, k, num_cols, num_rows, dur_secs, dur_mag,
973 invl_mag, invl_prec, tabrow_w, borderlen, invl_col_w, type,
974 maxfltr_w, ftype;
975 char **fmts, *fmt = NULL((void*)0);
976 static char *invl_fmt, *full_fmt;
977 io_stat_item_t *mit, **stat_cols, *item, **item_in_column;
978 bool_Bool last_row = false0;
979 io_stat_t *iot;
980 column_width *col_w;
981 char time_buf[NSTIME_ISO8601_BUFSIZEsizeof("YYYY-MM-DDTHH:MM:SS.123456789Z")];
982
983 mit = (io_stat_item_t *)arg;
984 iot = mit->parent;
985 num_cols = iot->num_cols;
986 col_w = g_new(column_width, num_cols)((column_width *) g_malloc_n ((num_cols), sizeof (column_width
)))
;
987 fmts = (char **)g_malloc(sizeof(char *) * num_cols);
988 duration = ((uint64_t)cfile.elapsed_time.secs * UINT64_C(1000000)1000000UL) +
989 (uint64_t)((cfile.elapsed_time.nsecs + 500) / 1000);
990
991 /* Store the pointer to each stat column */
992 stat_cols = (io_stat_item_t **)g_malloc(sizeof(io_stat_item_t *) * num_cols);
993 for (j=0; j<num_cols; j++)
994 stat_cols[j] = &iot->items[j];
995
996 /* The following prevents gross inaccuracies when the user specifies an interval that is greater
997 * than the capture duration. */
998 if (iot->interval > duration || iot->interval == UINT64_MAX(18446744073709551615UL)) {
999 interval = duration;
1000 iot->interval = UINT64_MAX(18446744073709551615UL);
1001 } else {
1002 interval = iot->interval;
1003 }
1004
1005 /* Calc the capture duration's magnitude (dur_mag) */
1006 dur_secs = (unsigned int)(duration/UINT64_C(1000000)1000000UL);
1007 dur_mag = magnitude((uint64_t)dur_secs, 5);
1008
1009 /* Calc the interval's magnitude */
1010 invl_mag = magnitude(interval/UINT64_C(1000000)1000000UL, 5);
1011
1012 /* Set or get the interval precision */
1013 if (interval == duration) {
1014 /*
1015 * An interval arg of 0 or an interval size exceeding the capture duration was specified.
1016 * Set the decimal precision of duration based on its magnitude. */
1017 if (dur_mag >= 2)
1018 invl_prec = 1;
1019 else if (dur_mag == 1)
1020 invl_prec = 3;
1021 else
1022 invl_prec = 6;
1023
1024 borderlen = 30 + dur_mag + (invl_prec == 0 ? 0 : invl_prec+1);
1025 } else {
1026 invl_prec = iot->invl_prec;
1027 borderlen = 25 + MAX(invl_mag,dur_mag)(((invl_mag) > (dur_mag)) ? (invl_mag) : (dur_mag)) + (invl_prec == 0 ? 0 : invl_prec+1);
1028 }
1029
1030 /* Round the duration according to invl_prec */
1031 dv = 1000000;
1032 for (i=0; i<invl_prec; i++)
1033 dv /= 10;
1034 if ((duration%dv) > 5*(dv/10)) {
1035 duration += 5*(dv/10);
1036 duration = (duration/dv) * dv;
1037 dur_secs = (unsigned int)(duration/UINT64_C(1000000)1000000UL);
1038 /*
1039 * Recalc dur_mag in case rounding has increased its magnitude */
1040 dur_mag = magnitude((uint64_t)dur_secs, 5);
1041 }
1042 if (iot->interval == UINT64_MAX(18446744073709551615UL))
1043 interval = duration;
1044
1045 //int dur_w = dur_mag + (invl_prec == 0 ? 0 : invl_prec+1);
1046
1047 /* Calc the width of the time interval column (incl borders and padding). */
1048 if (invl_prec == 0) {
1049 invl_fmt = g_strdup_printf("%%%du", dur_mag);
1050 invl_col_w = (2*dur_mag) + 8;
1051 } else {
1052 invl_fmt = g_strdup_printf("%%%du.%%0%du", dur_mag, invl_prec);
1053 invl_col_w = (2*dur_mag) + (2*invl_prec) + 10;
1054 }
1055
1056 /* Update the width of the time interval column if date is shown */
1057 switch (timestamp_get_type()) {
1058 case TS_ABSOLUTE_WITH_YMD:
1059 case TS_ABSOLUTE_WITH_YDOY:
1060 case TS_UTC_WITH_YMD:
1061 case TS_UTC_WITH_YDOY:
1062 // We don't show more than 6 fractional digits (+Z) currently.
1063 // NSTIME_ISO8601_BUFSIZE is enough room for 9 frac digits + Z + '\0'
1064 // That's 4 extra characters, which leaves room for the "| |".
1065 invl_col_w = MAX(invl_col_w, NSTIME_ISO8601_BUFSIZE + invl_prec - 6)(((invl_col_w) > (sizeof("YYYY-MM-DDTHH:MM:SS.123456789Z")
+ invl_prec - 6)) ? (invl_col_w) : (sizeof("YYYY-MM-DDTHH:MM:SS.123456789Z"
) + invl_prec - 6))
;
1066 break;
1067
1068 default:
1069 // Make it as least as twice as wide as "> Dur|" for the final interval
1070 invl_col_w = MAX(invl_col_w, 12)(((invl_col_w) > (12)) ? (invl_col_w) : (12));
1071 break;
1072 }
1073
1074 /* Calculate the width and format string of all the other columns, and add
1075 * the total to the interval column width for the entire total. */
1076 tabrow_w = invl_col_w + iostat_calc_cols_width_and_fmt(iot, interval, col_w, fmts);
1077
1078 borderlen = MAX(borderlen, tabrow_w)(((borderlen) > (tabrow_w)) ? (borderlen) : (tabrow_w));
1079
1080 /* Calc the max width of the list of filters. */
1081 maxfltr_w = 0;
1082 for (j=0; j<num_cols; j++) {
1083 if (iot->filters[j]) {
1084 k = (unsigned int) (strlen(iot->filters[j]) + 11);
1085 maxfltr_w = MAX(maxfltr_w, k)(((maxfltr_w) > (k)) ? (maxfltr_w) : (k));
1086 } else {
1087 maxfltr_w = MAX(maxfltr_w, 26)(((maxfltr_w) > (26)) ? (maxfltr_w) : (26));
1088 }
1089 }
1090 /* The stat table is not wrapped (by tshark) but filter is wrapped at the width of the stats table
1091 * (which currently = borderlen); however, if the filter width exceeds the table width and the
1092 * table width is less than 102 bytes, set borderlen to the lesser of the max filter width and 102.
1093 * The filters will wrap at the lesser of borderlen-2 and the last space in the filter.
1094 * NOTE: 102 is the typical size of a user window when the font is fixed width (e.g., COURIER 10).
1095 * XXX: A pref could be added to change the max width from the default size of 102. */
1096 if (maxfltr_w > borderlen && borderlen < 102)
1097 borderlen = MIN(maxfltr_w, 102)(((maxfltr_w) < (102)) ? (maxfltr_w) : (102));
1098
1099 /* Prevent double right border by adding a space */
1100 if (borderlen-tabrow_w == 1)
1101 borderlen++;
1102
1103 nstime_t invl_time = NSTIME_INIT_SECS_USECS(interval/UINT64_C(1000000), interval%UINT64_C(1000000)){interval/1000000UL, interval%1000000UL*1000};
1104 iostat_draw_header(borderlen, iot, &cfile.elapsed_time, &invl_time, invl_prec);
1105
1106 iostat_draw_header_row(borderlen, iot, col_w, invl_col_w, tabrow_w);
1107
1108 t = 0;
1109 if (invl_prec == 0 && dur_mag == 1)
1110 full_fmt = g_strconcat("| ", invl_fmt, " <> ", invl_fmt, " |", NULL((void*)0));
1111 else
1112 full_fmt = g_strconcat("| ", invl_fmt, " <> ", invl_fmt, " |", NULL((void*)0));
1113
1114 if (interval == 0 || duration == 0) {
1115 num_rows = 0;
1116 } else {
1117 num_rows = (unsigned int)(duration/interval) + ((unsigned int)(duration%interval) > 0 ? 1 : 0);
1118 }
1119
1120 /* Load item_in_column with the first item in each column */
1121 item_in_column = (io_stat_item_t **)g_malloc(sizeof(io_stat_item_t *) * num_cols);
1122 for (j=0; j<num_cols; j++) {
1123 item_in_column[j] = stat_cols[j];
1124 }
1125
1126 /* Display the table values
1127 *
1128 * The outer loop is for time interval rows and the inner loop is for stat column items.*/
1129 for (i=0; i<num_rows; i++) {
1130
1131 if (i == num_rows-1)
1132 last_row = true1;
1133
1134 /* Compute the interval for this row */
1135 if (!last_row) {
1136 invl_end = t + interval;
1137 } else {
1138 invl_end = duration;
1139 }
1140
1141 /* Patch for Absolute Time */
1142 /* XXX - has a Y2.038K problem with 32-bit time_t */
1143 nstime_t the_time = NSTIME_INIT_SECS_USECS(t / 1000000, t % 1000000){t / 1000000, t % 1000000*1000};
1144 nstime_add(&the_time, &iot->start_time)nstime_sum(&the_time, &the_time, &iot->start_time
)
;
1145
1146 /* Display the interval for this row */
1147 switch (timestamp_get_type()) {
1148 case TS_ABSOLUTE:
1149 fill_abs_time(&the_time, time_buf, io_decimal_point, invl_prec, true1);
1150 // invl_col_w includes the "| |"
1151 printf("| %-*s |", invl_col_w - 4, time_buf);
1152 break;
1153
1154 case TS_ABSOLUTE_WITH_YMD:
1155 format_nstime_as_iso8601(time_buf, NSTIME_ISO8601_BUFSIZEsizeof("YYYY-MM-DDTHH:MM:SS.123456789Z"), &the_time,
1156 io_decimal_point, true1, invl_prec);
1157 printf("| %-*s |", invl_col_w - 4, time_buf);
1158 break;
1159
1160 case TS_ABSOLUTE_WITH_YDOY:
1161 fill_abs_ydoy_time(&the_time, time_buf, io_decimal_point, invl_prec, true1);
1162 printf("| %-*s |", invl_col_w - 4, time_buf);
1163 break;
1164
1165 case TS_UTC:
1166 fill_abs_time(&the_time, time_buf, io_decimal_point, invl_prec, false0);
1167 printf("| %-*s |", invl_col_w - 4, time_buf);
1168 break;
1169
1170 case TS_UTC_WITH_YMD:
1171 format_nstime_as_iso8601(time_buf, NSTIME_ISO8601_BUFSIZEsizeof("YYYY-MM-DDTHH:MM:SS.123456789Z"), &the_time,
1172 io_decimal_point, false0, invl_prec);
1173 printf("| %-*s |", invl_col_w - 4, time_buf);
1174 break;
1175
1176 case TS_UTC_WITH_YDOY:
1177 fill_abs_ydoy_time(&the_time, time_buf, io_decimal_point, invl_prec, false0);
1178 printf("| %-*s |", invl_col_w - 4, time_buf);
1179 break;
1180
1181 case TS_RELATIVE:
1182 case TS_NOT_SET:
1183 if (invl_prec == 0) {
1184 if (last_row) {
1185 int maxw;
1186 maxw = dur_mag >= 3 ? dur_mag+1 : 3;
1187 g_free(full_fmt);
1188 full_fmt = g_strdup_printf("| %s%s <> %%-%ds|",
1189 dur_mag == 1 ? " " : "",
1190 invl_fmt, maxw);
1191 printf(full_fmt, (uint32_t)(t/UINT64_C(1000000)1000000UL), "Dur");
1192 } else {
1193 printf(full_fmt, (uint32_t)(t/UINT64_C(1000000)1000000UL),
1194 (uint32_t)(invl_end/UINT64_C(1000000)1000000UL));
1195 }
1196 } else {
1197 printf(full_fmt, (uint32_t)(t/UINT64_C(1000000)1000000UL),
1198 (uint32_t)(t%UINT64_C(1000000)1000000UL / dv),
1199 (uint32_t)(invl_end/UINT64_C(1000000)1000000UL),
1200 (uint32_t)(invl_end%UINT64_C(1000000)1000000UL / dv));
1201 }
1202 break;
1203 /* case TS_DELTA:
1204 case TS_DELTA_DIS:
1205 case TS_EPOCH:
1206 are not implemented */
1207 default:
1208 break;
1209 }
1210
1211 /* Display stat values in each column for this row */
1212 for (j=0; j<num_cols; j++) {
1213 fmt = fmts[j];
1214 item = item_in_column[j];
1215 type = iot->calc_type[j];
1216
1217 if (item) {
1218 switch (type) {
1219 case CALC_TYPE_FRAMES0:
1220 printf(fmt, item->frames);
1221 break;
1222 case CALC_TYPE_BYTES1:
1223 case CALC_TYPE_COUNT3:
1224 printf(fmt, item->counter);
1225 break;
1226 case CALC_TYPE_FRAMES_AND_BYTES2:
1227 printf(fmt, item->frames, item->counter);
1228 break;
1229
1230 case CALC_TYPE_SUM4:
1231 case CALC_TYPE_MIN5:
1232 case CALC_TYPE_MAX6:
1233 ftype = proto_registrar_get_ftype(iot->hf_indexes[j]);
1234 switch (ftype) {
1235 case FT_FLOAT:
1236 printf(fmt, item->float_counter);
1237 break;
1238 case FT_DOUBLE:
1239 printf(fmt, item->double_counter);
1240 break;
1241 case FT_RELATIVE_TIME:
1242 item->counter = (item->counter + UINT64_C(500)500UL) / UINT64_C(1000)1000UL;
1243 printf(fmt,
1244 (int)(item->counter/UINT64_C(1000000)1000000UL),
1245 (int)(item->counter%UINT64_C(1000000)1000000UL));
1246 break;
1247 default:
1248 printf(fmt, item->counter);
1249 break;
1250 }
1251 break;
1252
1253 case CALC_TYPE_AVG7:
1254 num = item->num;
1255 if (num == 0)
1256 num = 1;
1257 ftype = proto_registrar_get_ftype(iot->hf_indexes[j]);
1258 switch (ftype) {
1259 case FT_FLOAT:
1260 printf(fmt, item->float_counter/num);
1261 break;
1262 case FT_DOUBLE:
1263 printf(fmt, item->double_counter/num);
1264 break;
1265 case FT_RELATIVE_TIME:
1266 item->counter = ((item->counter / (uint64_t)num) + UINT64_C(500)500UL) / UINT64_C(1000)1000UL;
1267 printf(fmt,
1268 (int)(item->counter/UINT64_C(1000000)1000000UL),
1269 (int)(item->counter%UINT64_C(1000000)1000000UL));
1270 break;
1271 default:
1272 printf(fmt, item->counter / (uint64_t)num);
1273 break;
1274 }
1275 break;
1276
1277 case CALC_TYPE_LOAD8:
1278 ftype = proto_registrar_get_ftype(iot->hf_indexes[j]);
1279 switch (ftype) {
1280 case FT_RELATIVE_TIME:
1281 if (!last_row) {
1282 printf(fmt,
1283 (int) (item->counter/interval),
1284 (int)((item->counter%interval)*UINT64_C(1000000)1000000UL / interval));
1285 } else {
1286 printf(fmt,
1287 (int) (item->counter/(invl_end-t)),
1288 (int)((item->counter%(invl_end-t))*UINT64_C(1000000)1000000UL / (invl_end-t)));
1289 }
1290 break;
1291 }
1292 break;
1293 }
1294
1295 if (last_row) {
1296 g_free(fmt);
1297 } else {
1298 item_in_column[j] = item_in_column[j]->next;
1299 }
1300 } else {
1301 printf(fmt, (uint64_t)0, (uint64_t)0);
1302 }
1303 }
1304 if (tabrow_w < borderlen) {
1305 printf("%*s", borderlen - tabrow_w, "|");
1306 }
1307 printf("\n");
1308 t += interval;
1309
1310 }
1311 for (i=0; i<borderlen; i++) {
1312 printf("=");
1313 }
1314 printf("\n");
1315 g_free(iot->items);
1316 for (i = 0; i < iot->num_cols; i++) {
1317 g_free((char*)iot->filters[i]);
1318 }
1319 g_free((gpointer)iot->filters);
1320 g_free(iot->max_vals);
1321 g_free(iot->max_frame);
1322 g_free(iot->hf_indexes);
1323 g_free(iot->calc_type);
1324 g_free(iot);
1325 g_free(col_w);
1326 g_free(invl_fmt);
1327 g_free(full_fmt);
1328 g_free(fmts);
1329 g_free(stat_cols);
1330 g_free(item_in_column);
1331}
1332
1333
1334static bool_Bool
1335register_io_tap(io_stat_t *io, unsigned int i, const char *filter, GString *err)
1336{
1337 GString *error_string;
1338 const char *flt;
1339 int j;
1340 size_t namelen;
1341 const char *p, *parenp;
1342 char *field;
1343 header_field_info *hfi;
1344
1345 io->items[i].prev = &io->items[i];
1346 io->items[i].next = NULL((void*)0);
1347 io->items[i].parent = io;
1348 io->items[i].start_time = 0;
1349 io->items[i].frames = 0;
1350 io->items[i].counter = 0;
1351 io->items[i].num = 0;
1352
1353 io->filters[i] = filter;
1354 flt = filter;
1355
1356 io->calc_type[i] = CALC_TYPE_FRAMES_AND_BYTES2;
1357 field = NULL((void*)0);
1358 hfi = NULL((void*)0);
1359 for (j=0; calc_type_table[j].func_name; j++) {
1360 namelen = strlen(calc_type_table[j].func_name);
1361 if (filter && strncmp(filter, calc_type_table[j].func_name, namelen) == 0) {
1362 io->calc_type[i] = calc_type_table[j].calc_type;
1363 io->items[i].colnum = i;
1364 if (*(filter+namelen) == '(') {
1365 p = filter+namelen+1;
1366 parenp = strchr(p, ')');
1367 if (!parenp) {
1368 cmdarg_err("\ntshark: Closing parenthesis missing from calculated expression.\n");
1369 return false0;
1370 }
1371
1372 if (io->calc_type[i] == CALC_TYPE_FRAMES0 || io->calc_type[i] == CALC_TYPE_BYTES1) {
1373 if (parenp != p) {
1374 cmdarg_err("\ntshark: %s does not require or allow a field name within the parens.\n",
1375 calc_type_table[j].func_name);
1376 return false0;
1377 }
1378 } else {
1379 if (parenp == p) {
1380 /* bail out if a field name was not specified */
1381 cmdarg_err("\ntshark: You didn't specify a field name for %s(*).\n",
1382 calc_type_table[j].func_name);
1383 return false0;
1384 }
1385 }
1386
1387 field = (char *)g_malloc(parenp-p+1);
1388 memcpy(field, p, parenp-p);
1389 field[parenp-p] = '\0';
1390 flt = parenp + 1;
1391 if (io->calc_type[i] == CALC_TYPE_FRAMES0 || io->calc_type[i] == CALC_TYPE_BYTES1)
1392 break;
1393 hfi = proto_registrar_get_byname(field);
1394 if (!hfi) {
1395 cmdarg_err("\ntshark: There is no field named '%s'.\n", field);
1396 g_free(field);
1397 return false0;
1398 }
1399
1400 io->hf_indexes[i] = hfi->id;
1401 break;
1402 }
1403 } else {
1404 if (io->calc_type[i] == CALC_TYPE_FRAMES0 || io->calc_type[i] == CALC_TYPE_BYTES1)
1405 flt = "";
1406 io->items[i].colnum = i;
1407 }
1408 }
1409 if (hfi && !(io->calc_type[i] == CALC_TYPE_BYTES1 ||
1410 io->calc_type[i] == CALC_TYPE_FRAMES0 ||
1411 io->calc_type[i] == CALC_TYPE_FRAMES_AND_BYTES2)) {
1412 /* check that the type is compatible */
1413 switch (hfi->type) {
1414 case FT_UINT8:
1415 case FT_UINT16:
1416 case FT_UINT24:
1417 case FT_UINT32:
1418 case FT_UINT64:
1419 case FT_INT8:
1420 case FT_INT16:
1421 case FT_INT24:
1422 case FT_INT32:
1423 case FT_INT64:
1424 /* these types support all calculations */
1425 break;
1426 case FT_FLOAT:
1427 case FT_DOUBLE:
1428 /* these types only support SUM, COUNT, MAX, MIN, AVG */
1429 switch (io->calc_type[i]) {
1430 case CALC_TYPE_SUM4:
1431 case CALC_TYPE_COUNT3:
1432 case CALC_TYPE_MAX6:
1433 case CALC_TYPE_MIN5:
1434 case CALC_TYPE_AVG7:
1435 break;
1436 default:
1437 cmdarg_err("\ntshark: %s is a float field, so %s(*) calculations are not supported on it.",
1438 field,
1439 calc_type_table[j].func_name);
1440 return false0;
1441 }
1442 break;
1443 case FT_RELATIVE_TIME:
1444 /* this type only supports SUM, COUNT, MAX, MIN, AVG, LOAD */
1445 switch (io->calc_type[i]) {
1446 case CALC_TYPE_SUM4:
1447 case CALC_TYPE_COUNT3:
1448 case CALC_TYPE_MAX6:
1449 case CALC_TYPE_MIN5:
1450 case CALC_TYPE_AVG7:
1451 case CALC_TYPE_LOAD8:
1452 break;
1453 default:
1454 cmdarg_err("\ntshark: %s is a relative-time field, so %s(*) calculations are not supported on it.",
1455 field,
1456 calc_type_table[j].func_name);
1457 return false0;
1458 }
1459 break;
1460 default:
1461 /*
1462 * XXX - support all operations on floating-point
1463 * numbers?
1464 */
1465 if (io->calc_type[i] != CALC_TYPE_COUNT3) {
1466 cmdarg_err("\ntshark: %s doesn't have integral values, so %s(*) "
1467 "calculations are not supported on it.\n",
1468 field,
1469 calc_type_table[j].func_name);
1470 return false0;
1471 }
1472 break;
1473 }
1474 }
1475 g_free(field);
1476
1477 error_string = register_tap_listener("frame", &io->items[i], flt, TL_REQUIRES_PROTO_TREE0x00000001, NULL((void*)0),
1478 iostat_packet, i ? NULL((void*)0) : iostat_draw, NULL((void*)0));
1479 if (error_string) {
1480 /* Accumulate errors about all the possible filters tried at the same
1481 * starting character.
1482 */
1483 if (err->len) {
1484 g_string_append_c(err, '\n')g_string_append_c_inline (err, '\n');
1485 }
1486 g_string_append(err, error_string->str)(__builtin_constant_p (error_string->str) ? __extension__ (
{ const char * const __val = (error_string->str); g_string_append_len_inline
(err, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(err, error_string->str, (gssize) -1))
;
1487 g_string_free(error_string, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(error_string), ((!(0)))) : g_string_free_and_steal (error_string
)) : (g_string_free) ((error_string), ((!(0)))))
;
1488 return false0;
1489 }
1490
1491 /* On success, clear old errors (from splitting on internal commas). */
1492 g_string_truncate(err, 0)g_string_truncate_inline (err, 0);
1493 return true1;
1494}
1495
1496static bool_Bool
1497iostat_init(const char *opt_arg, void *userdata _U___attribute__((unused)))
1498{
1499 double interval_float;
1500 uint32_t idx = 0;
1501 unsigned int i;
1502 io_stat_t *io;
1503 const char *filters, *str, *pos;
1504
1505 io_decimal_point = localeconv()->decimal_point;
1506
1507 /* XXX - Why can't the last character be a comma? Shouldn't it be
1508 * fine for the last filter to be empty? Even in the case of locales
1509 * that use ',' for the decimal separator, there shouldn't be any
1510 * difference between interpreting a terminating ',' as a decimal
1511 * point for the interval, and interpreting it as a separator followed
1512 * by an empty filter.
1513 */
1514 if ((*(opt_arg+(strlen(opt_arg)-1)) == ',') ||
1
Assuming the condition is false
4
Taking false branch
1515 (sscanf(opt_arg, "io,stat,%lf%n", &interval_float, (int *)&idx) != 1) ||
2
Assuming the condition is false
1516 (idx < 8)) {
3
Assuming 'idx' is >= 8
1517 cmdarg_err("\ntshark: invalid \"-z io,stat,<interval>[,<filter>][,<filter>]...\" argument\n");
1518 return false0;
1519 }
1520
1521 filters = opt_arg+idx;
1522 if (*filters) {
5
Assuming the condition is true
6
Taking true branch
1523 if (*filters != ',') {
7
Assuming the condition is false
8
Taking false branch
1524 /* For locales that use ',' instead of '.', the comma might
1525 * have been consumed during the floating point conversion. */
1526 --filters;
1527 if (*filters != ',') {
1528 cmdarg_err("\ntshark: invalid \"-z io,stat,<interval>[,<filter>][,<filter>]...\" argument\n");
1529 return false0;
1530 }
1531 }
1532 }
1533 /* filters now either starts with ',' or '\0' */
1534
1535 switch (timestamp_get_type()) {
9
Control jumps to the 'default' case at line 1541
1536 case TS_DELTA:
1537 case TS_DELTA_DIS:
1538 case TS_EPOCH:
1539 cmdarg_err("\ntshark: invalid -t operand. io,stat only supports -t <r|a|ad|adoy|u|ud|udoy>\n");
1540 return false0;
1541 default:
1542 break;
1543 }
1544
1545 io = g_new(io_stat_t, 1)((io_stat_t *) g_malloc_n ((1), sizeof (io_stat_t)));
10
Execution continues on line 1545
1546
1547 /* If interval is 0, calculate statistics over the whole file by setting the interval to
1548 * UINT64_MAX */
1549 if (interval_float == 0) {
11
Assuming 'interval_float' is equal to 0
12
Taking true branch
1550 io->interval = UINT64_MAX(18446744073709551615UL);
1551 io->invl_prec = 0;
1552 } else {
1553 /* Set interval to the number of us rounded to the nearest integer */
1554 io->interval = (uint64_t)(interval_float * 1000000.0 + 0.5);
1555 /*
1556 * Determine what interval precision the user has specified */
1557 io->invl_prec = 6;
1558 for (i=10; i<10000000; i*=10) {
1559 if (io->interval%i > 0)
1560 break;
1561 io->invl_prec--;
1562 }
1563 if (io->invl_prec == 0) {
1564 /* The precision is zero but if the user specified one of more zeros after the decimal point,
1565 they want that many decimal places shown in the table for all time intervals except
1566 response time values such as smb.time which always have 6 decimal places of precision.
1567 This feature is useful in cases where for example the duration is 9.1, you specify an
1568 interval of 1 and the last interval becomes "9 <> 9". If the interval is instead set to
1569 1.1, the last interval becomes
1570 last interval is rounded up to value that is greater than the duration. */
1571 const char *invl_start = opt_arg+8;
1572 char *intv_end;
1573 int invl_len;
1574
1575 intv_end = g_strstr_len(invl_start, -1, ",");
1576 invl_len = (int)(intv_end - invl_start);
1577 invl_start = g_strstr_len(invl_start, invl_len, ".");
1578
1579 if (invl_start != NULL((void*)0)) {
1580 invl_len = (int)(intv_end - invl_start - 1);
1581 if (invl_len)
1582 io->invl_prec = MIN(invl_len, 6)(((invl_len) < (6)) ? (invl_len) : (6));
1583 }
1584 }
1585 }
1586 if (io->interval
12.1
Field 'interval' is >= 1
< 1) {
13
Taking false branch
1587 cmdarg_err("\ntshark: \"-z\" interval must be >=0.000001 seconds or \"0\" for the entire capture duration.\n");
1588 return false0;
1589 }
1590
1591 /* Find how many ',' separated filters we have */
1592 /* Filter can have internal commas, so this is only an upper bound on the
1593 * number of filters. In the display filter grammar, commas only appear
1594 * inside delimiters (quoted strings, slices, sets, and functions), so
1595 * splitting in the wrong place produces an invalid filter. That is, there
1596 * can be at most only one valid interpretation (but might be none).
1597 *
1598 * XXX - If the grammar changes to allow commas in other places, then there
1599 * is ambiguity.
1600 *
1601 * Perhaps ideally we'd verify the filters before doing allocation.
1602 */
1603 io->num_cols = 1;
1604 nstime_set_unset(&io->start_time);
1605
1606 if (*filters != '\0') {
14
Assuming the condition is false
15
Taking false branch
1607 /* Eliminate the first comma. */
1608 filters++;
1609 str = filters;
1610 while ((str = strchr(str, ','))) {
1611 io->num_cols++;
1612 str++;
1613 }
1614 }
1615
1616 io->items = g_new(io_stat_item_t, io->num_cols)((io_stat_item_t *) g_malloc_n ((io->num_cols), sizeof (io_stat_item_t
)))
;
1617 io->filters = (const char **)g_malloc(sizeof(char *) * io->num_cols);
1618 io->max_vals = g_new(uint64_t, io->num_cols)((uint64_t *) g_malloc_n ((io->num_cols), sizeof (uint64_t
)))
;
1619 io->max_frame = g_new(uint32_t, io->num_cols)((uint32_t *) g_malloc_n ((io->num_cols), sizeof (uint32_t
)))
;
1620 io->hf_indexes = g_new(int, io->num_cols)((int *) g_malloc_n ((io->num_cols), sizeof (int)));
1621 io->calc_type = g_new(int, io->num_cols)((int *) g_malloc_n ((io->num_cols), sizeof (int)));
1622
1623 for (i=0; i
15.1
'i' is < field 'num_cols'
<io->num_cols
; i++) {
16
Loop condition is true. Entering loop body
17
Assuming 'i' is >= field 'num_cols'
18
Loop condition is false. Execution continues on line 1628
1624 io->max_vals[i] = 0;
1625 io->max_frame[i] = 0;
1626 }
1627
1628 bool_Bool success;
1629 GString *err = g_string_new(NULL((void*)0));
1630
1631 /* Register a tap listener for each filter */
1632 if (filters[0] == '\0') {
19
Assuming the condition is false
20
Taking false branch
1633 success = register_io_tap(io, 0, NULL((void*)0), err);
1634 } else {
1635 char *filter;
1636 i = 0;
1637 str = filters;
1638 pos = str;
1639 while ((pos = strchr(pos, ',')) != NULL((void*)0)) {
21
Assuming the condition is true
22
Loop condition is true. Entering loop body
1640 if (pos == str) {
23
Assuming 'pos' is not equal to 'str'
24
Taking false branch
1641 /* Consecutive commas - an empty filter. */
1642 filter = NULL((void*)0);
1643 } else {
1644 /* Likely a filter. */
1645 filter = (char *)g_malloc((pos-str)+1);
25
Memory is allocated
1646 (void) g_strlcpy( filter, str, (size_t) ((pos-str)+1));
1647 filter = g_strstrip(filter)g_strchomp (g_strchug (filter));
1648 }
1649 success = register_io_tap(io, i, filter, err);
26
Potential leak of memory pointed to by 'filter'
1650 /* Advance to the next position to look for commas. */
1651 pos++;
1652 if (success) {
1653 /* Also advance the filter start on success. */
1654 str = pos;
1655 i++;
1656 } else {
1657 g_free(filter);
1658 }
1659 }
1660 /* No more commas, the rest of the string is the last filter. */
1661 filter = g_strstrip(g_strdup(str))g_strchomp (g_strchug (g_strdup_inline (str)));
1662 if (*filter) {
1663 success = register_io_tap(io, i, filter, err);
1664 } else {
1665 success = register_io_tap(io, i, NULL((void*)0), err);
1666 }
1667 if (success) {
1668 i++;
1669 }
1670 io->num_cols = i;
1671 }
1672
1673 if (!success) {
1674 cmdarg_err("\ntshark: Couldn't register io,stat tap: %s\n",
1675 err->str);
1676 g_string_free(err, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(err), ((!(0)))) : g_string_free_and_steal (err)) : (g_string_free
) ((err), ((!(0)))))
;
1677 g_free(io->items);
1678 g_free(io);
1679 return false0;
1680 }
1681 g_string_free(err, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(err), ((!(0)))) : g_string_free_and_steal (err)) : (g_string_free
) ((err), ((!(0)))))
;
1682 return true1;
1683
1684}
1685
1686static stat_tap_ui iostat_ui = {
1687 REGISTER_STAT_GROUP_GENERIC,
1688 NULL((void*)0),
1689 "io,stat",
1690 iostat_init,
1691 0,
1692 NULL((void*)0)
1693};
1694
1695void
1696register_tap_listener_iostat(void)
1697{
1698 register_stat_tap_ui(&iostat_ui, NULL((void*)0));
1699}