From: Matteo Croce Date: Thu, 22 May 2025 20:44:32 +0000 (+0200) Subject: fincore: add option to show a grand total X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b77b8172dbd4dfc31c55481de00eba62f1b87416;p=thirdparty%2Futil-linux.git fincore: add option to show a grand total Similarly to `du`, add a --total option to produce a grand total of the files analyzed. Signed-off-by: Matteo Croce --- diff --git a/misc-utils/fincore.1.adoc b/misc-utils/fincore.1.adoc index 7d0c8fca3..8e480777f 100644 --- a/misc-utils/fincore.1.adoc +++ b/misc-utils/fincore.1.adoc @@ -34,6 +34,9 @@ Do not print a header line in status output. *-b*, *--bytes*:: include::man-common/in-bytes.adoc[] +*-c*, *--total*:: +produce a grand total. + *-o*, *--output* _list_:: Define output columns. See the *--help* output to get a list of the currently supported columns. The default list of columns may be extended if _list_ is specified in the format _{plus}list_. //TRANSLATORS: Keep {plus} untranslated. diff --git a/misc-utils/fincore.c b/misc-utils/fincore.c index 160dd8e0b..86c1373cb 100644 --- a/misc-utils/fincore.c +++ b/misc-utils/fincore.c @@ -130,7 +130,8 @@ struct fincore_control { noheadings : 1, raw : 1, json : 1, - recursive : 1; + recursive : 1, + total : 1; }; @@ -147,6 +148,9 @@ struct fincore_state { } cstat_fields; }; +static struct fincore_state total = { + .name = "TOTAL", +}; static int column_name_to_id(const char *name, size_t namesz) { @@ -297,6 +301,8 @@ static int do_mincore(struct fincore_control *ctl, { vec[n] = 0; st->cstat.nr_cache++; + if (ctl->total) + total.cstat.nr_cache++; } } @@ -349,6 +355,15 @@ static int fincore_fd (struct fincore_control *ctl, st->cstat_fields.writeback = 1; st->cstat_fields.evicted = 1; st->cstat_fields.recently_evicted = 1; + + if (ctl->total) { + total.cstat.nr_cache += st->cstat.nr_cache; + total.cstat.nr_dirty += st->cstat.nr_dirty; + total.cstat.nr_writeback += st->cstat.nr_writeback; + total.cstat.nr_evicted += st->cstat.nr_evicted; + total.cstat.nr_recently_evicted += st->cstat.nr_recently_evicted; + } + return 0; } @@ -402,6 +417,8 @@ static int fincore_name(struct fincore_control *ctl, if (!rc) { st->name = showname; + if (ctl->total) + total.file_size += st->file_size; rc = add_output_data(ctl, st); } @@ -419,6 +436,7 @@ static void __attribute__((__noreturn__)) usage(void) fputs(USAGE_OPTIONS, out); fputs(_(" -J, --json use JSON output format\n"), out); fputs(_(" -b, --bytes print sizes in bytes rather than in human readable format\n"), out); + fputs(_(" -c, --total produce a grand total\n"), out); fputs(_(" -n, --noheadings don't print headings\n"), out); fputs(_(" -o, --output output columns\n"), out); fputs(_(" --output-all output all columns\n"), out); @@ -454,6 +472,7 @@ int main(int argc, char ** argv) }; static const struct option longopts[] = { { "bytes", no_argument, NULL, 'b' }, + { "total", no_argument, NULL, 'c' }, { "noheadings", no_argument, NULL, 'n' }, { "output", required_argument, NULL, 'o' }, { "output-all", no_argument, NULL, OPT_OUTPUT_ALL }, @@ -470,11 +489,14 @@ int main(int argc, char ** argv) textdomain(PACKAGE); close_stdout_atexit(); - while ((c = getopt_long (argc, argv, "bno:JrRVh", longopts, NULL)) != -1) { + while ((c = getopt_long (argc, argv, "bcno:JrRVh", longopts, NULL)) != -1) { switch (c) { case 'b': ctl.bytes = 1; break; + case 'c': + ctl.total = 1; + break; case 'n': ctl.noheadings = 1; break; @@ -584,6 +606,9 @@ int main(int argc, char ** argv) rc |= fincore_name(&ctl, argv[optind], argv[optind], NULL); } + if (ctl.total) + rc |= add_output_data(&ctl, &total); + scols_print_table(ctl.tb); scols_unref_table(ctl.tb); diff --git a/tests/expected/fincore/count.err b/tests/expected/fincore/count.err index e3fad0113..fb9f80627 100644 --- a/tests/expected/fincore/count.err +++ b/tests/expected/fincore/count.err @@ -2,3 +2,5 @@ fincore: failed to open: no_such_file: No such file or directory [ MULTIPLE FILES ] fincore: failed to open: no_such_file: No such file or directory +[ GRAND TOTAL SIZE ] +[ GRAND TOTAL PAGES ] diff --git a/tests/expected/fincore/count.total b/tests/expected/fincore/count.total new file mode 100644 index 000000000..57551ecb7 --- /dev/null +++ b/tests/expected/fincore/count.total @@ -0,0 +1,33 @@ +0 i_EMPTY +return value: 0 +1 i_1b +return value: 0 +1024 i_1k +return value: 0 +10240 i_10k +return value: 0 +[ GRAND TOTAL SIZE ] +0 i_EMPTY +1 i_1b +1024 i_1k +10240 i_10k +11265 TOTAL +return value: 0 +0 i_EMPTY +return value: 0 +1 i_1b +return value: 0 +1 i_ONE_PAGE +return value: 0 +2 i_TWO_PAGES +return value: 0 +10 i_TEN_PAGES +return value: 0 +[ GRAND TOTAL PAGES ] +0 i_EMPTY +1 i_1b +1 i_ONE_PAGE +2 i_TWO_PAGES +10 i_TEN_PAGES +14 TOTAL +return value: 0 diff --git a/tests/ts/fincore/count b/tests/ts/fincore/count index e132b9902..240ccdd11 100755 --- a/tests/ts/fincore/count +++ b/tests/ts/fincore/count @@ -117,6 +117,7 @@ else OUT_COLUMNS="PAGES,FILE" fi +cat "$TS_EXPECTED.total" >>"$AGG_OUT" cat "$TS_EXPECTED_ERR" >"$AGG_ERR" if ! $TS_CMD_FINCORE --recursive |& grep -q 'recursive option is not supported' ; then @@ -247,6 +248,67 @@ ts_log_both "[ MULTIPLE FILES ]" footer "$?" } >> $TS_OUTPUT 2>> $TS_ERRLOG +rm -f $INPUT +INPUT= + +OLD_COLUMNS=$OUT_COLUMNS +OUT_COLUMNS=SIZE,FILE + +{ + run_dd_test "EMPTY" 0 +} >> $TS_OUTPUT 2>> $TS_ERRLOG + +{ + run_dd_test 1b 1 +} >> $TS_OUTPUT 2>> $TS_ERRLOG + +{ + run_dd_test 1k 1024 +} >> $TS_OUTPUT 2>> $TS_ERRLOG + +{ + run_dd_test 10k 10240 +} >> $TS_OUTPUT 2>> $TS_ERRLOG + +ts_log_both "[ GRAND TOTAL SIZE ]" +{ + $TS_CMD_FINCORE --raw --output $OUT_COLUMNS --bytes --noheadings --total $INPUT + footer "$?" +} >> $TS_OUTPUT 2>> $TS_ERRLOG + +rm -f $INPUT +INPUT= + +OUT_COLUMNS=PAGES,FILE + +{ + run_dd_test "EMPTY" 0 +} >> $TS_OUTPUT 2>> $TS_ERRLOG + +{ + run_dd_test 1b 1 +} >> $TS_OUTPUT 2>> $TS_ERRLOG + +{ + run_dd_test 'ONE PAGE' $PAGE_SIZE +} >> $TS_OUTPUT 2>> $TS_ERRLOG + +{ + run_dd_test 'TWO PAGES' $(( 2 * PAGE_SIZE )) +} >> $TS_OUTPUT 2>> $TS_ERRLOG + +{ + run_dd_test 'TEN PAGES' $(( 10 * PAGE_SIZE )) +} >> $TS_OUTPUT 2>> $TS_ERRLOG + +ts_log_both "[ GRAND TOTAL PAGES ]" +{ + $TS_CMD_FINCORE --raw --output $OUT_COLUMNS --bytes --noheadings --total $INPUT + footer "$?" +} >> $TS_OUTPUT 2>> $TS_ERRLOG + +OUT_COLUMNS=$OLD_COLUMNS + if [ -n "$RECURSIVE" ]; then dir=$(make_input_name dir) mkdir -p "$dir"