From dd7dfb391085a122631395cf001b196feedc7747 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 16 Aug 2018 23:57:42 -0400 Subject: Add some missing fallthrough comments --- parse.c | 1 + printf.c | 1 + 2 files changed, 2 insertions(+) diff --git a/parse.c b/parse.c index 89a47b7..7f9ac9c 100644 --- a/parse.c +++ b/parse.c @@ -1829,6 +1829,7 @@ static struct expr *parse_perm(struct parser_state *state, int field, int arg2) ++mode; break; } + // Fallthrough default: expr->mode_cmp = MODE_EXACT; break; diff --git a/printf.c b/printf.c index 0a969d8..c2b165e 100644 --- a/printf.c +++ b/printf.c @@ -590,6 +590,7 @@ struct bfs_printf *parse_bfs_printf(const char *format, struct cmdline *cmdline) case '0': case '+': must_be_numeric = true; + // Fallthrough case ' ': case '-': if (strchr(directive->str, c)) { -- cgit v1.2.3 From 94740c610143ac26a2c0fa11998db8f0cb76af1a Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 16 Aug 2018 23:57:53 -0400 Subject: color: Fix a doc comment typo --- color.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/color.h b/color.h index ca8a46c..ac3d9b6 100644 --- a/color.h +++ b/color.h @@ -29,7 +29,7 @@ struct colors; /** * Parse a color table. * - * @param ls_color + * @param ls_colors * A color table in the LS_COLORS environment variable format. * @return The parsed color table. */ -- cgit v1.2.3 From 5529a7006ae22df4ea69e06121bd0111fa52e45c Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sat, 18 Aug 2018 12:23:41 -0400 Subject: opt: Re-run optimizations after reordering expressions This catches new data flow inferences that can be made after swapping the children of an expression. --- opt.c | 81 +++++++++++++++++++++++++++------------ tests.sh | 12 +++++- tests/test_data_flow_and_swap.out | 12 ++++++ tests/test_data_flow_or_swap.out | 12 ++++++ 4 files changed, 92 insertions(+), 25 deletions(-) create mode 100644 tests/test_data_flow_and_swap.out create mode 100644 tests/test_data_flow_or_swap.out diff --git a/opt.c b/opt.c index a7ebbe2..6875e92 100644 --- a/opt.c +++ b/opt.c @@ -355,17 +355,6 @@ static struct expr *optimize_and_expr(const struct opt_state *state, struct expr expr->cost = lhs->cost + lhs->probability*rhs->cost; expr->probability = lhs->probability*rhs->probability; - if (optlevel >= 3 && lhs->pure && rhs->pure) { - double swapped_cost = rhs->cost + rhs->probability*lhs->cost; - if (swapped_cost < expr->cost) { - debug_opt(state, "-O3: cost: %e", expr); - expr->lhs = rhs; - expr->rhs = lhs; - debug_opt(state, " <==> %e (~%g --> ~%g)\n", expr, expr->cost, swapped_cost); - expr->cost = swapped_cost; - } - } - return expr; } @@ -426,17 +415,6 @@ static struct expr *optimize_or_expr(const struct opt_state *state, struct expr expr->cost = lhs->cost + (1 - lhs->probability)*rhs->cost; expr->probability = lhs->probability + rhs->probability - lhs->probability*rhs->probability; - if (optlevel >= 3 && lhs->pure && rhs->pure) { - double swapped_cost = rhs->cost + (1 - rhs->probability)*lhs->cost; - if (swapped_cost < expr->cost) { - debug_opt(state, "-O3: cost: %e", expr); - expr->lhs = rhs; - expr->rhs = lhs; - debug_opt(state, " <==> %e (~%g --> ~%g)\n", expr, expr->cost, swapped_cost); - expr->cost = swapped_cost; - } - } - return expr; } @@ -619,6 +597,52 @@ done: return expr; } +/** Swap the children of a binary expression if it would reduce the cost. */ +static bool reorder_expr(const struct opt_state *state, struct expr *expr, double swapped_cost) { + if (swapped_cost < expr->cost) { + debug_opt(state, "-O3: cost: %e", expr); + struct expr *lhs = expr->lhs; + expr->lhs = expr->rhs; + expr->rhs = lhs; + debug_opt(state, " <==> %e (~%g --> ~%g)\n", expr, expr->cost, swapped_cost); + expr->cost = swapped_cost; + return true; + } else { + return false; + } +} + +/** + * Recursively reorder sub-expressions to reduce the overall cost. + * + * @param expr + * The expression to optimize. + * @return + * Whether any subexpression was reordered. + */ +static bool reorder_expr_recursive(const struct opt_state *state, struct expr *expr) { + bool ret = false; + struct expr *lhs = expr->lhs; + struct expr *rhs = expr->rhs; + + if (lhs) { + ret |= reorder_expr_recursive(state, lhs); + } + if (rhs) { + ret |= reorder_expr_recursive(state, rhs); + } + + if (expr->eval == eval_and || expr->eval == eval_or) { + if (lhs->pure && rhs->pure) { + double rhs_prob = expr->eval == eval_and ? rhs->probability : 1.0 - rhs->probability; + double swapped_cost = rhs->cost + rhs_prob*lhs->cost; + ret |= reorder_expr(state, expr, swapped_cost); + } + } + + return ret; +} + int optimize_cmdline(struct cmdline *cmdline) { struct opt_facts facts_when_impure; set_facts_impossible(&facts_when_impure); @@ -633,14 +657,23 @@ int optimize_cmdline(struct cmdline *cmdline) { .facts_when_impure = &facts_when_impure, }; + int optlevel = cmdline->optlevel; + cmdline->expr = optimize_expr_recursive(&state, cmdline->expr); if (!cmdline->expr) { return -1; } - cmdline->expr = ignore_result(&state, cmdline->expr); + if (optlevel >= 3 && reorder_expr_recursive(&state, cmdline->expr)) { + // Re-do optimizations to account for the new ordering + set_facts_impossible(&facts_when_impure); + cmdline->expr = optimize_expr_recursive(&state, cmdline->expr); + if (!cmdline->expr) { + return -1; + } + } - int optlevel = cmdline->optlevel; + cmdline->expr = ignore_result(&state, cmdline->expr); if (optlevel >= 2 && facts_when_impure.mindepth > cmdline->mindepth) { debug_opt(&state, "-O2: data flow: mindepth --> %d\n", facts_when_impure.mindepth); diff --git a/tests.sh b/tests.sh index 8532d10..1ad1568 100755 --- a/tests.sh +++ b/tests.sh @@ -227,11 +227,14 @@ posix_tests=( test_a test_o test_deep + test_or_purity test_double_negation test_de_morgan_not test_de_morgan_and test_de_morgan_or test_data_flow_type + test_data_flow_and_swap + test_data_flow_or_swap ) bsd_tests=( @@ -410,7 +413,6 @@ gnu_tests=( test_comma test_precedence test_and_purity - test_or_purity test_not_reachability test_comma_reachability test_print_error @@ -1589,6 +1591,14 @@ function test_data_flow_type() { bfs_diff basic \! \( -type f -o \! -type f \) } +function test_data_flow_and_swap() { + bfs_diff basic \! -type f -a -type d +} + +function test_data_flow_or_swap() { + bfs_diff basic \! \( -type f -o -not -type d \) +} + function test_print_error() { if [ -e /dev/full ]; then ! invoke_bfs basic -maxdepth 0 >/dev/full 2>/dev/null diff --git a/tests/test_data_flow_and_swap.out b/tests/test_data_flow_and_swap.out new file mode 100644 index 0000000..1e72fd9 --- /dev/null +++ b/tests/test_data_flow_and_swap.out @@ -0,0 +1,12 @@ +basic +basic/c +basic/e +basic/g +basic/i +basic/j +basic/k +basic/l +basic/g/h +basic/k/foo +basic/l/foo +basic/l/foo/bar diff --git a/tests/test_data_flow_or_swap.out b/tests/test_data_flow_or_swap.out new file mode 100644 index 0000000..1e72fd9 --- /dev/null +++ b/tests/test_data_flow_or_swap.out @@ -0,0 +1,12 @@ +basic +basic/c +basic/e +basic/g +basic/i +basic/j +basic/k +basic/l +basic/g/h +basic/k/foo +basic/l/foo +basic/l/foo/bar -- cgit v1.2.3 From fc76667077c0b6f769501d1bb25b1b41d5c38bf5 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 10 Sep 2018 20:33:01 -0400 Subject: exec: More fixes for bfs_exec_debug() changing errno --- exec.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/exec.c b/exec.c index 43ffad0..87bb5e6 100644 --- a/exec.c +++ b/exec.c @@ -368,12 +368,12 @@ static int bfs_exec_spawn(const struct bfs_exec *execbuf) { return -1; } - errno = 0; + int ret = -1; if (WIFEXITED(wstatus)) { int status = WEXITSTATUS(wstatus); if (status == EXIT_SUCCESS) { - return 0; + ret = 0; } else { bfs_exec_debug(execbuf, "Command '%s' failed with status %d\n", execbuf->argv[0], status); } @@ -384,7 +384,8 @@ static int bfs_exec_spawn(const struct bfs_exec *execbuf) { bfs_exec_debug(execbuf, "Command '%s' terminated abnormally\n", execbuf->argv[0]); } - return -1; + errno = 0; + return ret; } else { // Child close(pipefd[0]); -- cgit v1.2.3 From 727562e99082e9ed808b5ff6e02b65b9cf5b65c3 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 12 Sep 2018 00:12:28 -0400 Subject: exec: Don't leave zombies around if the child fails to exec() --- exec.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/exec.c b/exec.c index 87bb5e6..3cb05f4 100644 --- a/exec.c +++ b/exec.c @@ -355,12 +355,14 @@ static int bfs_exec_spawn(const struct bfs_exec *execbuf) { // Parent close(pipefd[1]); - int error; + int ret, error; ssize_t nbytes = read(pipefd[0], &error, sizeof(error)); close(pipefd[0]); if (nbytes == sizeof(error)) { - errno = error; - return -1; + ret = -1; + } else { + ret = 0; + error = 0; } int wstatus; @@ -368,23 +370,22 @@ static int bfs_exec_spawn(const struct bfs_exec *execbuf) { return -1; } - int ret = -1; - if (WIFEXITED(wstatus)) { int status = WEXITSTATUS(wstatus); - if (status == EXIT_SUCCESS) { - ret = 0; - } else { + if (status != EXIT_SUCCESS) { bfs_exec_debug(execbuf, "Command '%s' failed with status %d\n", execbuf->argv[0], status); + ret = -1; } } else if (WIFSIGNALED(wstatus)) { int sig = WTERMSIG(wstatus); bfs_exec_debug(execbuf, "Command '%s' terminated by signal %d\n", execbuf->argv[0], sig); + ret = -1; } else { bfs_exec_debug(execbuf, "Command '%s' terminated abnormally\n", execbuf->argv[0]); + ret = -1; } - errno = 0; + errno = error; return ret; } else { // Child @@ -407,7 +408,6 @@ static int bfs_exec_spawn(const struct bfs_exec *execbuf) { close(pipefd[1]); _Exit(EXIT_FAILURE); } - } /** exec() a command for a single file. */ -- cgit v1.2.3 From abf4394ae34bf25a17efb9fa560791005a6b217b Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 18 Sep 2018 21:29:59 -0400 Subject: spawn: New posix_spawn()-like API for exec --- Makefile | 4 +- exec.c | 98 +++++++++++---------------- spawn.c | 158 +++++++++++++++++++++++++++++++++++++++++++ spawn.h | 43 ++++++++++++ tests.sh | 9 --- tests/test_deep_stricter.out | 16 ----- 6 files changed, 243 insertions(+), 85 deletions(-) create mode 100644 spawn.c create mode 100644 spawn.h delete mode 100644 tests/test_deep_stricter.out diff --git a/Makefile b/Makefile index cb6a4a0..fcab96f 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ ############################################################################ # bfs # -# Copyright (C) 2015-2017 Tavian Barnes # +# Copyright (C) 2015-2018 Tavian Barnes # # # # Permission to use, copy, modify, and/or distribute this software for any # # purpose with or without fee is hereby granted. # @@ -51,7 +51,7 @@ ALL_LDFLAGS = $(ALL_CFLAGS) $(LDFLAGS) all: bfs -bfs: bftw.o color.o dstring.o eval.o exec.o main.o mtab.o opt.o parse.o printf.o stat.o typo.o util.o +bfs: bftw.o color.o dstring.o eval.o exec.o main.o mtab.o opt.o parse.o printf.o spawn.o stat.o typo.o util.o $(CC) $(ALL_LDFLAGS) $^ -o $@ sanitized: CFLAGS := -g $(WFLAGS) -fsanitize=address -fsanitize=undefined diff --git a/exec.c b/exec.c index 3cb05f4..c2163e3 100644 --- a/exec.c +++ b/exec.c @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2017 Tavian Barnes * + * Copyright (C) 2017-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * @@ -19,6 +19,7 @@ #include "cmdline.h" #include "color.h" #include "dstring.h" +#include "spawn.h" #include "util.h" #include #include @@ -339,75 +340,56 @@ static int bfs_exec_spawn(const struct bfs_exec *execbuf) { bfs_exec_debug(execbuf, "Executing '%s' ... [%zu arguments]\n", execbuf->argv[0], execbuf->argc - 1); } - // Use a pipe to report errors from the child - int pipefd[2] = {-1, -1}; - if (pipe_cloexec(pipefd) != 0) { - bfs_exec_debug(execbuf, "pipe() failed: %s\n", strerror(errno)); - } - - pid_t pid = fork(); + pid_t pid = -1; + int error; - if (pid < 0) { - close(pipefd[1]); - close(pipefd[0]); + struct bfs_spawn ctx; + if (bfs_spawn_init(&ctx) != 0) { return -1; - } else if (pid > 0) { - // Parent - close(pipefd[1]); - - int ret, error; - ssize_t nbytes = read(pipefd[0], &error, sizeof(error)); - close(pipefd[0]); - if (nbytes == sizeof(error)) { - ret = -1; - } else { - ret = 0; - error = 0; - } + } - int wstatus; - if (waitpid(pid, &wstatus, 0) < 0) { - return -1; - } + if (bfs_spawn_setflags(&ctx, BFS_SPAWN_USEPATH) != 0) { + goto fail; + } - if (WIFEXITED(wstatus)) { - int status = WEXITSTATUS(wstatus); - if (status != EXIT_SUCCESS) { - bfs_exec_debug(execbuf, "Command '%s' failed with status %d\n", execbuf->argv[0], status); - ret = -1; - } - } else if (WIFSIGNALED(wstatus)) { - int sig = WTERMSIG(wstatus); - bfs_exec_debug(execbuf, "Command '%s' terminated by signal %d\n", execbuf->argv[0], sig); - ret = -1; - } else { - bfs_exec_debug(execbuf, "Command '%s' terminated abnormally\n", execbuf->argv[0]); - ret = -1; + if (execbuf->wd_fd >= 0) { + if (bfs_spawn_addfchdir(&ctx, execbuf->wd_fd) != 0) { + goto fail; } + } + pid = bfs_spawn(execbuf->argv[0], &ctx, execbuf->argv, environ); +fail: + error = errno; + bfs_spawn_destroy(&ctx); + if (pid < 0) { errno = error; - return ret; - } else { - // Child - close(pipefd[0]); + return -1; + } - if (execbuf->wd_fd >= 0) { - if (fchdir(execbuf->wd_fd) != 0) { - goto child_err; - } - } + int wstatus; + if (waitpid(pid, &wstatus, 0) < 0) { + return -1; + } - execvp(execbuf->argv[0], execbuf->argv); + int ret = -1; - int error; - child_err: - error = errno; - if (write(pipefd[1], &error, sizeof(error)) != sizeof(error)) { - // Parent will still see that we exited unsuccessfully, but won't know why + if (WIFEXITED(wstatus)) { + int status = WEXITSTATUS(wstatus); + if (status == EXIT_SUCCESS) { + ret = 0; + } else { + bfs_exec_debug(execbuf, "Command '%s' failed with status %d\n", execbuf->argv[0], status); } - close(pipefd[1]); - _Exit(EXIT_FAILURE); + } else if (WIFSIGNALED(wstatus)) { + int sig = WTERMSIG(wstatus); + bfs_exec_debug(execbuf, "Command '%s' terminated by signal %d\n", execbuf->argv[0], sig); + } else { + bfs_exec_debug(execbuf, "Command '%s' terminated abnormally\n", execbuf->argv[0]); } + + errno = 0; + return ret; } /** exec() a command for a single file. */ diff --git a/spawn.c b/spawn.c new file mode 100644 index 0000000..82bce11 --- /dev/null +++ b/spawn.c @@ -0,0 +1,158 @@ +/**************************************************************************** + * bfs * + * Copyright (C) 2018 Tavian Barnes * + * * + * Permission to use, copy, modify, and/or distribute this software for any * + * purpose with or without fee is hereby granted. * + * * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * + ****************************************************************************/ + +#include "spawn.h" +#include "util.h" +#include +#include +#include +#include +#include +#include +#include + +/** + * Types of spawn actions. + */ +enum bfs_spawn_op { + BFS_SPAWN_FCHDIR, +}; + +/** + * A spawn action. + */ +struct bfs_spawn_action { + struct bfs_spawn_action *next; + + enum bfs_spawn_op op; + int fd; +}; + +int bfs_spawn_init(struct bfs_spawn *ctx) { + ctx->flags = 0; + ctx->actions = NULL; + ctx->tail = &ctx->actions; + return 0; +} + +int bfs_spawn_destroy(struct bfs_spawn *ctx) { + struct bfs_spawn_action *action = ctx->actions; + while (action) { + struct bfs_spawn_action *next = action->next; + free(action); + action = next; + } + return 0; +} + +int bfs_spawn_setflags(struct bfs_spawn *ctx, enum bfs_spawn_flags flags) { + ctx->flags = flags; + return 0; +} + +static struct bfs_spawn_action *bfs_spawn_add(struct bfs_spawn *ctx, enum bfs_spawn_op op) { + struct bfs_spawn_action *action = malloc(sizeof(*action)); + if (action) { + action->next = NULL; + action->op = op; + action->fd = -1; + + *ctx->tail = action; + ctx->tail = &action->next; + } + return action; +} + +int bfs_spawn_addfchdir(struct bfs_spawn *ctx, int fd) { + if (fd < 0) { + errno = EBADF; + return -1; + } + + struct bfs_spawn_action *action = bfs_spawn_add(ctx, BFS_SPAWN_FCHDIR); + if (action) { + action->fd = fd; + return 0; + } else { + return -1; + } +} + +static void bfs_spawn_exec(const char *file, const struct bfs_spawn *ctx, char **argv, char **envp, int pipefd[2]) { + int error; + enum bfs_spawn_flags flags = ctx ? ctx->flags : 0; + const struct bfs_spawn_action *actions = ctx ? ctx->actions : NULL; + + close(pipefd[0]); + + for (const struct bfs_spawn_action *action = actions; action; action = action->next) { + switch (action->op) { + case BFS_SPAWN_FCHDIR: + if (fchdir(action->fd) != 0) { + goto fail; + } + break; + } + } + + if (flags & BFS_SPAWN_USEPATH) { + execvpe(file, argv, envp); + } else { + execve(file, argv, envp); + } + +fail: + error = errno; + while (write(pipefd[1], &error, sizeof(error)) < sizeof(error)); + close(pipefd[1]); + _Exit(127); +} + +pid_t bfs_spawn(const char *file, const struct bfs_spawn *ctx, char **argv, char **envp) { + // Use a pipe to report errors from the child + int pipefd[2]; + if (pipe_cloexec(pipefd) != 0) { + return -1; + } + + int error; + pid_t pid = fork(); + + if (pid < 0) { + error = errno; + close(pipefd[1]); + close(pipefd[0]); + errno = error; + return -1; + } else if (pid == 0) { + // Child + bfs_spawn_exec(file, ctx, argv, envp, pipefd); + } + + // Parent + close(pipefd[1]); + + ssize_t nbytes = read(pipefd[0], &error, sizeof(error)); + close(pipefd[0]); + if (nbytes == sizeof(error)) { + int wstatus; + waitpid(pid, &wstatus, 0); + errno = error; + return -1; + } + + return pid; +} diff --git a/spawn.h b/spawn.h new file mode 100644 index 0000000..6a8a15c --- /dev/null +++ b/spawn.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * bfs * + * Copyright (C) 2018 Tavian Barnes * + * * + * Permission to use, copy, modify, and/or distribute this software for any * + * purpose with or without fee is hereby granted. * + * * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * + ****************************************************************************/ + +#ifndef BFS_SPAWN_H +#define BFS_SPAWN_H + +#include +#include +#include + +enum bfs_spawn_flags { + BFS_SPAWN_USEPATH = 1 << 0, +}; + +struct bfs_spawn { + enum bfs_spawn_flags flags; + struct bfs_spawn_action *actions; + struct bfs_spawn_action **tail; +}; + +int bfs_spawn_init(struct bfs_spawn *ctx); +int bfs_spawn_destroy(struct bfs_spawn *ctx); + +int bfs_spawn_setflags(struct bfs_spawn *ctx, enum bfs_spawn_flags flags); + +int bfs_spawn_addfchdir(struct bfs_spawn *ctx, int fd); + +pid_t bfs_spawn(const char *file, const struct bfs_spawn *ctx, char **argv, char **envp); + +#endif // BFS_SPAWN_H diff --git a/tests.sh b/tests.sh index 1ad1568..c732979 100755 --- a/tests.sh +++ b/tests.sh @@ -438,7 +438,6 @@ bfs_tests=( test_expr_path_flag test_colors test_deep_strict - test_deep_stricter ) BSD=yes @@ -1523,14 +1522,6 @@ function test_deep_strict() { bfs_diff deep -mindepth 18 -exec /bin/bash -c 'echo "${1:0:6}/.../${1##*/} (${#1})"' /bin/bash '{}' \; } -function test_deep_stricter() { - closefrom 4 - - # So few fds that pipe() fails in the -exec implementation - ulimit -n 6 - bfs_diff deep -mindepth 18 -exec /bin/bash -c 'echo "${1:0:6}/.../${1##*/} (${#1})"' /bin/bash '{}' \; -} - function test_exit() { invoke_bfs basic -name foo -exit 42 if [ $? -ne 42 ]; then diff --git a/tests/test_deep_stricter.out b/tests/test_deep_stricter.out deleted file mode 100644 index c385fce..0000000 --- a/tests/test_deep_stricter.out +++ /dev/null @@ -1,16 +0,0 @@ -deep/0/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/1/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/2/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/3/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/4/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/5/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/6/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/7/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/8/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/9/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/A/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/B/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/C/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/D/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/E/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -deep/F/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358) -- cgit v1.2.3 From a68b6d13ef4137596d4d9ec6f653c76503cc7702 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 19 Sep 2018 18:11:39 -0400 Subject: spawn: Implement execvpe() on platforms that lack it Credit to https://github.com/nim-lang/Nim/issues/3138 for the idea to just overwrite environ and call execvp() instead of duplicating the path searching logic. --- spawn.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/spawn.c b/spawn.c index 82bce11..a54303f 100644 --- a/spawn.c +++ b/spawn.c @@ -91,6 +91,16 @@ int bfs_spawn_addfchdir(struct bfs_spawn *ctx, int fd) { } } +static int bfs_execvpe(const char *file, char **argv, char **envp) { +#if __GLIBC__ || __linux__ || __NetBSD__ || __OpenBSD__ + return execvpe(file, argv, envp); +#else + extern char **environ; + environ = envp; + return execvp(file, argv); +#endif +} + static void bfs_spawn_exec(const char *file, const struct bfs_spawn *ctx, char **argv, char **envp, int pipefd[2]) { int error; enum bfs_spawn_flags flags = ctx ? ctx->flags : 0; @@ -109,7 +119,7 @@ static void bfs_spawn_exec(const char *file, const struct bfs_spawn *ctx, char * } if (flags & BFS_SPAWN_USEPATH) { - execvpe(file, argv, envp); + bfs_execvpe(file, argv, envp); } else { execve(file, argv, envp); } -- cgit v1.2.3 From b5c9656a2f5be060491fae98f589f66855b8a638 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 19 Sep 2018 18:41:33 -0400 Subject: spawn: Add some docs --- spawn.c | 19 +++++++++++-------- spawn.h | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/spawn.c b/spawn.c index a54303f..ffc3d2e 100644 --- a/spawn.c +++ b/spawn.c @@ -63,6 +63,7 @@ int bfs_spawn_setflags(struct bfs_spawn *ctx, enum bfs_spawn_flags flags) { return 0; } +/** Add a spawn action to the chain. */ static struct bfs_spawn_action *bfs_spawn_add(struct bfs_spawn *ctx, enum bfs_spawn_op op) { struct bfs_spawn_action *action = malloc(sizeof(*action)); if (action) { @@ -91,17 +92,19 @@ int bfs_spawn_addfchdir(struct bfs_spawn *ctx, int fd) { } } -static int bfs_execvpe(const char *file, char **argv, char **envp) { +/** Facade for execvpe() which is non-standard. */ +static int bfs_execvpe(const char *exe, char **argv, char **envp) { #if __GLIBC__ || __linux__ || __NetBSD__ || __OpenBSD__ - return execvpe(file, argv, envp); + return execvpe(exe, argv, envp); #else extern char **environ; environ = envp; - return execvp(file, argv); + return execvp(exe, argv); #endif } -static void bfs_spawn_exec(const char *file, const struct bfs_spawn *ctx, char **argv, char **envp, int pipefd[2]) { +/** Actually exec() the new process. */ +static void bfs_spawn_exec(const char *exe, const struct bfs_spawn *ctx, char **argv, char **envp, int pipefd[2]) { int error; enum bfs_spawn_flags flags = ctx ? ctx->flags : 0; const struct bfs_spawn_action *actions = ctx ? ctx->actions : NULL; @@ -119,9 +122,9 @@ static void bfs_spawn_exec(const char *file, const struct bfs_spawn *ctx, char * } if (flags & BFS_SPAWN_USEPATH) { - bfs_execvpe(file, argv, envp); + bfs_execvpe(exe, argv, envp); } else { - execve(file, argv, envp); + execve(exe, argv, envp); } fail: @@ -131,7 +134,7 @@ fail: _Exit(127); } -pid_t bfs_spawn(const char *file, const struct bfs_spawn *ctx, char **argv, char **envp) { +pid_t bfs_spawn(const char *exe, const struct bfs_spawn *ctx, char **argv, char **envp) { // Use a pipe to report errors from the child int pipefd[2]; if (pipe_cloexec(pipefd) != 0) { @@ -149,7 +152,7 @@ pid_t bfs_spawn(const char *file, const struct bfs_spawn *ctx, char **argv, char return -1; } else if (pid == 0) { // Child - bfs_spawn_exec(file, ctx, argv, envp, pipefd); + bfs_spawn_exec(exe, ctx, argv, envp, pipefd); } // Parent diff --git a/spawn.h b/spawn.h index 6a8a15c..ef510e1 100644 --- a/spawn.h +++ b/spawn.h @@ -21,23 +21,65 @@ #include #include +/** + * bfs_spawn() flags. + */ enum bfs_spawn_flags { + /** Use the PATH variable to resolve the executable (like execvp()). */ BFS_SPAWN_USEPATH = 1 << 0, }; +/** + * bfs_spawn() attributes, controlling the context of the new process. + */ struct bfs_spawn { enum bfs_spawn_flags flags; struct bfs_spawn_action *actions; struct bfs_spawn_action **tail; }; +/** + * Create a new bfs_spawn() context. + * + * @return 0 on success, -1 on failure. + */ int bfs_spawn_init(struct bfs_spawn *ctx); + +/** + * Destroy a bfs_spawn() context. + * + * @return 0 on success, -1 on failure. + */ int bfs_spawn_destroy(struct bfs_spawn *ctx); +/** + * Set the flags for a bfs_spawn() context. + * + * @return 0 on success, -1 on failure. + */ int bfs_spawn_setflags(struct bfs_spawn *ctx, enum bfs_spawn_flags flags); +/** + * Add an fchdir() action to a bfs_spawn() context. + * + * @return 0 on success, -1 on failure. + */ int bfs_spawn_addfchdir(struct bfs_spawn *ctx, int fd); -pid_t bfs_spawn(const char *file, const struct bfs_spawn *ctx, char **argv, char **envp); +/** + * Spawn a new process. + * + * @param exe + * The executable to run. + * @param ctx + * The context for the new process. + * @param argv + * The arguments for the new process. + * @param envp + * The environment variables for the new process. + * @return + * The PID of the new process, or -1 on error. + */ +pid_t bfs_spawn(const char *exe, const struct bfs_spawn *ctx, char **argv, char **envp); #endif // BFS_SPAWN_H -- cgit v1.2.3 From 50b8a56d0057244725aa7408857c61da3ec1a768 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 24 Sep 2018 23:09:38 -0400 Subject: Update copyright dates --- Makefile | 2 +- bfs.h | 2 +- bftw.c | 2 +- bftw.h | 2 +- cmdline.h | 2 +- color.c | 2 +- color.h | 2 +- eval.c | 2 +- eval.h | 2 +- exec.c | 2 +- expr.h | 2 +- mtab.c | 2 +- mtab.h | 2 +- opt.c | 2 +- parse.c | 2 +- printf.c | 2 +- printf.h | 2 +- util.c | 2 +- util.h | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index cb6a4a0..d63fbe3 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ ############################################################################ # bfs # -# Copyright (C) 2015-2017 Tavian Barnes # +# Copyright (C) 2015-2018 Tavian Barnes # # # # Permission to use, copy, modify, and/or distribute this software for any # # purpose with or without fee is hereby granted. # diff --git a/bfs.h b/bfs.h index 5ed6620..6624ed4 100644 --- a/bfs.h +++ b/bfs.h @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2015-2017 Tavian Barnes * + * Copyright (C) 2015-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/bftw.c b/bftw.c index 000fd2b..295c09f 100644 --- a/bftw.c +++ b/bftw.c @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2015-2017 Tavian Barnes * + * Copyright (C) 2015-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/bftw.h b/bftw.h index ebdd5d3..c874188 100644 --- a/bftw.h +++ b/bftw.h @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2015-2017 Tavian Barnes * + * Copyright (C) 2015-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/cmdline.h b/cmdline.h index b8d22d8..df49dd6 100644 --- a/cmdline.h +++ b/cmdline.h @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2015-2017 Tavian Barnes * + * Copyright (C) 2015-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/color.c b/color.c index cb73d3f..bf6cf4d 100644 --- a/color.c +++ b/color.c @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2015-2017 Tavian Barnes * + * Copyright (C) 2015-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/color.h b/color.h index ac3d9b6..419180c 100644 --- a/color.h +++ b/color.h @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2015-2017 Tavian Barnes * + * Copyright (C) 2015-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/eval.c b/eval.c index 6731b31..15dddf4 100644 --- a/eval.c +++ b/eval.c @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2015-2017 Tavian Barnes * + * Copyright (C) 2015-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/eval.h b/eval.h index 5bf1682..d826176 100644 --- a/eval.h +++ b/eval.h @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2015-2017 Tavian Barnes * + * Copyright (C) 2015-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/exec.c b/exec.c index 3cb05f4..7d44d60 100644 --- a/exec.c +++ b/exec.c @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2017 Tavian Barnes * + * Copyright (C) 2017-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/expr.h b/expr.h index 9644a0d..b7c5c15 100644 --- a/expr.h +++ b/expr.h @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2015-2017 Tavian Barnes * + * Copyright (C) 2015-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/mtab.c b/mtab.c index 363d3db..4d9e1d8 100644 --- a/mtab.c +++ b/mtab.c @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2017 Tavian Barnes * + * Copyright (C) 2017-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/mtab.h b/mtab.h index f23c036..e8a021c 100644 --- a/mtab.h +++ b/mtab.h @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2017 Tavian Barnes * + * Copyright (C) 2017-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/opt.c b/opt.c index 6875e92..5e3dc19 100644 --- a/opt.c +++ b/opt.c @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2017 Tavian Barnes * + * Copyright (C) 2017-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/parse.c b/parse.c index 7f9ac9c..c8faed3 100644 --- a/parse.c +++ b/parse.c @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2015-2017 Tavian Barnes * + * Copyright (C) 2015-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/printf.c b/printf.c index c2b165e..8643f68 100644 --- a/printf.c +++ b/printf.c @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2017 Tavian Barnes * + * Copyright (C) 2017-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/printf.h b/printf.h index 353c82d..27336eb 100644 --- a/printf.h +++ b/printf.h @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2017 Tavian Barnes * + * Copyright (C) 2017-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/util.c b/util.c index aaddaa0..9730a5e 100644 --- a/util.c +++ b/util.c @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2016-2017 Tavian Barnes * + * Copyright (C) 2016-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * diff --git a/util.h b/util.h index 81caf12..f0512f7 100644 --- a/util.h +++ b/util.h @@ -1,6 +1,6 @@ /**************************************************************************** * bfs * - * Copyright (C) 2016-2017 Tavian Barnes * + * Copyright (C) 2016-2018 Tavian Barnes * * * * Permission to use, copy, modify, and/or distribute this software for any * * purpose with or without fee is hereby granted. * -- cgit v1.2.3 From ce1118b27fdbf7886b108b5c805107e98e75194a Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 24 Sep 2018 23:10:37 -0400 Subject: Release 1.2.4 --- Makefile | 2 +- RELEASES.md | 13 +++++++++++++ bfs.h | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d63fbe3..b18c61a 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ ############################################################################ ifeq ($(wildcard .git),) -VERSION := 1.2.3 +VERSION := 1.2.4 else VERSION := $(shell git describe --always) endif diff --git a/RELEASES.md b/RELEASES.md index fcc3e14..9e34a3b 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -2,6 +2,19 @@ === +1.2.4 +----- + +**September 24, 2018** + +- GNU find compatibility fixes for `-printf`: + - `%Y` now prints `?` if an error occurs resolving the link + - `%B` is now supported for birth/creation time (as well as `%W`/`%w`) + - All standard `strftime()` formats are supported, not just the ones from the GNU find manual +- Optimizations are now re-run if any expressions are reordered +- `-exec` and friends no longer leave zombie processes around when `exec()` fails + + 1.2.3 ----- diff --git a/bfs.h b/bfs.h index 6624ed4..d53e628 100644 --- a/bfs.h +++ b/bfs.h @@ -18,7 +18,7 @@ #define BFS_H #ifndef BFS_VERSION -# define BFS_VERSION "1.2.3" +# define BFS_VERSION "1.2.4" #endif #ifndef BFS_HOMEPAGE -- cgit v1.2.3 From 26ee90f1fe64c333f6b87f3202eadec745d2071a Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 26 Sep 2018 19:37:11 -0400 Subject: Update some more copyright dates --- COPYING | 2 +- tests.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/COPYING b/COPYING index f99675f..670e870 100644 --- a/COPYING +++ b/COPYING @@ -1,4 +1,4 @@ -Copyright (C) 2015-2017 Tavian Barnes +Copyright (C) 2015-2018 Tavian Barnes Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. diff --git a/tests.sh b/tests.sh index c732979..0664612 100755 --- a/tests.sh +++ b/tests.sh @@ -2,7 +2,7 @@ ############################################################################ # bfs # -# Copyright (C) 2015-2017 Tavian Barnes # +# Copyright (C) 2015-2018 Tavian Barnes # # # # Permission to use, copy, modify, and/or distribute this software for any # # purpose with or without fee is hereby granted. # -- cgit v1.2.3 From 4d57db8436dcdeb1a1ab428a057f59c2f2512f3c Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 26 Sep 2018 19:37:49 -0400 Subject: tests: Remove non-POSIX features from POSIX tests Credit to http://core.suckless.org/sbase/ for identifying these. --- tests.sh | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/tests.sh b/tests.sh index 0664612..4898c1c 100755 --- a/tests.sh +++ b/tests.sh @@ -139,11 +139,13 @@ function make_deep() { mkdir "$1/$i" cd "$1/$i" - # 17 * 256 > 16 * 256 == 4096 == PATH_MAX - for j in {1..17}; do + # 16 * 256 == 4096 == PATH_MAX + for j in {1..16}; do mkdir "$name" cd "$name" 2>/dev/null done + + touch "$name" ) done } @@ -169,14 +171,8 @@ posix_tests=( test_basic test_type_d test_type_f - test_mindepth - test_maxdepth test_depth test_depth_slash - test_depth_mindepth_1 - test_depth_mindepth_2 - test_depth_maxdepth_1 - test_depth_maxdepth_2 test_depth_error test_name test_name_root @@ -242,6 +238,12 @@ bsd_tests=( test_P_slash test_X test_follow + test_mindepth + test_maxdepth + test_depth_mindepth_1 + test_depth_mindepth_2 + test_depth_maxdepth_1 + test_depth_maxdepth_2 test_samefile test_samefile_symlink test_H_samefile_symlink @@ -311,6 +313,12 @@ bsd_tests=( ) gnu_tests=( + test_mindepth + test_maxdepth + test_depth_mindepth_1 + test_depth_mindepth_2 + test_depth_maxdepth_1 + test_depth_maxdepth_2 test_true test_false test_executable @@ -1176,12 +1184,12 @@ function test_permcopy() { function test_ok_stdin() { # -ok should *not* close stdin # See https://savannah.gnu.org/bugs/?24561 - yes | bfs_diff basic -ok bash -c "printf '%s? ' {} && head -n1" \; 2>/dev/null + yes | bfs_diff basic -ok bash -c 'printf "%s? " "$1" && head -n1' bash '{}' \; 2>/dev/null } function test_okdir_stdin() { # -okdir should *not* close stdin - yes | bfs_diff basic -okdir bash -c "printf '%s? ' {} && head -n1" \; 2>/dev/null + yes | bfs_diff basic -okdir bash -c 'printf "%s? " "$1" && head -n1' bash '{}' \; 2>/dev/null } function test_ok_plus_semicolon() { @@ -1511,7 +1519,7 @@ function test_deep() { closefrom 4 ulimit -n 16 - bfs_diff deep -mindepth 18 -exec /bin/bash -c 'echo "${1:0:6}/.../${1##*/} (${#1})"' /bin/bash '{}' \; + bfs_diff deep -type f -exec bash -c 'echo "${1:0:6}/.../${1##*/} (${#1})"' bash '{}' \; } function test_deep_strict() { @@ -1519,7 +1527,7 @@ function test_deep_strict() { # Not even enough fds to keep the root open ulimit -n 7 - bfs_diff deep -mindepth 18 -exec /bin/bash -c 'echo "${1:0:6}/.../${1##*/} (${#1})"' /bin/bash '{}' \; + bfs_diff deep -type f -exec bash -c 'echo "${1:0:6}/.../${1##*/} (${#1})"' bash '{}' \; } function test_exit() { @@ -1587,7 +1595,7 @@ function test_data_flow_and_swap() { } function test_data_flow_or_swap() { - bfs_diff basic \! \( -type f -o -not -type d \) + bfs_diff basic \! \( -type f -o \! -type d \) } function test_print_error() { -- cgit v1.2.3 From 9198235d8184cab0fc84e967c149f6a2a7293b52 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 27 Sep 2018 23:04:35 -0400 Subject: tests: Move test for -H -newer out of POSIX The POSIX spec implies that -newer is actually not supposed to respect -H/-L. But all implementations I know about do anyway. --- tests.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests.sh b/tests.sh index 4898c1c..dfbda09 100755 --- a/tests.sh +++ b/tests.sh @@ -188,7 +188,6 @@ posix_tests=( test_H_slash test_H_broken test_H_notdir - test_H_newer test_L test_L_broken test_L_notdir @@ -262,6 +261,7 @@ bsd_tests=( test_ilname test_L_lname test_L_ilname + test_H_newer test_newerma test_size_big test_exec_substring @@ -331,6 +331,7 @@ gnu_tests=( test_uid test_uid_plus test_uid_minus + test_H_newer test_anewer test_P test_P_slash -- cgit v1.2.3 From 7b8729f6d3b799f4a7a55348c8baae7f52134862 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 27 Sep 2018 23:37:39 -0400 Subject: tests: Sort test lists --- tests.sh | 451 +++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 292 insertions(+), 159 deletions(-) diff --git a/tests.sh b/tests.sh index dfbda09..226bd34 100755 --- a/tests.sh +++ b/tests.sh @@ -168,42 +168,60 @@ BFS="$(_realpath ./bfs)" TESTS="$(_realpath ./tests)" posix_tests=( + # General parsing + test_parens + test_bang + test_implicit_and + test_a + test_o + test_basic - test_type_d - test_type_f - test_depth - test_depth_slash - test_depth_error - test_name - test_name_root - test_name_root_depth - test_name_trailing_slash - test_path - test_newer - test_newer_link - test_links - test_links_plus - test_links_minus + + # Flags + test_H test_H_slash test_H_broken test_H_notdir + test_L test_L_broken test_L_notdir + + test_flag_comma + + # Primaries + + test_depth + test_depth_slash + test_depth_error test_L_depth - test_user_name - test_user_id - test_group_name - test_group_id - test_size - test_size_plus - test_size_bytes + test_exec test_exec_plus test_exec_plus_status test_exec_plus_semicolon - test_flag_comma + + test_group_name + test_group_id + + test_links + test_links_plus + test_links_minus + + test_name + test_name_root + test_name_root_depth + test_name_trailing_slash + + test_newer + test_newer_link + + test_ok_stdin + test_ok_plus_semicolon + + test_path + test_perm_000 test_perm_000_minus test_perm_222 @@ -214,14 +232,21 @@ posix_tests=( test_perm_symbolic_minus test_perm_leading_plus_symbolic_minus test_permcopy - test_ok_stdin - test_ok_plus_semicolon - test_parens - test_bang - test_implicit_and - test_a - test_o + + test_size + test_size_plus + test_size_bytes + + test_type_d + test_type_f + + test_user_name + test_user_id + + # PATH_MAX handling test_deep + + # Optimizer tests test_or_purity test_double_negation test_de_morgan_not @@ -233,55 +258,32 @@ posix_tests=( ) bsd_tests=( + # Flags + + test_E + test_P test_P_slash + test_X - test_follow - test_mindepth - test_maxdepth - test_depth_mindepth_1 - test_depth_mindepth_2 - test_depth_maxdepth_1 - test_depth_maxdepth_2 - test_samefile - test_samefile_symlink - test_H_samefile_symlink - test_L_samefile_symlink - test_samefile_broken - test_H_samefile_broken - test_L_samefile_broken - test_samefile_notdir - test_H_samefile_notdir - test_L_samefile_notdir - test_name_slash - test_name_slashes - test_iname - test_ipath - test_lname - test_ilname - test_L_lname - test_L_ilname - test_H_newer - test_newerma - test_size_big - test_exec_substring - test_execdir_pwd - test_execdir_slash - test_execdir_slash_pwd - test_execdir_slashes + + test_d_path + + test_f + test_double_dash test_flag_double_dash - test_ok_stdin - test_okdir_stdin + + # Primaries + test_delete test_L_delete - test_rm - test_regex - test_iregex - test_regex_parens - test_E - test_d_path - test_f + + test_depth_maxdepth_1 + test_depth_maxdepth_2 + test_depth_mindepth_1 + test_depth_mindepth_2 + test_depth_n test_depth_n_plus test_depth_n_minus @@ -289,14 +291,63 @@ bsd_tests=( test_depth_depth_n_plus test_depth_depth_n_minus test_depth_overflow + test_data_flow_depth + + test_exec_substring + + test_execdir_pwd + test_execdir_slash + test_execdir_slash_pwd + test_execdir_slashes + + test_exit + + test_follow + test_gid_name - test_uid_name + + test_ilname + test_L_ilname + + test_iname + + test_inum + + test_ipath + + test_iregex + + test_lname + test_L_lname + + test_maxdepth + + test_mindepth + test_mnewer test_H_mnewer + + test_name_slash + test_name_slashes + + test_H_newer + + test_newerma + + test_nogroup + + test_nouser + + test_ok_stdin + + test_okdir_stdin + test_perm_000_plus test_perm_222_plus test_perm_644_plus - test_size_T + + test_printx + test_quit test_quit_child test_quit_depth @@ -304,38 +355,12 @@ bsd_tests=( test_quit_after_print test_quit_before_print test_quit_implicit_print - test_inum - test_nogroup - test_nouser - test_exit - test_printx - test_data_flow_depth -) -gnu_tests=( - test_mindepth - test_maxdepth - test_depth_mindepth_1 - test_depth_mindepth_2 - test_depth_maxdepth_1 - test_depth_maxdepth_2 - test_true - test_false - test_executable - test_readable - test_writable - test_empty - test_gid - test_gid_plus - test_gid_minus - test_uid - test_uid_plus - test_uid_minus - test_H_newer - test_anewer - test_P - test_P_slash - test_follow + test_rm + + test_regex + test_regex_parens + test_samefile test_samefile_symlink test_H_samefile_symlink @@ -346,23 +371,56 @@ gnu_tests=( test_samefile_notdir test_H_samefile_notdir test_L_samefile_notdir - test_xtype_l - test_xtype_f - test_L_xtype_l - test_L_xtype_f - test_name_slash - test_name_slashes - test_iname - test_ipath - test_lname - test_ilname - test_L_lname - test_L_ilname + + test_size_T + test_size_big + + test_uid_name +) + +gnu_tests=( + # General parsing + + test_not + test_and + test_or + test_comma + test_precedence + + test_weird_names + test_flag_weird_names + + test_follow_comma + + # Flags + + test_P + test_P_slash + + test_double_dash + test_flag_double_dash + + # Primaries + + test_anewer + + test_path_d + test_daystart test_daystart_twice - test_newerma - test_size_big + + test_delete + test_L_delete + + test_depth_mindepth_1 + test_depth_mindepth_2 + test_depth_maxdepth_1 + test_depth_maxdepth_2 + + test_empty + test_exec_substring + test_execdir test_execdir_substring test_execdir_plus_semicolon @@ -370,37 +428,66 @@ gnu_tests=( test_execdir_slash test_execdir_slash_pwd test_execdir_slashes - test_okdir_plus_semicolon - test_weird_names - test_flag_weird_names - test_follow_comma + + test_executable + + test_false + + test_follow + test_fprint test_fprint_duplicate - test_double_dash - test_flag_double_dash + test_fprint_error + + test_fstype + + test_gid + test_gid_plus + test_gid_minus + test_ignore_readdir_race test_ignore_readdir_race_root test_ignore_readdir_race_notdir + + test_ilname + test_L_ilname + + test_iname + + test_inum + + test_ipath + + test_iregex + + test_lname + test_L_lname + + test_maxdepth + + test_mindepth + + test_name_slash + test_name_slashes + + test_H_newer + + test_newerma + + test_nogroup + + test_nouser + + test_okdir_plus_semicolon + test_perm_000_slash test_perm_222_slash test_perm_644_slash test_perm_symbolic_slash test_perm_leading_plus_symbolic_slash - test_delete - test_L_delete - test_regex - test_iregex - test_regex_parens - test_regextype_posix_basic - test_regextype_posix_extended - test_path_d - test_quit - test_quit_child - test_quit_depth - test_quit_depth_child - test_inum - test_nogroup - test_nouser + + test_print_error + test_printf test_printf_slash test_printf_slashes @@ -413,39 +500,85 @@ gnu_tests=( test_printf_leak test_printf_nul test_printf_Y_error + + test_quit + test_quit_child + test_quit_depth + test_quit_depth_child test_quit_after_print test_quit_before_print - test_fstype - test_not - test_and - test_or - test_comma - test_precedence + + test_readable + + test_regex + test_regex_parens + + test_regextype_posix_basic + test_regextype_posix_extended + + test_samefile + test_samefile_symlink + test_H_samefile_symlink + test_L_samefile_symlink + test_samefile_broken + test_H_samefile_broken + test_L_samefile_broken + test_samefile_notdir + test_H_samefile_notdir + test_L_samefile_notdir + + test_size_big + + test_true + + test_uid + test_uid_plus + test_uid_minus + + test_writable + + test_xtype_l + test_xtype_f + test_L_xtype_l + test_L_xtype_f + + # Optimizer tests test_and_purity test_not_reachability test_comma_reachability - test_print_error - test_fprint_error ) bfs_tests=( - test_type_multi - test_xtype_multi - test_xtype_reorder - test_perm_symbolic_trailing_comma - test_perm_symbolic_double_comma - test_perm_symbolic_missing_action - test_perm_leading_plus_symbolic - test_execdir_plus - test_hidden - test_nohidden - test_printf_w + # General parsing test_path_flag_expr test_path_expr_flag test_flag_expr_path test_expr_flag_path test_expr_path_flag + + # Primaries + test_colors + + test_execdir_plus + + test_hidden + + test_nohidden + + test_perm_symbolic_trailing_comma + test_perm_symbolic_double_comma + test_perm_symbolic_missing_action + test_perm_leading_plus_symbolic + + test_printf_w + + test_type_multi + + test_xtype_multi + test_xtype_reorder + + # PATH_MAX handling test_deep_strict ) -- cgit v1.2.3 From 3f05616d94eedc9429bafdd28075ba911bf4de69 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 1 Nov 2018 21:46:50 -0400 Subject: Remove man page on make uninstall --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 35a1496..6863832 100644 --- a/Makefile +++ b/Makefile @@ -77,6 +77,7 @@ install: uninstall: $(RM) $(DESTDIR)$(PREFIX)/bin/bfs + $(RM) $(DESTDIR)$(PREFIX)/share/man/man1/bfs.1 .PHONY: all release check clean install uninstall -- cgit v1.2.3 From 1358b69c22ac9f675f6a4d0c0d796e8dae7823fd Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 1 Nov 2018 21:46:50 -0400 Subject: tests: Add testcases for -prune --- tests.sh | 16 ++++++++++++++++ tests/test_not_prune.out | 13 +++++++++++++ tests/test_prune.out | 3 +++ tests/test_prune_or_print.out | 13 +++++++++++++ 4 files changed, 45 insertions(+) create mode 100644 tests/test_not_prune.out create mode 100644 tests/test_prune.out create mode 100644 tests/test_prune_or_print.out diff --git a/tests.sh b/tests.sh index 226bd34..3f22b22 100755 --- a/tests.sh +++ b/tests.sh @@ -233,6 +233,10 @@ posix_tests=( test_perm_leading_plus_symbolic_minus test_permcopy + test_prune + test_prune_or_print + test_not_prune + test_size test_size_plus test_size_bytes @@ -1315,6 +1319,18 @@ function test_permcopy() { bfs_diff perms -perm u+rw,g+u-w,o=g } +function test_prune() { + bfs_diff basic -name foo -prune +} + +function test_prune_or_print() { + bfs_diff basic -name foo -prune -o -print +} + +function test_not_prune() { + bfs_diff basic \! \( -name foo -prune \) +} + function test_ok_stdin() { # -ok should *not* close stdin # See https://savannah.gnu.org/bugs/?24561 diff --git a/tests/test_not_prune.out b/tests/test_not_prune.out new file mode 100644 index 0000000..40e2ea0 --- /dev/null +++ b/tests/test_not_prune.out @@ -0,0 +1,13 @@ +basic +basic/a +basic/b +basic/c +basic/e +basic/g +basic/i +basic/j +basic/k +basic/l