summaryrefslogtreecommitdiffstats
path: root/parse.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2021-09-26 15:23:26 -0400
committerTavian Barnes <tavianator@tavianator.com>2021-09-26 15:23:26 -0400
commit78944c815a5d8d1c93771ca1c343b9406bc262c4 (patch)
tree0e11144b526a3a1cebeedf4f7277b60d40488580 /parse.c
parent2e918d33be152c1a57ffb3ff53e344cafb161a8c (diff)
downloadbfs-78944c815a5d8d1c93771ca1c343b9406bc262c4.tar.xz
Don't truncate files until we know they're not duplicates
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/parse.c b/parse.c
index 98e7dbb..22c2473 100644
--- a/parse.c
+++ b/parse.c
@@ -334,25 +334,45 @@ static void init_print_expr(struct parser_state *state, struct expr *expr) {
static int expr_open(struct parser_state *state, struct expr *expr, const char *path) {
struct bfs_ctx *ctx = state->ctx;
- CFILE *cfile = cfopen(path, state->use_color ? ctx->colors : NULL);
+ FILE *file = NULL;
+ CFILE *cfile = NULL;
+
+ file = xfopen(path, O_WRONLY | O_CREAT | O_CLOEXEC);
+ if (!file) {
+ goto fail;
+ }
+
+ cfile = cfwrap(file, state->use_color ? ctx->colors : NULL, true);
if (!cfile) {
- parse_error(state, "${blu}%s${rs} ${bld}%s${rs}: %m.\n", expr->argv[0], path);
- return -1;
+ goto fail;
}
CFILE *dedup = bfs_ctx_dedup(ctx, cfile, path);
if (!dedup) {
- parse_error(state, "${blu}%s${rs} ${bld}%s${rs}: %m.\n", expr->argv[0], path);
+ goto fail;
+ }
+
+ if (dedup == cfile) {
+ // O_TRUNC was omitted above to avoid repeatedly truncating the same file, so do it
+ // manually here
+ if (ftruncate(fileno(file), 0) != 0) {
+ goto fail;
+ }
+ } else {
cfclose(cfile);
- return -1;
}
expr->cfile = dedup;
+ return 0;
- if (dedup != cfile) {
+fail:
+ parse_error(state, "${blu}%s${rs} ${bld}%s${rs}: %m.\n", expr->argv[0], path);
+ if (cfile) {
cfclose(cfile);
+ } else if (file) {
+ fclose(file);
}
- return 0;
+ return -1;
}
/**
@@ -2675,12 +2695,11 @@ static CFILE *launch_pager(pid_t *pid, CFILE *cout) {
}
pipefd[1] = -1;
- CFILE *ret = cfdup(file, NULL);
+ CFILE *ret = cfwrap(file, NULL, true);
if (!ret) {
goto fail_file;
}
file = NULL;
- ret->close = true;
struct bfs_spawn ctx;
if (bfs_spawn_init(&ctx) != 0) {
@@ -3689,15 +3708,15 @@ struct bfs_ctx *bfs_parse_cmdline(int argc, char *argv[]) {
ctx->colors_error = errno;
}
- ctx->cerr = cfdup(stderr, use_color ? ctx->colors : NULL);
+ ctx->cerr = cfwrap(stderr, use_color ? ctx->colors : NULL, false);
if (!ctx->cerr) {
- perror("cfdup()");
+ perror("cfwrap()");
goto fail;
}
- ctx->cout = cfdup(stdout, use_color ? ctx->colors : NULL);
+ ctx->cout = cfwrap(stdout, use_color ? ctx->colors : NULL, false);
if (!ctx->cout) {
- bfs_perror(ctx, "cfdup()");
+ bfs_perror(ctx, "cfwrap()");
goto fail;
}