From 4e38f139f92b8b3729f82c37f0904c2b77d3eb58 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sat, 21 Oct 2017 13:10:36 -0400 Subject: Report errors that occur when closing files Otherwise we miss write errors that occur when flushing the cache. --- cmdline.h | 4 +++- color.c | 2 ++ expr.h | 4 +++- main.c | 4 +++- parse.c | 37 ++++++++++++++++++++++++++++++------- tests.sh | 20 +++++++++++++++++++- 6 files changed, 60 insertions(+), 11 deletions(-) diff --git a/cmdline.h b/cmdline.h index a1dadc3..9a46f7f 100644 --- a/cmdline.h +++ b/cmdline.h @@ -117,7 +117,9 @@ int eval_cmdline(const struct cmdline *cmdline); /** * Free the parsed command line. + * + * @return 0 if successful, -1 on error. */ -void free_cmdline(struct cmdline *cmdline); +int free_cmdline(struct cmdline *cmdline); #endif // CMDLINE_H diff --git a/color.c b/color.c index 8df6a1f..1025c9e 100644 --- a/color.c +++ b/color.c @@ -288,6 +288,8 @@ int cfclose(CFILE *cfile) { if (cfile) { if (cfile->close) { ret = fclose(cfile->file); + } else if (cfile->file) { + ret = fflush(cfile->file); } free(cfile); } diff --git a/expr.h b/expr.h index 0eba0da..c0e2b92 100644 --- a/expr.h +++ b/expr.h @@ -219,7 +219,9 @@ void dump_expr(CFILE *cfile, const struct expr *expr, bool verbose); /** * Free an expression tree. + * + * @return 0 if successful, -1 on error. */ -void free_expr(struct expr *expr); +int free_expr(struct expr *expr); #endif // EXPR_H diff --git a/main.c b/main.c index 9e8fdbf..2734aaf 100644 --- a/main.c +++ b/main.c @@ -60,7 +60,9 @@ int main(int argc, char *argv[]) { ret = eval_cmdline(cmdline); } - free_cmdline(cmdline); + if (free_cmdline(cmdline) != 0 && ret == EXIT_SUCCESS) { + ret = EXIT_FAILURE; + } done: return ret; diff --git a/parse.c b/parse.c index 46c860c..b4b7ddc 100644 --- a/parse.c +++ b/parse.c @@ -80,11 +80,14 @@ struct expr expr_false = { /** * Free an expression. */ -void free_expr(struct expr *expr) { +int free_expr(struct expr *expr) { + int ret = 0; + if (expr && expr != &expr_true && expr != &expr_false) { if (expr->cfile && expr->cfile->close) { if (cfclose(expr->cfile) != 0) { perror("cfclose()"); + ret = -1; } } @@ -96,10 +99,17 @@ void free_expr(struct expr *expr) { free_bfs_printf(expr->printf); free_bfs_exec(expr->execbuf); - free_expr(expr->lhs); - free_expr(expr->rhs); + if (free_expr(expr->lhs) != 0) { + ret = -1; + } + if (free_expr(expr->rhs) != 0) { + ret = -1; + } + free(expr); } + + return ret; } struct expr *new_expr(eval_fn *eval, size_t argc, char **argv) { @@ -224,14 +234,25 @@ void dump_expr(CFILE *cfile, const struct expr *expr, bool verbose) { /** * Free the parsed command line. */ -void free_cmdline(struct cmdline *cmdline) { +int free_cmdline(struct cmdline *cmdline) { + int ret = 0; + if (cmdline) { - free_expr(cmdline->expr); + if (free_expr(cmdline->expr) != 0) { + ret = -1; + } free_bfs_mtab(cmdline->mtab); - cfclose(cmdline->cerr); - cfclose(cmdline->cout); + if (cfclose(cmdline->cerr) != 0) { + perror("cfclose()"); + ret = -1; + } + if (cfclose(cmdline->cout) != 0) { + perror("cfclose()"); + ret = -1; + } + free_colors(cmdline->colors); struct root *root = cmdline->roots; @@ -244,6 +265,8 @@ void free_cmdline(struct cmdline *cmdline) { free(cmdline->argv); free(cmdline); } + + return ret; } /** diff --git a/tests.sh b/tests.sh index 57aa47b..0f52581 100755 --- a/tests.sh +++ b/tests.sh @@ -376,6 +376,8 @@ gnu_tests=( test_or_purity test_not_reachability test_comma_reachability + test_print_error + test_fprint_error ) bfs_tests=( @@ -1410,6 +1412,18 @@ function test_data_flow_type() { bfs_diff basic \! \( -type f -o \! -type f \) } +function test_print_error() { + if [ -e /dev/full ]; then + ! invoke_bfs basic -maxdepth 0 >/dev/full 2>/dev/null + fi +} + +function test_fprint_error() { + if [ -e /dev/full ]; then + ! invoke_bfs basic -maxdepth 0 -fprint /dev/full 2>/dev/null + fi +} + if [ -t 1 -a ! "$VERBOSE" ]; then in_place=yes fi @@ -1433,7 +1447,11 @@ for test in ${!run_*}; do ((++passed)) else ((++failed)) - echo "$test failed!" + if [ "$in_place" ]; then + printf '\r\033[J%s\n' "$test failed!" + else + echo "$test failed!" + fi fi done -- cgit v1.2.3