diff options
-rw-r--r-- | cmdline.h | 14 | ||||
-rw-r--r-- | diag.c | 10 | ||||
-rw-r--r-- | exec.c | 11 | ||||
-rw-r--r-- | exec.h | 4 | ||||
-rw-r--r-- | fsade.c | 88 | ||||
-rw-r--r-- | parse.c | 55 |
6 files changed, 95 insertions, 87 deletions
@@ -87,16 +87,18 @@ struct cmdline { /** bftw() search strategy. */ enum bftw_strategy strategy; - /** Optimization level. */ + /** Optimization level (-O). */ int optlevel; - /** Debugging flags. */ + /** Debugging flags (-D). */ enum debug_flags debug; - /** Whether to only handle paths with xargs-safe characters. */ - bool xargs_safe; - /** Whether to ignore deletions that race with bfs. */ + /** Whether to ignore deletions that race with bfs (-ignore_readdir_race). */ bool ignore_races; - /** Whether to only return unique files. */ + /** Whether to only return unique files (-unique). */ bool unique; + /** Whether to print warnings (-warn/-nowarn). */ + bool warn; + /** Whether to only handle paths with xargs-safe characters (-X). */ + bool xargs_safe; /** The command line expression. */ struct expr *expr; @@ -47,12 +47,14 @@ void bfs_verror(const struct cmdline *cmdline, const char *format, va_list args) } void bfs_vwarning(const struct cmdline *cmdline, const char *format, va_list args) { - int error = errno; + if (cmdline->warn) { + int error = errno; - bfs_warning_prefix(cmdline); + bfs_warning_prefix(cmdline); - errno = error; - cvfprintf(cmdline->cerr, format, args); + errno = error; + cvfprintf(cmdline->cerr, format, args); + } } void bfs_error_prefix(const struct cmdline *cmdline) { @@ -37,7 +37,7 @@ /** Print some debugging info. */ BFS_FORMATTER(2, 3) static void bfs_exec_debug(const struct bfs_exec *execbuf, const char *format, ...) { - if (!(execbuf->flags & BFS_EXEC_DEBUG)) { + if (!(execbuf->cmdline->debug & DEBUG_EXEC)) { return; } @@ -123,6 +123,7 @@ struct bfs_exec *parse_bfs_exec(char **argv, enum bfs_exec_flags flags, const st } execbuf->flags = flags; + execbuf->cmdline = cmdline; execbuf->argv = NULL; execbuf->argc = 0; execbuf->argv_cap = 0; @@ -133,10 +134,6 @@ struct bfs_exec *parse_bfs_exec(char **argv, enum bfs_exec_flags flags, const st execbuf->wd_len = 0; execbuf->ret = 0; - if (cmdline->debug & DEBUG_EXEC) { - execbuf->flags |= BFS_EXEC_DEBUG; - } - size_t i; for (i = 1; ; ++i) { const char *arg = argv[i]; @@ -391,9 +388,9 @@ fail: } } else if (WIFSIGNALED(wstatus)) { int sig = WTERMSIG(wstatus); - bfs_exec_debug(execbuf, "Command '%s' terminated by signal %d\n", execbuf->argv[0], sig); + bfs_warning(execbuf->cmdline, "Command '${ex}%s${rs}' terminated by signal %d\n", execbuf->argv[0], sig); } else { - bfs_exec_debug(execbuf, "Command '%s' terminated abnormally\n", execbuf->argv[0]); + bfs_warning(execbuf->cmdline, "Command '${ex}%s${rs}' terminated abnormally\n", execbuf->argv[0]); } errno = 0; @@ -36,8 +36,6 @@ enum bfs_exec_flags { BFS_EXEC_CHDIR = 1 << 1, /** Pass multiple files at once to the command (-exec ... {} +). */ BFS_EXEC_MULTI = 1 << 2, - /** Print debugging information (-D exec). */ - BFS_EXEC_DEBUG = 1 << 3, }; /** @@ -47,6 +45,8 @@ struct bfs_exec { /** Flags for this exec buffer. */ enum bfs_exec_flags flags; + /** The overall command line. */ + const struct cmdline *cmdline; /** Command line template. */ char **tmpl_argv; /** Command line template size. */ @@ -126,29 +126,10 @@ static bool is_absence_error(int error) { #if BFS_CAN_CHECK_ACL -/** Check if any ACLs of the given type are non-trivial. */ -static int bfs_check_acl_type(const char *path, acl_type_t type) { - acl_t acl = acl_get_file(path, type); - if (!acl) { - if (is_absence_error(errno)) { - return 0; - } else { - return -1; - } - } - +/** Check if a POSIX.1e ACL is non-trivial. */ +static int bfs_check_posix1e_acl(acl_t acl, bool ignore_required) { int ret = 0; -#if __FreeBSD__ - int trivial; - if (acl_is_trivial_np(acl, &trivial) < 0) { - ret = -1; - } else if (trivial) { - ret = 0; - } else { - ret = 1; - } -#else acl_entry_t entry; for (int status = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); #if __APPLE__ @@ -160,27 +141,46 @@ static int bfs_check_acl_type(const char *path, acl_type_t type) { #endif status = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry)) { #if defined(ACL_USER_OBJ) && defined(ACL_GROUP_OBJ) && defined(ACL_OTHER) - acl_tag_t tag; - if (acl_get_tag_type(entry, &tag) != 0) { - continue; - } - if (tag != ACL_USER_OBJ && tag != ACL_GROUP_OBJ && tag != ACL_OTHER) { - ret = 1; - break; + if (ignore_required) { + acl_tag_t tag; + if (acl_get_tag_type(entry, &tag) != 0) { + ret = -1; + continue; + } + if (tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER) { + continue; + } } -#else +#endif + ret = 1; break; -#endif } -#endif // !__FreeBSD__ - int error = errno; - acl_free(acl); - errno = error; return ret; } +/** Check if an ACL of the given type is non-trivial. */ +static int bfs_check_acl_type(acl_t acl, acl_type_t type) { + if (type == ACL_TYPE_DEFAULT) { + // For directory default ACLs, any entries make them non-trivial + return bfs_check_posix1e_acl(acl, false); + } + +#if __FreeBSD__ + int trivial; + if (acl_is_trivial_np(acl, &trivial) < 0) { + return -1; + } else if (trivial) { + return 0; + } else { + return 1; + } +#endif + + return bfs_check_posix1e_acl(acl, true); +} + int bfs_check_acl(const struct BFTW *ftwbuf) { static const acl_type_t acl_types[] = { #if __APPLE__ @@ -205,18 +205,30 @@ int bfs_check_acl(const struct BFTW *ftwbuf) { const char *path = fake_at(ftwbuf); - int ret = -1; + int ret = -1, error = 0; for (size_t i = 0; i < n_acl_types && ret <= 0; ++i) { - if (acl_types[i] == ACL_TYPE_DEFAULT && ftwbuf->typeflag != BFTW_DIR) { + acl_type_t type = acl_types[i]; + + if (type == ACL_TYPE_DEFAULT && ftwbuf->typeflag != BFTW_DIR) { // ACL_TYPE_DEFAULT is supported only for directories, // otherwise acl_get_file() gives EACCESS continue; } - ret = bfs_check_acl_type(path, acl_types[i]); + acl_t acl = acl_get_file(path, type); + if (!acl) { + error = errno; + if (is_absence_error(error)) { + ret = 0; + } + continue; + } + + ret = bfs_check_acl_type(acl, type); + error = errno; + acl_free(acl); } - int error = errno; free_fake_at(ftwbuf, path); errno = error; return ret; @@ -337,8 +337,6 @@ struct parser_state { enum use_color use_color; /** Whether a -print action is implied. */ bool implicit_print; - /** Whether warnings are enabled (see -warn, -nowarn). */ - bool warn; /** Whether the expression has started. */ bool expr_started; /** Whether any non-option arguments have been encountered. */ @@ -704,7 +702,7 @@ static struct expr *parse_unary_flag(struct parser_state *state) { static struct expr *parse_option(struct parser_state *state, size_t argc) { const char *arg = *parser_advance(state, T_OPTION, argc); - if (state->warn && state->non_option_seen) { + if (state->non_option_seen) { parse_warning(state, "The '%s' option applies to the entire command line. For clarity, place\n" "it before any non-option arguments.\n\n", @@ -961,7 +959,7 @@ static struct expr *parse_optlevel(struct parser_state *state, int arg1, int arg return NULL; } - if (state->warn && *optlevel > 4) { + if (*optlevel > 4) { parse_warning(state, "%s is the same as -O4.\n\n", state->argv[0]); } @@ -1569,12 +1567,10 @@ static struct expr *parse_ls(struct parser_state *state, int arg1, int arg2) { * Parse -mount. */ static struct expr *parse_mount(struct parser_state *state, int arg1, int arg2) { - if (state->warn) { - parse_warning(state, - "In the future, %s will skip mount points entirely, unlike\n" - "-xdev, due to http://austingroupbugs.net/view.php?id=1133.\n\n", - state->argv[0]); - } + parse_warning(state, + "In the future, %s will skip mount points entirely, unlike\n" + "-xdev, due to http://austingroupbugs.net/view.php?id=1133.\n\n", + state->argv[0]); state->cmdline->flags |= BFTW_XDEV; state->mount_arg = state->argv[0]; @@ -1783,10 +1779,7 @@ static struct expr *parse_nohidden(struct parser_state *state, int arg1, int arg * Parse -noleaf. */ static struct expr *parse_noleaf(struct parser_state *state, int arg1, int arg2) { - if (state->warn) { - parse_warning(state, "bfs does not apply the optimization that %s inhibits.\n\n", state->argv[0]); - } - + parse_warning(state, "bfs does not apply the optimization that %s inhibits.\n\n", state->argv[0]); return parse_nullary_option(state); } @@ -2493,7 +2486,7 @@ fail: * Parse -(no)?warn. */ static struct expr *parse_warn(struct parser_state *state, int warn, int arg2) { - state->warn = warn; + state->cmdline->warn = warn; return parse_nullary_positional_option(state); } @@ -3310,23 +3303,21 @@ static struct expr *parse_whole_expr(struct parser_state *state) { } } - if (state->warn) { - if (state->mount_arg && state->xdev_arg) { - parse_warning(state, "%s is redundant in the presence of %s.\n\n", state->xdev_arg, state->mount_arg); - } + if (state->mount_arg && state->xdev_arg) { + parse_warning(state, "%s is redundant in the presence of %s.\n\n", state->xdev_arg, state->mount_arg); + } - if (state->depth_arg && state->prune_arg) { - parse_warning(state, "%s does not work in the presence of %s.\n", state->prune_arg, state->depth_arg); + if (state->cmdline->warn && state->depth_arg && state->prune_arg) { + parse_warning(state, "%s does not work in the presence of %s.\n", state->prune_arg, state->depth_arg); - if (state->interactive) { - fprintf(stderr, "Do you want to continue? "); - if (ynprompt() == 0) { - goto fail; - } + if (state->interactive) { + fprintf(stderr, "Do you want to continue? "); + if (ynprompt() == 0) { + goto fail; } - - fprintf(stderr, "\n"); } + + fprintf(stderr, "\n"); } return expr; @@ -3488,9 +3479,10 @@ struct cmdline *parse_cmdline(int argc, char *argv[]) { cmdline->strategy = BFTW_BFS; cmdline->optlevel = 3; cmdline->debug = 0; - cmdline->xargs_safe = false; cmdline->ignore_races = false; cmdline->unique = false; + cmdline->warn = false; + cmdline->xargs_safe = false; cmdline->expr = &expr_true; cmdline->nopen_files = 0; @@ -3544,6 +3536,10 @@ struct cmdline *parse_cmdline(int argc, char *argv[]) { bool stdout_tty = isatty(STDOUT_FILENO); bool stderr_tty = isatty(STDERR_FILENO); + if (!getenv("POSIXLY_CORRECT")) { + cmdline->warn = stdin_tty; + } + struct parser_state state = { .cmdline = cmdline, .argv = cmdline->argv + 1, @@ -3553,7 +3549,6 @@ struct cmdline *parse_cmdline(int argc, char *argv[]) { .interactive = stdin_tty && stderr_tty, .use_color = use_color, .implicit_print = true, - .warn = stdin_tty, .non_option_seen = false, .just_info = false, .last_arg = NULL, |