diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2017-10-21 13:10:36 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2017-10-21 13:10:36 -0400 |
commit | 4e38f139f92b8b3729f82c37f0904c2b77d3eb58 (patch) | |
tree | a10f9de054cbcd2176be7666e56e0ae660bebf84 | |
parent | 305f75468ead1f68aad3f3b5162f7437ad8dd732 (diff) | |
download | bfs-4e38f139f92b8b3729f82c37f0904c2b77d3eb58.tar.xz |
Report errors that occur when closing files
Otherwise we miss write errors that occur when flushing the cache.
-rw-r--r-- | cmdline.h | 4 | ||||
-rw-r--r-- | color.c | 2 | ||||
-rw-r--r-- | expr.h | 4 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | parse.c | 37 | ||||
-rwxr-xr-x | tests.sh | 20 |
6 files changed, 60 insertions, 11 deletions
@@ -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 @@ -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); } @@ -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 @@ -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; @@ -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; } /** @@ -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 |